galaxy-commits
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
November 2013
- 1 participants
- 208 discussions
commit/galaxy-central: jmchilton: Re-fix tool API for uploads coming through nginx.
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/facb9f9d2ee4/
Changeset: facb9f9d2ee4
User: jmchilton
Date: 2013-11-19 04:26:29
Summary: Re-fix tool API for uploads coming through nginx.
Give tools.get_incoming_value a chance to mangle all keys and see if they appear in some other format. Thanks to @natefoo for detecting the problem, determining the source of the error, and describing the exact path through the code - i.e. doing all the …
[View More]work.
Affected #: 1 file
diff -r b0535b4864b4bf542e31af7acc027fcbb5a00a54 -r facb9f9d2ee4d614d21e4fc1a4a6d99f2668349a lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -2083,19 +2083,11 @@
if any_group_errors:
errors[input.name] = group_errors
else:
- if key not in incoming \
- and "__force_update__" + key not in incoming:
- # No new value provided, and we are only updating, so keep
- # the old value (which should already be in the state) and
- # preserve the old error message.
- pass
- else:
- incoming_value = get_incoming_value( incoming, key, None )
- value, error = check_param( trans, input, incoming_value, context, source=source )
- # If a callback was provided, allow it to process the value
- if error:
- errors[ input.name ] = error
- state[ input.name ] = value
+ incoming_value = get_incoming_value( incoming, key, None )
+ value, error = check_param( trans, input, incoming_value, context, source=source )
+ if error:
+ errors[ input.name ] = error
+ state[ input.name ] = value
return errors
def update_state( self, trans, inputs, state, incoming, source='html', prefix="", context=None,
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.
[View Less]
1
0
18 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b0535b4864b4/
Changeset: b0535b4864b4
User: guerler
Date: 2013-11-18 22:02:41
Summary: Toolshed: Fix grids
Affected #: 2 files
diff -r 32acc00ca229951afbd659281f57d93a47bcab06 -r b0535b4864b4bf542e31af7acc027fcbb5a00a54 templates/webapps/tool_shed/category/grid.mako
--- a/templates/webapps/tool_shed/category/grid.mako
+++ b/templates/webapps/tool_shed/category/grid.mako
@@ -6,6 +6,7 @@
## …
[View More]Render grid header.
## TODO: This is very similar to this directory's valid_grid.mako, so see if we can re-use this code in a better way.
<%def name="render_grid_header( grid, repo_grid, render_title=True)">
+ ${init()}
<div class="grid-header">
%if render_title:
${grid_title()}
diff -r 32acc00ca229951afbd659281f57d93a47bcab06 -r b0535b4864b4bf542e31af7acc027fcbb5a00a54 templates/webapps/tool_shed/category/valid_grid.mako
--- a/templates/webapps/tool_shed/category/valid_grid.mako
+++ b/templates/webapps/tool_shed/category/valid_grid.mako
@@ -5,6 +5,7 @@
## Render grid header.
<%def name="render_grid_header( grid, repo_grid, render_title=True)">
+ ${init()}
<div class="grid-header">
%if render_title:
${grid_title()}
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.
[View Less]
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fe8bb4e8e3a1/
Changeset: fe8bb4e8e3a1
User: jgoecks
Date: 2013-11-18 20:18:10
Summary: Trackster painters: rename y_center variable to y_start to reflect real position.
Affected #: 1 file
diff -r c0eb0f44b7fe80fdcb6590c4364312bbdcb286b0 -r fe8bb4e8e3a122930548c03c899fcdcaff52f484 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/…
[View More]viz/trackster/painters.js
@@ -466,7 +466,7 @@
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
draw_start = f_start,
draw_end = f_end,
- y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale + this.get_top_padding(width),
+ y_start = (mode === "Dense" ? 0 : (0 + slot)) * y_scale + this.get_top_padding(width),
thickness, y_start, thick_start = null, thick_end = null,
// TODO: is there any reason why block, label color cannot be set at the Painter level?
// For now, assume '.' === '+'
@@ -484,7 +484,7 @@
if (mode === "no_detail") {
// No details for feature, so only one way to display.
ctx.fillStyle = block_color;
- ctx.fillRect(f_start, y_center + 5, f_end - f_start, NO_DETAIL_FEATURE_HEIGHT);
+ ctx.fillRect(f_start, y_start + 5, f_end - f_start, NO_DETAIL_FEATURE_HEIGHT);
}
else { // Mode is either Squish or Pack:
// Feature details.
@@ -517,7 +517,7 @@
if (!feature_blocks) {
// If there are no blocks, treat the feature as one big exon.
ctx.fillStyle = block_color;
- ctx.fillRect(f_start, y_center + 1, f_end - f_start, thick_height);
+ ctx.fillRect(f_start, y_start + 1, f_end - f_start, thick_height);
// If strand is specified, draw arrows over feature
if ( feature_strand && full_height ) {
if (feature_strand === "+") {
@@ -525,7 +525,7 @@
} else if (feature_strand === "-") {
ctx.fillStyle = ctx.canvas.manager.get_pattern( 'left_strand_inv' );
}
- ctx.fillRect(f_start, y_center + 1, f_end - f_start, thick_height);
+ ctx.fillRect(f_start, y_start + 1, f_end - f_start, thick_height);
}
} else {
//
@@ -536,19 +536,19 @@
// a block, is visible.
//
- // Compute y axis center position and height
- var cur_y_center, cur_height;
+ // Compute y axis start position and height
+ var cur_y_start, cur_height;
if (mode === "Squish" || mode === "Dense") {
- cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_y_start = y_start + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
cur_height = 1;
}
else { // mode === "Pack"
if (feature_strand) {
- cur_y_center = y_center;
+ cur_y_start = y_start;
cur_height = thick_height;
}
else {
- cur_y_center += (SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_y_start += (SQUISH_FEATURE_HEIGHT/2) + 1;
cur_height = 1;
}
}
@@ -570,7 +570,7 @@
ctx.fillStyle = CONNECTOR_COLOR;
}
}
- ctx.fillRect(f_start, cur_y_center, f_end - f_start, cur_height);
+ ctx.fillRect(f_start, cur_y_start, f_end - f_start, cur_height);
}
// Draw blocks.
@@ -587,14 +587,14 @@
// Draw thin block.
ctx.fillStyle = block_color;
- ctx.fillRect(block_start, y_center + (thick_height-thin_height)/2 + 1, block_end - block_start, thin_height);
+ ctx.fillRect(block_start, y_start + (thick_height-thin_height)/2 + 1, block_end - block_start, thin_height);
// If block intersects with thick region, draw block as thick.
// - No thick is sometimes encoded as thick_start == thick_end, so don't draw in that case
if (thick_start !== undefined && feature_te > feature_ts && !(block_start > thick_end || block_end < thick_start) ) {
var block_thick_start = Math.max(block_start, thick_start),
block_thick_end = Math.min(block_end, thick_end);
- ctx.fillRect(block_thick_start, y_center + 1, block_thick_end - block_thick_start, thick_height);
+ ctx.fillRect(block_thick_start, y_start + 1, block_thick_end - block_thick_start, thick_height);
if ( feature_blocks.length === 1 && mode === "Pack") {
// Exactly one block means we have no introns, but do have a distinct "thick" region,
// draw arrows over it if in pack mode.
@@ -608,12 +608,12 @@
block_thick_start += 2;
block_thick_end -= 2;
}
- ctx.fillRect(block_thick_start, y_center + 1, block_thick_end - block_thick_start, thick_height);
+ ctx.fillRect(block_thick_start, y_start + 1, block_thick_end - block_thick_start, thick_height);
}
}
// Draw individual connectors if required
if ( this.draw_individual_connectors && last_block_start ) {
- this.draw_connector( ctx, last_block_start, last_block_end, block_start, block_end, y_center );
+ this.draw_connector( ctx, last_block_start, last_block_end, block_start, block_end, y_start );
}
last_block_start = block_start;
last_block_end = block_end;
@@ -632,8 +632,8 @@
new_height = Math.ceil(thick_height * hscale_factor),
ws_height = Math.round( (thick_height-new_height)/2 );
if (hscale_factor !== 1) {
- ctx.fillRect(f_start, cur_y_center + 1, f_end - f_start, ws_height);
- ctx.fillRect(f_start, cur_y_center + thick_height - ws_height + 1, f_end - f_start, ws_height);
+ ctx.fillRect(f_start, cur_y_start + 1, f_end - f_start, ws_height);
+ ctx.fillRect(f_start, cur_y_start + thick_height - ws_height + 1, f_end - f_start, ws_height);
}
}
}
@@ -647,11 +647,11 @@
// FIXME: assumption here that the entire view starts at 0
if (tile_low === 0 && f_start - ctx.measureText(feature_name).width < 0) {
ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_end + LABEL_SPACING, y_start + 8);
draw_end += ctx.measureText(feature_name).width + LABEL_SPACING;
} else {
ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start - LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_start - LABEL_SPACING, y_start + 8);
draw_start -= ctx.measureText(feature_name).width + LABEL_SPACING;
}
//ctx.fillStyle = block_color;
@@ -741,7 +741,7 @@
/**
* Draw a single read.
*/
- draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
+ draw_read: function(ctx, mode, w_scale, y_start, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
@@ -793,7 +793,7 @@
// Draw read base as rectangle.
ctx.fillStyle = block_color;
ctx.fillRect(s_start,
- y_center + (pack_mode ? 1 : 4 ),
+ y_start + (pack_mode ? 1 : 4 ),
s_end - s_start,
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
@@ -824,12 +824,12 @@
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
ctx.fillStyle = this.base_color_fn(seq[c]);
if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(seq[c], c_start, y_center + 9);
+ ctx.fillText(seq[c], c_start, y_start + 9);
}
// Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
else if (w_scale > 0.05) {
ctx.fillRect(c_start - gap,
- y_center + (pack_mode ? 1 : 4),
+ y_start + (pack_mode ? 1 : 4),
Math.max( 1, Math.round(w_scale) ),
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
@@ -843,12 +843,12 @@
break;
case "N": // Skipped bases.
ctx.fillStyle = CONNECTOR_COLOR;
- ctx.fillRect(s_start, y_center + 5, s_end - s_start, 1);
- //ctx.dashedLine(s_start + this.left_offset, y_center + 5, this.left_offset + s_end, y_center + 5);
+ ctx.fillRect(s_start, y_start + 5, s_end - s_start, 1);
+ //ctx.dashedLine(s_start + this.left_offset, y_start + 5, this.left_offset + s_end, y_start + 5);
base_offset += cig_len;
break;
case "D": // Deletion.
- paint_utils.draw_deletion(s_start, y_center, 1);
+ paint_utils.draw_deletion(s_start, y_start, 1);
base_offset += cig_len;
break;
case "P": // TODO: No good way to draw insertions/padding right now, so ignore
@@ -874,8 +874,8 @@
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Draw sequence container.
ctx.fillStyle = "yellow";
- ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9);
- draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_center + 4, 5]};
+ ctx.fillRect(x_center - gap, y_start - 9, s_end - s_start, 9);
+ draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_start + 4, 5]};
ctx.fillStyle = CONNECTOR_COLOR;
// Based on overlap b/t sequence and tile, get sequence to be drawn.
switch( compute_overlap( [seq_start, seq_start + cig_len], tile_region ) ) {
@@ -895,21 +895,21 @@
// Draw sequence.
for (var c = 0, str_len = seq.length; c < str_len; c++) {
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_center);
+ ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_start);
}
}
else {
// Draw block.
ctx.fillStyle = "yellow";
// TODO: This is a pretty hack-ish way to fill rectangle based on mode.
- ctx.fillRect(x_center, y_center + (this.mode !== "Dense" ? 2 : 5),
+ ctx.fillRect(x_center, y_start + (this.mode !== "Dense" ? 2 : 5),
s_end - s_start, (mode !== "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
}
}
else {
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Show insertions with a single number at the insertion point.
- draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } );
+ draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_start + 9] } );
}
else {
// TODO: probably can merge this case with code above.
@@ -955,7 +955,7 @@
// -0.5 to put element between bases.
f_start = Math.floor( Math.max(-0.5 * w_scale, (feature_start - tile_low - 0.5) * w_scale) ),
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
- y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale,
+ y_start = (mode === "Dense" ? 0 : (0 + slot)) * y_scale,
label_color = this.prefs.label_color;
@@ -966,7 +966,7 @@
// Draw left/forward read.
if (feature[4][1] >= tile_low && feature[4][0] <= tile_high && feature[4][2]) {
- this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], feature[4][4]);
+ this.draw_read(ctx, mode, w_scale, y_start, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], feature[4][4]);
}
else {
connector = false;
@@ -974,7 +974,7 @@
// Draw right/reverse read.
if (feature[5][1] >= tile_low && feature[5][0] <= tile_high && feature[5][2]) {
- this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], feature[5][4]);
+ this.draw_read(ctx, mode, w_scale, y_start, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], feature[5][4]);
}
else {
connector = false;
@@ -989,21 +989,21 @@
b2_start = Math.floor( Math.max(-0.5 * w_scale, (feature[5][0] - tile_low - 0.5) * w_scale) );
if (connector && b2_start > b1_end) {
ctx.fillStyle = CONNECTOR_COLOR;
- dashedLine(ctx, b1_end, y_center + 5, b2_start, y_center + 5);
+ dashedLine(ctx, b1_end, y_start + 5, b2_start, y_start + 5);
}
} else {
// Read is single.
- this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, feature[4], feature[5], feature[6]);
+ this.draw_read(ctx, mode, w_scale, y_start, tile_low, tile_high, feature_start, feature[4], feature[5], feature[6]);
}
if (mode === "Pack" && feature_start >= tile_low && feature_name !== ".") {
// Draw label.
ctx.fillStyle = this.prefs.label_color;
if (tile_low === 0 && f_start - ctx.measureText(feature_name).width < 0) {
ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_end + LABEL_SPACING, y_start + 8);
} else {
ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start - LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_start - LABEL_SPACING, y_start + 8);
}
}
@@ -1024,7 +1024,7 @@
/**
* Draw a single read from reference-based read sequence and cigar.
*/
- draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
+ draw_read: function(ctx, mode, w_scale, y_start, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
@@ -1063,7 +1063,7 @@
// Draw read base as rectangle.
ctx.fillStyle = block_color;
ctx.fillRect(s_start,
- y_center + (pack_mode ? 1 : 4 ),
+ y_start + (pack_mode ? 1 : 4 ),
s_end - s_start,
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
@@ -1130,12 +1130,12 @@
var c_start = Math.floor( Math.max(0, (start_pos + c - tile_low) * w_scale) );
ctx.fillStyle = this.base_color_fn(cur_seq[c]);
if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(cur_seq[c], c_start, y_center + 9);
+ ctx.fillText(cur_seq[c], c_start, y_start + 9);
}
// Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
else if (w_scale > 0.05) {
ctx.fillRect(c_start - gap,
- y_center + (pack_mode ? 1 : 4),
+ y_start + (pack_mode ? 1 : 4),
Math.max( 1, Math.round(w_scale) ),
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
@@ -1150,14 +1150,14 @@
break;
case "N": // Skipped bases.
ctx.fillStyle = CONNECTOR_COLOR;
- ctx.fillRect(s_start, y_center + 5, s_end - s_start, 1);
- //ctx.dashedLine(s_start + this.left_offset, y_center + 5, this.left_offset + s_end, y_center + 5);
+ ctx.fillRect(s_start, y_start + 5, s_end - s_start, 1);
+ //ctx.dashedLine(s_start + this.left_offset, y_start + 5, this.left_offset + s_end, y_start + 5);
// No change in seq_offset because sequence not used when skipping.
base_offset += cig_len;
break;
case "D": // Deletion.
ctx.fillStyle = "black";
- ctx.fillRect(s_start, y_center + 4, s_end - s_start, 3);
+ ctx.fillRect(s_start, y_start + 4, s_end - s_start, 3);
base_offset += cig_len;
break;
case "I": // Insertion.
@@ -1180,8 +1180,8 @@
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Draw sequence container.
ctx.fillStyle = "yellow";
- ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9);
- draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_center + 4, 5]};
+ ctx.fillRect(x_center - gap, y_start - 9, s_end - s_start, 9);
+ draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_start + 4, 5]};
ctx.fillStyle = CONNECTOR_COLOR;
// Based on overlap b/t sequence and tile, get sequence to be drawn.
switch( compute_overlap( [seq_start, seq_start + cig_len], tile_region ) ) {
@@ -1201,21 +1201,21 @@
// Draw sequence.
for (var c = 0, str_len = seq.length; c < str_len; c++) {
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_center);
+ ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_start);
}
}
else {
// Draw block.
ctx.fillStyle = "yellow";
// TODO: This is a pretty hack-ish way to fill rectangle based on mode.
- ctx.fillRect(x_center, y_center + (this.mode !== "Dense" ? 2 : 5),
+ ctx.fillRect(x_center, y_start + (this.mode !== "Dense" ? 2 : 5),
s_end - s_start, (mode !== "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
}
}
else {
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Show insertions with a single number at the insertion point.
- draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } );
+ draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_start + 9] } );
}
else {
// TODO: probably can merge this case with code above.
@@ -1275,7 +1275,7 @@
return Math.min( 128, Math.ceil( ( this.longest_feature_length / 2 ) * w_scale ) );
},
- draw_connector: function( ctx, block1_start, block1_end, block2_start, block2_end, y_center ) {
+ draw_connector: function( ctx, block1_start, block1_end, block2_start, block2_end, y_start ) {
// Arc drawing -- from closest endpoints
var x_center = ( block1_end + block2_start ) / 2,
radius = block2_start - x_center;
@@ -1283,7 +1283,7 @@
var angle1 = Math.PI, angle2 = 0;
if ( radius > 0 ) {
ctx.beginPath();
- ctx.arc( x_center, y_center, block2_start - x_center, Math.PI, 0 );
+ ctx.arc( x_center, y_start, block2_start - x_center, Math.PI, 0 );
ctx.stroke();
}
}
https://bitbucket.org/galaxy/galaxy-central/commits/32acc00ca229/
Changeset: 32acc00ca229
User: jgoecks
Date: 2013-11-18 21:57:15
Summary: Trackster: more improvements for drawing deletions in read and variant track.
Affected #: 1 file
diff -r fe8bb4e8e3a122930548c03c899fcdcaff52f484 -r 32acc00ca229951afbd659281f57d93a47bcab06 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -750,7 +750,7 @@
char_width_px = ctx.canvas.manager.char_width_px,
block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color),
pack_mode = (mode === 'Pack'),
- paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale);
+ paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale, mode);
// Keep list of items that need to be drawn on top of initial drawing layer.
var draw_last = [];
@@ -770,6 +770,10 @@
// -0.5 to offset sequence between bases.
s_start = Math.floor( Math.max(-0.5 * w_scale, (seq_start - tile_low - 0.5) * w_scale) ),
s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low - 0.5) * w_scale) );
+
+ if (!is_overlap([seq_start, seq_start + cig_len], tile_region)) {
+ continue;
+ }
// Make sure that read is drawn even if it too small to be rendered officially; in this case,
// read is drawn at 1px.
@@ -789,55 +793,54 @@
case "M": // Loose match with reference; can be match or mismatch.
case "=": // Strict match with reference.
case "X": // Strict mismatch with reference.
- if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- // Draw read base as rectangle.
- ctx.fillStyle = block_color;
- ctx.fillRect(s_start,
- y_start + (pack_mode ? 1 : 4 ),
- s_end - s_start,
- (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
+ // Draw read base as rectangle.
+ ctx.fillStyle = block_color;
+ ctx.fillRect(s_start,
+ y_start + (pack_mode ? 1 : 4 ),
+ s_end - s_start,
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
- // Draw sequence and/or variants.
- var seq = read_seq.slice(seq_offset, seq_offset + cig_len),
- ref_char,
- read_char;
- for (var c = 0, str_len = seq.length; c < str_len; c++) {
- // Draw base if it's on tile:
- if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
- // Get reference and read character.
- ref_char = (this.ref_seq ? this.ref_seq[seq_start - tile_low + c] : null);
- read_char = seq[c];
+ // Draw sequence and/or variants.
+ var seq = read_seq.slice(seq_offset, seq_offset + cig_len),
+ ref_char,
+ read_char;
+ for (var c = 0, str_len = seq.length; c < str_len; c++) {
+ // Draw base if it's on tile:
+ if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
+ // Get reference and read character.
+ ref_char = (this.ref_seq ? this.ref_seq[seq_start - tile_low + c] : null);
+ read_char = seq[c];
- // Draw base depending on (a) available reference data and (b) config options.
- if (
- // If there's reference data and (a) showing all (i.e. not showing
- // differences) or (b) if there is a variant.
- (ref_char &&
- (!this.prefs.show_differences ||
- (read_char.toLowerCase !== 'n' && (ref_char.toLowerCase() !== read_char.toLowerCase())))
- ) ||
- // If there's no reference data and showing all.
- (!ref_char && !this.prefs.show_differences)
- ) {
+ // Draw base depending on (a) available reference data and (b) config options.
+ if (
+ // If there's reference data and (a) showing all (i.e. not showing
+ // differences) or (b) if there is a variant.
+ (ref_char &&
+ (!this.prefs.show_differences ||
+ (read_char.toLowerCase !== 'n' && (ref_char.toLowerCase() !== read_char.toLowerCase())))
+ ) ||
+ // If there's no reference data and showing all.
+ (!ref_char && !this.prefs.show_differences)
+ ) {
- // Draw base.
- var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillStyle = this.base_color_fn(seq[c]);
- if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(seq[c], c_start, y_start + 9);
- }
- // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
- else if (w_scale > 0.05) {
- ctx.fillRect(c_start - gap,
- y_start + (pack_mode ? 1 : 4),
- Math.max( 1, Math.round(w_scale) ),
- (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
- }
+ // Draw base.
+ var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
+ ctx.fillStyle = this.base_color_fn(seq[c]);
+ if (pack_mode && w_scale > char_width_px) {
+ ctx.fillText(seq[c], c_start, y_start + 9);
}
+ // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
+ else if (w_scale > 0.05) {
+ ctx.fillRect(c_start - gap,
+ y_start + (pack_mode ? 1 : 4),
+ Math.max( 1, Math.round(w_scale) ),
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
+ }
+ }
- }
}
}
+
seq_offset += cig_len;
base_offset += cig_len;
break;
@@ -1033,6 +1036,7 @@
char_width_px = ctx.canvas.manager.char_width_px,
block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color),
pack_mode = (mode === 'Pack'),
+ paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale, mode),
drawing_blocks = [];
// Keep list of items that need to be drawn on top of initial drawing layer.
@@ -1074,11 +1078,15 @@
var cig = cigar[cig_id],
cig_op = "MIDNSHP=X"[ cig[0] ],
cig_len = cig[1];
-
+
var seq_start = feature_start + base_offset,
// -0.5 to offset sequence between bases.
s_start = Math.floor( Math.max(0, -0.5 * w_scale, (seq_start - tile_low - 0.5) * w_scale) ),
s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low - 0.5) * w_scale) );
+
+ if (!is_overlap([seq_start, seq_start + cig_len], tile_region)) {
+ continue;
+ }
// Make sure that read is drawn even if it too small to be rendered officially; in this case,
// read is drawn at 1px.
@@ -1100,45 +1108,43 @@
break;
case "=": // Match with reference.
case "X": // Mismatch with reference.
- if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- //
- // Draw sequence and/or variants.
- //
+ //
+ // Draw sequence and/or variants.
+ //
- // Get sequence to draw.
- var cur_seq = '';
- if (cig_op === 'X') {
- // Get sequence from read_seq.
- cur_seq = read_seq.slice(seq_offset, seq_offset + cig_len);
- }
- else if (this.ref_seq) { // && cig_op === '='
- // Use reference sequence.
- cur_seq = this.ref_seq.slice(
- // If read starts after tile start, slice at read start.
- Math.max(0, seq_start - tile_low),
- // If read ends before tile end, slice at read end.
- Math.min(seq_start - tile_low + cig_len, tile_high - tile_low)
- );
- }
+ // Get sequence to draw.
+ var cur_seq = '';
+ if (cig_op === 'X') {
+ // Get sequence from read_seq.
+ cur_seq = read_seq.slice(seq_offset, seq_offset + cig_len);
+ }
+ else if (this.ref_seq) { // && cig_op === '='
+ // Use reference sequence.
+ cur_seq = this.ref_seq.slice(
+ // If read starts after tile start, slice at read start.
+ Math.max(0, seq_start - tile_low),
+ // If read ends before tile end, slice at read end.
+ Math.min(seq_start - tile_low + cig_len, tile_high - tile_low)
+ );
+ }
- // Draw sequence. Because cur_seq starts and read/tile start, go to there to start writing.
- var start_pos = Math.max(seq_start, tile_low);
- for (var c = 0; c < cur_seq.length; c++) {
- // Draw base if showing all (i.e. not showing differences) or there is a mismatch.
- if (cur_seq && !this.prefs.show_differences || cig_op === 'X') {
- // Draw base.
- var c_start = Math.floor( Math.max(0, (start_pos + c - tile_low) * w_scale) );
- ctx.fillStyle = this.base_color_fn(cur_seq[c]);
- if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(cur_seq[c], c_start, y_start + 9);
- }
- // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
- else if (w_scale > 0.05) {
- ctx.fillRect(c_start - gap,
- y_start + (pack_mode ? 1 : 4),
- Math.max( 1, Math.round(w_scale) ),
- (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
- }
+ // Draw sequence. Because cur_seq starts and read/tile start, go to there to start writing.
+ var start_pos = Math.max(seq_start, tile_low);
+ for (var c = 0; c < cur_seq.length; c++) {
+ // Draw base if showing all (i.e. not showing differences) or there is a mismatch.
+ if (cur_seq && !this.prefs.show_differences || cig_op === 'X') {
+ // Draw base.
+ var c_start = Math.floor( Math.max(0, (start_pos + c - tile_low) * w_scale) );
+ ctx.fillStyle = this.base_color_fn(cur_seq[c]);
+ if (pack_mode && w_scale > char_width_px) {
+ ctx.fillText(cur_seq[c], c_start, y_start + 9);
+ }
+ // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
+ else if (w_scale > 0.05) {
+ ctx.fillRect(c_start - gap,
+ y_start + (pack_mode ? 1 : 4),
+ Math.max( 1, Math.round(w_scale) ),
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
}
}
@@ -1156,8 +1162,7 @@
base_offset += cig_len;
break;
case "D": // Deletion.
- ctx.fillStyle = "black";
- ctx.fillRect(s_start, y_start + 4, s_end - s_start, 3);
+ paint_utils.draw_deletion(s_start, y_start + (pack_mode ? 1 : 4), cig_len);
base_offset += cig_len;
break;
case "I": // Insertion.
@@ -1509,21 +1514,24 @@
/**
* Utilities for painting reads.
*/
-var ReadPainterUtils = function(ctx, row_height, char_width) {
+var ReadPainterUtils = function(ctx, row_height, px_per_base, mode) {
this.ctx = ctx;
this.row_height = row_height;
- this.char_width = char_width;
+ this.px_per_base = px_per_base;
+ this.draw_details = (mode === 'Pack' || mode === 'Auto') && (px_per_base >= ctx.canvas.manager.char_width_px);
+ this.delete_details_thickness = 0.2;
};
extend(ReadPainterUtils.prototype, {
/**
- * Draw deletion of base(s).
+ * Draw deletion of base(s).
+ * @param draw_detail if true, drawing in detail and deletion is drawn more subtly
*/
draw_deletion: function(x, y, len) {
this.ctx.fillStyle = "black";
- var thickness = Math.max( 0.25 * this.row_height, 1 );
+ var thickness = (this.draw_details ? this.delete_details_thickness : 1) * this.row_height;
y += 0.5 * ( this.row_height - thickness );
- this.ctx.fillRect( x, y + 4, len * this.char_width, thickness);
+ this.ctx.fillRect(x, y, len * this.px_per_base, thickness);
}
});
@@ -1631,7 +1639,7 @@
(this.mode === 'Squish' ? SQUISH_FEATURE_HEIGHT : PACK_FEATURE_HEIGHT)
),
draw_summary = true,
- paint_utils = new ReadPainterUtils(ctx, row_height, base_px),
+ paint_utils = new ReadPainterUtils(ctx, row_height, w_scale, this.mode),
j;
// If there's a single sample, update drawing variables.
@@ -1738,15 +1746,15 @@
if (variant.type === 'snp') {
var snp = variant.value;
ctx.fillStyle = this.base_color_fn(snp);
- if (this.mode === 'Squish' || w_scale < ctx.canvas.manager.char_width_px) {
- ctx.fillRect(draw_x_start, draw_y_start + 1, base_px, feature_height);
+ if (paint_utils.draw_details) {
+ ctx.fillText(snp, char_x_start, draw_y_start + row_height);
}
else {
- ctx.fillText(snp, char_x_start, draw_y_start + row_height);
+ ctx.fillRect(draw_x_start, draw_y_start + 1, base_px, feature_height);
}
}
else if (variant.type === 'deletion') {
- paint_utils.draw_deletion(draw_x_start + base_px * variant.start, draw_y_start, variant.len);
+ paint_utils.draw_deletion(draw_x_start + base_px * variant.start, draw_y_start + 1, variant.len);
}
else {
// TODO: handle insertions.
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.
[View Less]
1
0
commit/galaxy-central: jgoecks: Trackster: add support for detecting and drawing deletions in VCF datasets. Create shared read painter utils that are used by multiple painters.
by commits-noreply@bitbucket.org 18 Nov '13
by commits-noreply@bitbucket.org 18 Nov '13
18 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c0eb0f44b7fe/
Changeset: c0eb0f44b7fe
User: jgoecks
Date: 2013-11-18 19:55:43
Summary: Trackster: add support for detecting and drawing deletions in VCF datasets. Create shared read painter utils that are used by multiple painters.
Affected #: 1 file
diff -r a0120448a28eeda50a0476a6d46da74ad3afa484 -r c0eb0f44b7fe80fdcb6590c4364312bbdcb286b0 static/scripts/viz/trackster/painters.js
--- a/…
[View More]static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -749,7 +749,8 @@
gap = Math.round(w_scale/2),
char_width_px = ctx.canvas.manager.char_width_px,
block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color),
- pack_mode = (mode === 'Pack');
+ pack_mode = (mode === 'Pack'),
+ paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale);
// Keep list of items that need to be drawn on top of initial drawing layer.
var draw_last = [];
@@ -847,8 +848,7 @@
base_offset += cig_len;
break;
case "D": // Deletion.
- ctx.fillStyle = "black";
- ctx.fillRect(s_start, y_center + 4, s_end - s_start, 3);
+ paint_utils.draw_deletion(s_start, y_center, 1);
base_offset += cig_len;
break;
case "P": // TODO: No good way to draw insertions/padding right now, so ignore
@@ -1507,6 +1507,27 @@
};
/**
+ * Utilities for painting reads.
+ */
+var ReadPainterUtils = function(ctx, row_height, char_width) {
+ this.ctx = ctx;
+ this.row_height = row_height;
+ this.char_width = char_width;
+};
+
+extend(ReadPainterUtils.prototype, {
+ /**
+ * Draw deletion of base(s).
+ */
+ draw_deletion: function(x, y, len) {
+ this.ctx.fillStyle = "black";
+ var thickness = Math.max( 0.25 * this.row_height, 1 );
+ y += 0.5 * ( this.row_height - thickness );
+ this.ctx.fillRect( x, y + 4, len * this.char_width, thickness);
+ }
+});
+
+/**
* Paints variant data onto canvas.
*/
var VariantPainter = function(data, view_start, view_end, prefs, mode, base_color_fn) {
@@ -1556,6 +1577,34 @@
draw: function(ctx, width, height, w_scale) {
ctx.save();
+ // Functions for detection insertions (TODO) and deletions.
+
+ /** Returns dictionary of information about a deletion; returns null if there no deletion.
+ * Dict attributes:
+ * -start: where the deletion starts relative to reference start
+ * -len: how long the deletion is
+ */
+ var get_deletion_info = function(ref, alt) {
+ var ref_len = ref.length,
+ alt_len = alt.length,
+ start = 0,
+ len = 1,
+ is_delete = false;
+ if (alt === '-') {
+ is_delete = true;
+ len = ref.length;
+ }
+ else if (ref.indexOf(alt) === 0 && ref_len > alt_len) {
+ is_delete = true;
+ len = ref_len = alt_len;
+ start += alt_len;
+ }
+
+ return ( is_delete ? { start: start, len: len } : null );
+ };
+
+
+ // Draw.
var locus_data,
pos,
id,
@@ -1582,6 +1631,7 @@
(this.mode === 'Squish' ? SQUISH_FEATURE_HEIGHT : PACK_FEATURE_HEIGHT)
),
draw_summary = true,
+ paint_utils = new ReadPainterUtils(ctx, row_height, base_px),
j;
// If there's a single sample, update drawing variables.
@@ -1605,10 +1655,31 @@
// Get locus data.
locus_data = this.data[i];
pos = locus_data[1];
- alt = locus_data[4].split(',');
+ ref = locus_data[3];
+ alt = [ locus_data[4].split(',') ];
sample_gts = locus_data[7].split(',');
allele_counts = locus_data.slice(8);
+ // Process alterate values to derive information about each alt.
+ alt = _.map(_.flatten(alt), function(a) {
+ var type,
+ alt_info = {},
+ delete_info = get_deletion_info(ref, a);
+ if (delete_info) {
+ type = 'deletion';
+ _.extend(alt_info, delete_info);
+ }
+ // TODO: test for insertion.
+ else { // SNP.
+ type = 'snp';
+ }
+
+ return _.extend(alt_info, {
+ type: type,
+ value: a,
+ });
+ });
+
// Only draw locus data if it's in viewing region.
if (pos < this.view_start || pos > this.view_end) {
continue;
@@ -1627,7 +1698,7 @@
draw_y_start = this.prefs.summary_height;
// Draw allele fractions onto summary.
for (j = 0; j < alt.length; j++) {
- ctx.fillStyle = this.base_color_fn(alt[j]);
+ ctx.fillStyle = ( alt[j].type === 'deletion' ? 'black' : this.base_color_fn(alt[j].value) );
allele_frac = allele_counts / sample_gts.length;
draw_height = Math.ceil(this.prefs.summary_height * allele_frac);
ctx.fillRect(draw_x_start, draw_y_start - draw_height, base_px, draw_height);
@@ -1664,12 +1735,21 @@
// If there's a variant, draw it.
if (variant) {
- ctx.fillStyle = this.base_color_fn(variant);
- if (this.mode === 'Squish' || w_scale < ctx.canvas.manager.char_width_px) {
- ctx.fillRect(draw_x_start, draw_y_start + 1, base_px, feature_height);
+ if (variant.type === 'snp') {
+ var snp = variant.value;
+ ctx.fillStyle = this.base_color_fn(snp);
+ if (this.mode === 'Squish' || w_scale < ctx.canvas.manager.char_width_px) {
+ ctx.fillRect(draw_x_start, draw_y_start + 1, base_px, feature_height);
+ }
+ else {
+ ctx.fillText(snp, char_x_start, draw_y_start + row_height);
+ }
+ }
+ else if (variant.type === 'deletion') {
+ paint_utils.draw_deletion(draw_x_start + base_px * variant.start, draw_y_start, variant.len);
}
else {
- ctx.fillText(variant, char_x_start, draw_y_start + row_height);
+ // TODO: handle insertions.
}
}
}
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.
[View Less]
1
0
commit/galaxy-central: carlfeberhard: History panel: ensure tooltip deletion on hda view removal, add class selectors for primary action buttons; pack scripts
by commits-noreply@bitbucket.org 18 Nov '13
by commits-noreply@bitbucket.org 18 Nov '13
18 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a0120448a28e/
Changeset: a0120448a28e
User: carlfeberhard
Date: 2013-11-18 18:39:52
Summary: History panel: ensure tooltip deletion on hda view removal, add class selectors for primary action buttons; pack scripts
Affected #: 4 files
diff -r 3ebc0f5c4486cc5c207882bcea819018d23b2bf4 -r a0120448a28eeda50a0476a6d46da74ad3afa484 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/…
[View More]dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -149,8 +149,8 @@
}
var displayBtnData = {
- icon_class : 'display',
- target : 'galaxy_main'
+ target : 'galaxy_main',
+ classes : 'dataset-display'
};
// show a disabled display if the data's been purged
diff -r 3ebc0f5c4486cc5c207882bcea819018d23b2bf4 -r a0120448a28eeda50a0476a6d46da74ad3afa484 static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -69,7 +69,7 @@
title : _l( 'Edit Attributes' ),
href : this.urls.edit,
target : 'galaxy_main',
- icon_class : 'edit'
+ classes : 'dataset-edit'
};
// disable if purged or deleted and explain why in the tooltip
@@ -102,21 +102,18 @@
}
var self = this,
- delete_url = self.urls[ 'delete' ],
deleteBtnData = {
title : _l( 'Delete' ),
- href : delete_url,
- icon_class : 'delete',
- onclick : function() {
+ classes : 'dataset-delete',
+ onclick : function() {
// ...bler... tooltips being left behind in DOM (hover out never called on deletion)
- self.$el.find( '.menu-button.delete' ).trigger( 'mouseout' );
+ self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
self.model[ 'delete' ]();
}
};
if( this.model.get( 'deleted' ) || this.model.get( 'purged' ) ){
deleteBtnData = {
title : _l( 'Dataset is already deleted' ),
- icon_class : 'delete',
disabled : true
};
}
diff -r 3ebc0f5c4486cc5c207882bcea819018d23b2bf4 -r a0120448a28eeda50a0476a6d46da74ad3afa484 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.expanded=c.expanded||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(e){e=(e===undefined)?(true):(e);var c=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var d=$(a.templates.skeleton(this.model.toJSON()));d.find(".dataset-primary-actions").append(this._render_titleButtons());d.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(d);if(e){$(c).queue(function(f){this.$el.fadeOut(c.fxSpeed,f)})}$(c).queue(function(f){this.$el.empty().attr("class",c.className).addClass("state-"+c.model.get("state")).append(d.children());f()});if(e){$(c).queue(function(f){this.$el.fadeIn(c.fxSpeed,f)})}$(c).queue(function(f){this.trigger("rendered",c);if(this.model.inReadyState()){this.trigger("rendered:ready",c)}f()});return this},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var d={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){d.disabled=true;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.disabled=true;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.onclick=function(){Galaxy.frame.add({title:"Data Viewer: "+c.model.get("name"),type:"url",target:"galaxy_main",content:c.urls.display})}}}d.faIcon="fa-eye";return faIconButton(d)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var d=this.urls,e=this.model.get("meta_files");if(_.isEmpty(e)){return $(['<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var f="dataset-"+this.model.get("id")+"-popup",c=['<div popupmenu="'+f+'">','<a href="'+d.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(e,function(g){return['<a class="action-button" href="',d.meta_download+g.file_type,'">',_l("Download")," ",g.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+f+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(c)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",faIcon:"fa-info-circle"})},_render_body:function(){var d=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),c=this["_render_body_"+this.model.get("state")];if(_.isFunction(c)){d=c.call(this)}if(this.expanded){d.show()}return d},_render_stateBodyHelper:function(c,f){f=f||[];var d=this,e=$(a.templates.body(_.extend(this.model.toJSON(),{body:c})));e.find(".dataset-actions .left").append(_.map(f,function(g){return g.call(d)}));return e},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var c=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){c="<div>"+this.model.get("misc_blurb")+"</div>"+c}return this._render_stateBodyHelper(c,this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton]))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var c=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),d=this._render_body_ok();d.prepend(c);return d},_render_body_ok:function(){var c=this,e=$(a.templates.body(this.model.toJSON())),d=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);e.find(".dataset-actions .left").append(_.map(d,function(f){return f.call(c)}));if(this.model.isDeletedOrPurged()){return e}return e},events:{"click .dataset-title-bar":"toggleBodyVisibility"},toggleBodyVisibility:function(d,c){var e=this.$el.find(".dataset-body");c=(c===undefined)?(!e.is(":visible")):(c);if(c){this.expandBody()}else{this.collapseBody()}},expandBody:function(){var c=this;function d(){c.render(false).$el.children(".dataset-body").slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.$el.children(".dataset-body").slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={skeleton:Handlebars.templates["template-hda-skeleton"],body:Handlebars.templates["template-hda-body"]};return{HDABaseView:a}});
\ No newline at end of file
+define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.expanded=c.expanded||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(e){e=(e===undefined)?(true):(e);var c=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var d=$(a.templates.skeleton(this.model.toJSON()));d.find(".dataset-primary-actions").append(this._render_titleButtons());d.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(d);if(e){$(c).queue(function(f){this.$el.fadeOut(c.fxSpeed,f)})}$(c).queue(function(f){this.$el.empty().attr("class",c.className).addClass("state-"+c.model.get("state")).append(d.children());f()});if(e){$(c).queue(function(f){this.$el.fadeIn(c.fxSpeed,f)})}$(c).queue(function(f){this.trigger("rendered",c);if(this.model.inReadyState()){this.trigger("rendered:ready",c)}f()});return this},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var d={target:"galaxy_main",classes:"dataset-display"};if(this.model.get("purged")){d.disabled=true;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.disabled=true;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.onclick=function(){Galaxy.frame.add({title:"Data Viewer: "+c.model.get("name"),type:"url",target:"galaxy_main",content:c.urls.display})}}}d.faIcon="fa-eye";return faIconButton(d)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var d=this.urls,e=this.model.get("meta_files");if(_.isEmpty(e)){return $(['<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var f="dataset-"+this.model.get("id")+"-popup",c=['<div popupmenu="'+f+'">','<a href="'+d.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(e,function(g){return['<a class="action-button" href="',d.meta_download+g.file_type,'">',_l("Download")," ",g.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+f+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(c)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",faIcon:"fa-info-circle"})},_render_body:function(){var d=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),c=this["_render_body_"+this.model.get("state")];if(_.isFunction(c)){d=c.call(this)}if(this.expanded){d.show()}return d},_render_stateBodyHelper:function(c,f){f=f||[];var d=this,e=$(a.templates.body(_.extend(this.model.toJSON(),{body:c})));e.find(".dataset-actions .left").append(_.map(f,function(g){return g.call(d)}));return e},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var c=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){c="<div>"+this.model.get("misc_blurb")+"</div>"+c}return this._render_stateBodyHelper(c,this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton]))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var c=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),d=this._render_body_ok();d.prepend(c);return d},_render_body_ok:function(){var c=this,e=$(a.templates.body(this.model.toJSON())),d=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);e.find(".dataset-actions .left").append(_.map(d,function(f){return f.call(c)}));if(this.model.isDeletedOrPurged()){return e}return e},events:{"click .dataset-title-bar":"toggleBodyVisibility"},toggleBodyVisibility:function(d,c){var e=this.$el.find(".dataset-body");c=(c===undefined)?(!e.is(":visible")):(c);if(c){this.expandBody()}else{this.collapseBody()}},expandBody:function(){var c=this;function d(){c.render(false).$el.children(".dataset-body").slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.$el.children(".dataset-body").slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={skeleton:Handlebars.templates["template-hda-skeleton"],body:Handlebars.templates["template-hda-body"]};return{HDABaseView:a}});
\ No newline at end of file
diff -r 3ebc0f5c4486cc5c207882bcea819018d23b2bf4 -r a0120448a28eeda50a0476a6d46da74ad3afa484 static/scripts/packed/mvc/dataset/hda-edit.js
--- a/static/scripts/packed/mvc/dataset/hda-edit.js
+++ b/static/scripts/packed/mvc/dataset/hda-edit.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_render_titleButtons:function(){return a.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(g||i){h.disabled=true;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){h.disabled=true;h.title=_l("This dataset must finish uploading before it can be edited")}}h.faIcon="fa-pencil";return faIconButton(h)},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var g=this,h=g.urls["delete"],i={title:_l("Delete"),href:h,icon_class:"delete",onclick:function(){g.$el.find(".menu-button.delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){i={title:_l("Dataset is already deleted"),icon_class:"delete",disabled:true}}i.faIcon="fa-times";return faIconButton(i)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var g=this.model.get("visualizations");if((!this.model.hasData())||(_.isEmpty(g))){return null}if(_.isObject(g[0])){return this._render_visualizationsFrameworkButton(g)}if(!this.urls.visualization){return null}var i=this.model.get("dbkey"),l=this.urls.visualization,j={},m={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(i){m.dbkey=i}var h=faIconButton({title:_l("Visualize"),href:this.urls.visualization,faIcon:"fa-bar-chart-o"});function k(n){switch(n){case"trackster":return b(l,m,i);case"scatterplot":return e(l,m);default:return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:l+"/"+n+"?"+$.param(m)})}}}if(g.length===1){h.attr("title",g[0]);h.click(k(g[0]))}else{_.each(g,function(o){var n=o.charAt(0).toUpperCase()+o.slice(1);j[_l(n)]=k(o)});make_popupmenu(h,j)}return h},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){return null}var i=faIconButton({title:_l("Visualize"),faIcon:"fa-bar-chart-o"});i.addClass("visualize-icon");if(_.keys(g).length===1){i.attr("title",_.keys(g)[0]);i.attr("href",_.values(g)[0])}else{var j=[];_.each(g,function(k){j.push(k)});var h=new PopupMenu(i,j)}return i},_render_body_failed_metadata:function(){var h=$("<a/>").attr({href:this.urls.edit,target:"galaxy_main"}).text(_l("set it manually or retry auto-detection")),g=$("<span/>").text(". "+_l("You may be able to")+" ").append(h),i=a.HDABaseView.prototype._render_body_failed_metadata.call(this);i.find(".warningmessagesmall strong").append(g);return i},_render_body_error:function(){var g=a.HDABaseView.prototype._render_body_error.call(this);g.find(".dataset-actions .left").prepend(this._render_errButton());return g},_render_body_ok:function(){var g=a.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return g}this.makeDbkeyEditLink(g);if(this.hasUser){g.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(g);this._renderAnnotation(g)}return g},_renderTags:function(g){this.tagsEditor=new TagsEditor({model:this.model,el:g.find(".tags-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(g.find(".dataset-actions .right"))})},_renderAnnotation:function(g){this.annotationEditor=new AnnotationEditor({model:this.model,el:g.find(".annotation-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(g.find(".dataset-actions .right"))})},makeDbkeyEditLink:function(g){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){g.find(".dataset-dbkey .value").replaceWith($('<a target="galaxy_main">?</a>').attr("href",this.urls.edit))}},events:{"click .dataset-title-bar":"toggleBodyVisibility","click .dataset-undelete":function(g){this.model.undelete();return false},"click .dataset-unhide":function(g){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"},confirmPurge:function c(g){this.model.purge();return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});function e(g,h){action=function(){Galaxy.frame.add({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(h),target:"galaxy_main",scratchbook:true});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame.add({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i),scratchbook:true})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame.add({title:"Trackster",type:"url",content:m,scratchbook:true})}}})}});return false}}return{HDAEditView:f}});
\ No newline at end of file
+define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_render_titleButtons:function(){return a.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",classes:"dataset-edit"};if(g||i){h.disabled=true;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){h.disabled=true;h.title=_l("This dataset must finish uploading before it can be edited")}}h.faIcon="fa-pencil";return faIconButton(h)},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var g=this,h={title:_l("Delete"),classes:"dataset-delete",onclick:function(){g.$el.find(".icon-btn.dataset-delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){h={title:_l("Dataset is already deleted"),disabled:true}}h.faIcon="fa-times";return faIconButton(h)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var g=this.model.get("visualizations");if((!this.model.hasData())||(_.isEmpty(g))){return null}if(_.isObject(g[0])){return this._render_visualizationsFrameworkButton(g)}if(!this.urls.visualization){return null}var i=this.model.get("dbkey"),l=this.urls.visualization,j={},m={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(i){m.dbkey=i}var h=faIconButton({title:_l("Visualize"),href:this.urls.visualization,faIcon:"fa-bar-chart-o"});function k(n){switch(n){case"trackster":return b(l,m,i);case"scatterplot":return e(l,m);default:return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:l+"/"+n+"?"+$.param(m)})}}}if(g.length===1){h.attr("title",g[0]);h.click(k(g[0]))}else{_.each(g,function(o){var n=o.charAt(0).toUpperCase()+o.slice(1);j[_l(n)]=k(o)});make_popupmenu(h,j)}return h},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){return null}var i=faIconButton({title:_l("Visualize"),faIcon:"fa-bar-chart-o"});i.addClass("visualize-icon");if(_.keys(g).length===1){i.attr("title",_.keys(g)[0]);i.attr("href",_.values(g)[0])}else{var j=[];_.each(g,function(k){j.push(k)});var h=new PopupMenu(i,j)}return i},_render_body_failed_metadata:function(){var h=$("<a/>").attr({href:this.urls.edit,target:"galaxy_main"}).text(_l("set it manually or retry auto-detection")),g=$("<span/>").text(". "+_l("You may be able to")+" ").append(h),i=a.HDABaseView.prototype._render_body_failed_metadata.call(this);i.find(".warningmessagesmall strong").append(g);return i},_render_body_error:function(){var g=a.HDABaseView.prototype._render_body_error.call(this);g.find(".dataset-actions .left").prepend(this._render_errButton());return g},_render_body_ok:function(){var g=a.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return g}this.makeDbkeyEditLink(g);if(this.hasUser){g.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(g);this._renderAnnotation(g)}return g},_renderTags:function(g){this.tagsEditor=new TagsEditor({model:this.model,el:g.find(".tags-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(g.find(".dataset-actions .right"))})},_renderAnnotation:function(g){this.annotationEditor=new AnnotationEditor({model:this.model,el:g.find(".annotation-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(g.find(".dataset-actions .right"))})},makeDbkeyEditLink:function(g){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){g.find(".dataset-dbkey .value").replaceWith($('<a target="galaxy_main">?</a>').attr("href",this.urls.edit))}},events:{"click .dataset-title-bar":"toggleBodyVisibility","click .dataset-undelete":function(g){this.model.undelete();return false},"click .dataset-unhide":function(g){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"},confirmPurge:function c(g){this.model.purge();return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});function e(g,h){action=function(){Galaxy.frame.add({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(h),target:"galaxy_main",scratchbook:true});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame.add({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i),scratchbook:true})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame.add({title:"Trackster",type:"url",content:m,scratchbook:true})}}})}});return false}}return{HDAEditView:f}});
\ 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.
[View Less]
1
0
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/40d2e69e89a3/
Changeset: 40d2e69e89a3
User: jmchilton
Date: 2013-11-18 07:51:54
Summary: Redo fix from 8b65e61 so it works when no Twill clicking at all occurs (e.g. all default params used).
Affected #: 1 file
diff -r 64cb656e95b2f40ac5f6f1f26fc484ce88a11ad1 -r 40d2e69e89a3210d1760851ea8563e1e344a0c3f test/base/twilltestcase.py
--- a/test/base/twilltestcase.py
+++ b/test/base/…
[View More]twilltestcase.py
@@ -1356,11 +1356,11 @@
tool_id = tool_id.replace(" ", "+")
"""Runs the tool 'tool_id' and passes it the key/values from the *kwd"""
self.visit_url( "%s/tool_runner/index?tool_id=%s" % (self.url, tool_id) )
+ # Must click somewhere in tool_form, to disambiguate what form
+ # is being targetted.
+ tc.browser.clicked( tc.browser.get_form( 'tool_form' ), None )
if repeat_name is not None:
repeat_button = '%s_add' % repeat_name
- # Must click somewhere in tool_form, to disambiguate what form
- # is being targetted.
- tc.browser.clicked( tc.browser.get_form( 'tool_form' ), None )
# Submit the "repeat" form button to add an input)
tc.submit( repeat_button )
tc.find( 'runtool_btn' )
https://bitbucket.org/galaxy/galaxy-central/commits/59a0ca3d48c0/
Changeset: 59a0ca3d48c0
User: jmchilton
Date: 2013-11-18 07:51:54
Summary: PEP-8 fixes related to tool test parsing.
Affected #: 2 files
diff -r 40d2e69e89a3210d1760851ea8563e1e344a0c3f -r 59a0ca3d48c019c017d85fc780239837b2e5453d lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1574,7 +1574,7 @@
# history, but we'll keep it unique per set of tests
composite_data_names_counter = 0
for i, test_elem in enumerate( tests_elem.findall( 'test' ) ):
- name = test_elem.get( 'name', 'Test-%d' % (i+1) )
+ name = test_elem.get( 'name', 'Test-%d' % (i + 1) )
maxseconds = int( test_elem.get( 'maxseconds', '120' ) )
test = ToolTestBuilder( self, name, maxseconds )
try:
@@ -1625,6 +1625,7 @@
raise Exception( "Test output does not have a 'name'" )
assert_elem = output_elem.find("assert_contents")
assert_list = None
+
# Trying to keep testing patch as localized as
# possible, this function should be relocated
# somewhere more conventional.
@@ -1636,7 +1637,7 @@
converted_children = []
for child_elem in child_elems:
converted_children.append( convert_elem(child_elem) )
- return {"tag" : tag, "attributes" : attributes, "children" : converted_children}
+ return {"tag": tag, "attributes": attributes, "children": converted_children}
if assert_elem is not None:
assert_list = []
for assert_child in list(assert_elem):
@@ -1677,6 +1678,7 @@
test.error = True
test.exception = e
self.tests.append( test )
+
def parse_input_page( self, input_elem, enctypes ):
"""
Parse a page of inputs. This basically just calls 'parse_input_elem',
diff -r 40d2e69e89a3210d1760851ea8563e1e344a0c3f -r 59a0ca3d48c019c017d85fc780239837b2e5453d lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -1,20 +1,18 @@
-import new, sys
import os.path
-import galaxy.util
-import parameters
from parameters import basic
from parameters import grouping
-from elementtree.ElementTree import XML
import logging
log = logging.getLogger( __name__ )
+
class ToolTestBuilder( object ):
"""
Encapsulates information about a tool test, and allows creation of a
dynamic TestCase class (the unittest framework is very class oriented,
doing dynamic tests in this way allows better integration)
"""
+
def __init__( self, tool, name, maxseconds ):
self.tool = tool
self.name = name
@@ -24,6 +22,7 @@
self.outputs = []
self.error = False
self.exception = None
+
def add_param( self, name, value, extra ):
try:
if name not in self.tool.inputs:
@@ -43,8 +42,10 @@
except Exception, e:
log.debug( "Error for tool %s: could not add test parameter %s. %s" % ( self.tool.id, name, e ) )
self.inputs.append( ( name, value, extra ) )
+
def add_output( self, name, file, extra ):
self.outputs.append( ( name, file, extra ) )
+
def __expand_grouping_for_data_input( self, name, value, extra, grouping_name, grouping_value ):
# Currently handles grouping.Conditional and grouping.Repeat
if isinstance( grouping_value, grouping.Conditional ):
@@ -93,20 +94,21 @@
if found_parameter:
return True, new_value
return False, value
+
def __add_uploaded_dataset( self, name, value, extra, input_parameter ):
if value is None:
assert input_parameter.optional, '%s is not optional. You must provide a valid filename.' % name
return value
if ( value, extra ) not in self.required_files:
- self.required_files.append( ( value, extra ) ) #these files will be uploaded
+ self.required_files.append( ( value, extra ) ) # these files will be uploaded
name_change = [ att for att in extra.get( 'edit_attributes', [] ) if att.get( 'type' ) == 'name' ]
if name_change:
- name_change = name_change[-1].get( 'value' ) #only the last name change really matters
- value = name_change #change value for select to renamed uploaded file for e.g. composite dataset
+ name_change = name_change[-1].get( 'value' ) # only the last name change really matters
+ value = name_change # change value for select to renamed uploaded file for e.g. composite dataset
else:
for end in [ '.zip', '.gz' ]:
if value.endswith( end ):
value = value[ :-len( end ) ]
break
- value = os.path.basename( value ) #if uploading a file in a path other than root of test-data
+ value = os.path.basename( value ) # if uploading a file in a path other than root of test-data
return value
https://bitbucket.org/galaxy/galaxy-central/commits/d9482b09663e/
Changeset: d9482b09663e
User: jmchilton
Date: 2013-11-18 07:51:54
Summary: Refactor tool test parsing logic out of Tool and into ToolTestBuilder.
Affected #: 2 files
diff -r 59a0ca3d48c019c017d85fc780239837b2e5453d -r d9482b09663e0cb7cc74adc284267fee1dc498eb lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1570,113 +1570,8 @@
store in `self.tests`.
"""
self.tests = []
- # Composite datasets need a unique name: each test occurs in a fresh
- # history, but we'll keep it unique per set of tests
- composite_data_names_counter = 0
for i, test_elem in enumerate( tests_elem.findall( 'test' ) ):
- name = test_elem.get( 'name', 'Test-%d' % (i + 1) )
- maxseconds = int( test_elem.get( 'maxseconds', '120' ) )
- test = ToolTestBuilder( self, name, maxseconds )
- try:
- for param_elem in test_elem.findall( "param" ):
- attrib = dict( param_elem.attrib )
- if 'values' in attrib:
- value = attrib[ 'values' ].split( ',' )
- elif 'value' in attrib:
- value = attrib['value']
- else:
- value = None
- attrib['children'] = list( param_elem.getchildren() )
- if attrib['children']:
- # At this time, we can assume having children only
- # occurs on DataToolParameter test items but this could
- # change and would cause the below parsing to change
- # based upon differences in children items
- attrib['metadata'] = []
- attrib['composite_data'] = []
- attrib['edit_attributes'] = []
- # Composite datasets need to be renamed uniquely
- composite_data_name = None
- for child in attrib['children']:
- if child.tag == 'composite_data':
- attrib['composite_data'].append( child )
- if composite_data_name is None:
- # Generate a unique name; each test uses a
- # fresh history
- composite_data_name = '_COMPOSITE_RENAMED_%i_' \
- % ( composite_data_names_counter )
- composite_data_names_counter += 1
- elif child.tag == 'metadata':
- attrib['metadata'].append( child )
- elif child.tag == 'metadata':
- attrib['metadata'].append( child )
- elif child.tag == 'edit_attributes':
- attrib['edit_attributes'].append( child )
- if composite_data_name:
- # Composite datasets need implicit renaming;
- # inserted at front of list so explicit declarations
- # take precedence
- attrib['edit_attributes'].insert( 0, { 'type': 'name', 'value': composite_data_name } )
- test.add_param( attrib.pop( 'name' ), value, attrib )
- for output_elem in test_elem.findall( "output" ):
- attrib = dict( output_elem.attrib )
- name = attrib.pop( 'name', None )
- if name is None:
- raise Exception( "Test output does not have a 'name'" )
- assert_elem = output_elem.find("assert_contents")
- assert_list = None
-
- # Trying to keep testing patch as localized as
- # possible, this function should be relocated
- # somewhere more conventional.
- def convert_elem(elem):
- """ Converts and XML element to a dictionary format, used by assertion checking code. """
- tag = elem.tag
- attributes = dict( elem.attrib )
- child_elems = list( elem.getchildren() )
- converted_children = []
- for child_elem in child_elems:
- converted_children.append( convert_elem(child_elem) )
- return {"tag": tag, "attributes": attributes, "children": converted_children}
- if assert_elem is not None:
- assert_list = []
- for assert_child in list(assert_elem):
- assert_list.append(convert_elem(assert_child))
- file = attrib.pop( 'file', None )
- # File no longer required if an list of assertions was present.
- if assert_list is None and file is None:
- raise Exception( "Test output does not have a 'file'")
- attributes = {}
- # Method of comparison
- attributes['compare'] = attrib.pop( 'compare', 'diff' ).lower()
- # Number of lines to allow to vary in logs (for dates, etc)
- attributes['lines_diff'] = int( attrib.pop( 'lines_diff', '0' ) )
- # Allow a file size to vary if sim_size compare
- attributes['delta'] = int( attrib.pop( 'delta', '10000' ) )
- attributes['sort'] = string_as_bool( attrib.pop( 'sort', False ) )
- attributes['extra_files'] = []
- attributes['assert_list'] = assert_list
- if 'ftype' in attrib:
- attributes['ftype'] = attrib['ftype']
- for extra in output_elem.findall( 'extra_files' ):
- # File or directory, when directory, compare basename
- # by basename
- extra_type = extra.get( 'type', 'file' )
- extra_name = extra.get( 'name', None )
- assert extra_type == 'directory' or extra_name is not None, \
- 'extra_files type (%s) requires a name attribute' % extra_type
- extra_value = extra.get( 'value', None )
- assert extra_value is not None, 'extra_files requires a value attribute'
- extra_attributes = {}
- extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower()
- extra_attributes['delta'] = extra.get( 'delta', '0' )
- extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) )
- extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) )
- attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) )
- test.add_output( name, file, attributes )
- except Exception, e:
- test.error = True
- test.exception = e
+ test = ToolTestBuilder( self, test_elem, i )
self.tests.append( test )
def parse_input_page( self, input_elem, enctypes ):
diff -r 59a0ca3d48c019c017d85fc780239837b2e5453d -r d9482b09663e0cb7cc74adc284267fee1dc498eb lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -1,6 +1,7 @@
import os.path
from parameters import basic
from parameters import grouping
+from galaxy.util import string_as_bool
import logging
log = logging.getLogger( __name__ )
@@ -13,7 +14,10 @@
doing dynamic tests in this way allows better integration)
"""
- def __init__( self, tool, name, maxseconds ):
+ def __init__( self, tool, test_elem, i ):
+ name = test_elem.get( 'name', 'Test-%d' % (i + 1) )
+ maxseconds = int( test_elem.get( 'maxseconds', '120' ) )
+
self.tool = tool
self.name = name
self.maxseconds = maxseconds
@@ -23,6 +27,114 @@
self.error = False
self.exception = None
+ self.__parse_elem( test_elem, i )
+
+ def __parse_elem( self, test_elem, i ):
+ # Composite datasets need a unique name: each test occurs in a fresh
+ # history, but we'll keep it unique per set of tests - use i (test #)
+ # and composite_data_names_counter (instance per test #)
+ composite_data_names_counter = 0
+ try:
+ for param_elem in test_elem.findall( "param" ):
+ attrib = dict( param_elem.attrib )
+ if 'values' in attrib:
+ value = attrib[ 'values' ].split( ',' )
+ elif 'value' in attrib:
+ value = attrib['value']
+ else:
+ value = None
+ attrib['children'] = list( param_elem.getchildren() )
+ if attrib['children']:
+ # At this time, we can assume having children only
+ # occurs on DataToolParameter test items but this could
+ # change and would cause the below parsing to change
+ # based upon differences in children items
+ attrib['metadata'] = []
+ attrib['composite_data'] = []
+ attrib['edit_attributes'] = []
+ # Composite datasets need to be renamed uniquely
+ composite_data_name = None
+ for child in attrib['children']:
+ if child.tag == 'composite_data':
+ attrib['composite_data'].append( child )
+ if composite_data_name is None:
+ # Generate a unique name; each test uses a
+ # fresh history
+ composite_data_name = '_COMPOSITE_RENAMED_t%i_d%i' \
+ % ( i, composite_data_names_counter )
+ composite_data_names_counter += 1
+ elif child.tag == 'metadata':
+ attrib['metadata'].append( child )
+ elif child.tag == 'metadata':
+ attrib['metadata'].append( child )
+ elif child.tag == 'edit_attributes':
+ attrib['edit_attributes'].append( child )
+ if composite_data_name:
+ # Composite datasets need implicit renaming;
+ # inserted at front of list so explicit declarations
+ # take precedence
+ attrib['edit_attributes'].insert( 0, { 'type': 'name', 'value': composite_data_name } )
+ self.add_param( attrib.pop( 'name' ), value, attrib )
+ for output_elem in test_elem.findall( "output" ):
+ attrib = dict( output_elem.attrib )
+ name = attrib.pop( 'name', None )
+ if name is None:
+ raise Exception( "Test output does not have a 'name'" )
+ assert_elem = output_elem.find("assert_contents")
+ assert_list = None
+
+ # Trying to keep testing patch as localized as
+ # possible, this function should be relocated
+ # somewhere more conventional.
+ def convert_elem(elem):
+ """ Converts and XML element to a dictionary format, used by assertion checking code. """
+ tag = elem.tag
+ attributes = dict( elem.attrib )
+ child_elems = list( elem.getchildren() )
+ converted_children = []
+ for child_elem in child_elems:
+ converted_children.append( convert_elem(child_elem) )
+ return {"tag": tag, "attributes": attributes, "children": converted_children}
+ if assert_elem is not None:
+ assert_list = []
+ for assert_child in list(assert_elem):
+ assert_list.append(convert_elem(assert_child))
+ file = attrib.pop( 'file', None )
+ # File no longer required if an list of assertions was present.
+ if assert_list is None and file is None:
+ raise Exception( "Test output does not have a 'file'")
+ attributes = {}
+ # Method of comparison
+ attributes['compare'] = attrib.pop( 'compare', 'diff' ).lower()
+ # Number of lines to allow to vary in logs (for dates, etc)
+ attributes['lines_diff'] = int( attrib.pop( 'lines_diff', '0' ) )
+ # Allow a file size to vary if sim_size compare
+ attributes['delta'] = int( attrib.pop( 'delta', '10000' ) )
+ attributes['sort'] = string_as_bool( attrib.pop( 'sort', False ) )
+ attributes['extra_files'] = []
+ attributes['assert_list'] = assert_list
+ if 'ftype' in attrib:
+ attributes['ftype'] = attrib['ftype']
+ for extra in output_elem.findall( 'extra_files' ):
+ # File or directory, when directory, compare basename
+ # by basename
+ extra_type = extra.get( 'type', 'file' )
+ extra_name = extra.get( 'name', None )
+ assert extra_type == 'directory' or extra_name is not None, \
+ 'extra_files type (%s) requires a name attribute' % extra_type
+ extra_value = extra.get( 'value', None )
+ assert extra_value is not None, 'extra_files requires a value attribute'
+ extra_attributes = {}
+ extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower()
+ extra_attributes['delta'] = extra.get( 'delta', '0' )
+ extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) )
+ extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) )
+ attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) )
+ self.add_output( name, file, attributes )
+ except Exception, e:
+ self.error = True
+ self.exception = e
+
def add_param( self, name, value, extra ):
try:
if name not in self.tool.inputs:
https://bitbucket.org/galaxy/galaxy-central/commits/b1a929a53f22/
Changeset: b1a929a53f22
User: jmchilton
Date: 2013-11-18 07:51:54
Summary: Make formerly public methods in ToolTestBuilder private now that it does its own construction.
Affected #: 1 file
diff -r d9482b09663e0cb7cc74adc284267fee1dc498eb -r b1a929a53f22ed8e59e8ca4d75d3ab230344cd46 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -74,7 +74,7 @@
# inserted at front of list so explicit declarations
# take precedence
attrib['edit_attributes'].insert( 0, { 'type': 'name', 'value': composite_data_name } )
- self.add_param( attrib.pop( 'name' ), value, attrib )
+ self.__add_param( attrib.pop( 'name' ), value, attrib )
for output_elem in test_elem.findall( "output" ):
attrib = dict( output_elem.attrib )
name = attrib.pop( 'name', None )
@@ -130,12 +130,12 @@
extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) )
extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) )
attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) )
- self.add_output( name, file, attributes )
+ self.__add_output( name, file, attributes )
except Exception, e:
self.error = True
self.exception = e
- def add_param( self, name, value, extra ):
+ def __add_param( self, name, value, extra ):
try:
if name not in self.tool.inputs:
found_parameter = False
@@ -155,7 +155,7 @@
log.debug( "Error for tool %s: could not add test parameter %s. %s" % ( self.tool.id, name, e ) )
self.inputs.append( ( name, value, extra ) )
- def add_output( self, name, file, extra ):
+ def __add_output( self, name, file, extra ):
self.outputs.append( ( name, file, extra ) )
def __expand_grouping_for_data_input( self, name, value, extra, grouping_name, grouping_value ):
https://bitbucket.org/galaxy/galaxy-central/commits/3ebc0f5c4486/
Changeset: 3ebc0f5c4486
User: jmchilton
Date: 2013-11-18 07:51:54
Summary: Refactor smaller methods out of tool output test parsing.
Affected #: 1 file
diff -r b1a929a53f22ed8e59e8ca4d75d3ab230344cd46 -r 3ebc0f5c4486cc5c207882bcea819018d23b2bf4 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -80,29 +80,12 @@
name = attrib.pop( 'name', None )
if name is None:
raise Exception( "Test output does not have a 'name'" )
- assert_elem = output_elem.find("assert_contents")
- assert_list = None
- # Trying to keep testing patch as localized as
- # possible, this function should be relocated
- # somewhere more conventional.
- def convert_elem(elem):
- """ Converts and XML element to a dictionary format, used by assertion checking code. """
- tag = elem.tag
- attributes = dict( elem.attrib )
- child_elems = list( elem.getchildren() )
- converted_children = []
- for child_elem in child_elems:
- converted_children.append( convert_elem(child_elem) )
- return {"tag": tag, "attributes": attributes, "children": converted_children}
- if assert_elem is not None:
- assert_list = []
- for assert_child in list(assert_elem):
- assert_list.append(convert_elem(assert_child))
+ assert_list = self.__parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
# File no longer required if an list of assertions was present.
- if assert_list is None and file is None:
- raise Exception( "Test output does not have a 'file'")
+ if not assert_list and file is None:
+ raise Exception( "Test output does not have a 'file' to compare with or list of assertions to check")
attributes = {}
# Method of comparison
attributes['compare'] = attrib.pop( 'compare', 'diff' ).lower()
@@ -116,25 +99,51 @@
if 'ftype' in attrib:
attributes['ftype'] = attrib['ftype']
for extra in output_elem.findall( 'extra_files' ):
- # File or directory, when directory, compare basename
- # by basename
- extra_type = extra.get( 'type', 'file' )
- extra_name = extra.get( 'name', None )
- assert extra_type == 'directory' or extra_name is not None, \
- 'extra_files type (%s) requires a name attribute' % extra_type
- extra_value = extra.get( 'value', None )
- assert extra_value is not None, 'extra_files requires a value attribute'
- extra_attributes = {}
- extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower()
- extra_attributes['delta'] = extra.get( 'delta', '0' )
- extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) )
- extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) )
- attributes['extra_files'].append( ( extra_type, extra_value, extra_name, extra_attributes ) )
+ attributes['extra_files'].append( self.__parse_extra_files_elem( extra ) )
self.__add_output( name, file, attributes )
except Exception, e:
self.error = True
self.exception = e
+ def __parse_assert_list( self, output_elem ):
+ assert_elem = output_elem.find("assert_contents")
+ assert_list = None
+
+ # Trying to keep testing patch as localized as
+ # possible, this function should be relocated
+ # somewhere more conventional.
+ def convert_elem(elem):
+ """ Converts and XML element to a dictionary format, used by assertion checking code. """
+ tag = elem.tag
+ attributes = dict( elem.attrib )
+ child_elems = list( elem.getchildren() )
+ converted_children = []
+ for child_elem in child_elems:
+ converted_children.append( convert_elem(child_elem) )
+ return {"tag": tag, "attributes": attributes, "children": converted_children}
+ if assert_elem is not None:
+ assert_list = []
+ for assert_child in list(assert_elem):
+ assert_list.append(convert_elem(assert_child))
+
+ return assert_list
+
+ def __parse_extra_files_elem( self, extra ):
+ # File or directory, when directory, compare basename
+ # by basename
+ extra_type = extra.get( 'type', 'file' )
+ extra_name = extra.get( 'name', None )
+ assert extra_type == 'directory' or extra_name is not None, \
+ 'extra_files type (%s) requires a name attribute' % extra_type
+ extra_value = extra.get( 'value', None )
+ assert extra_value is not None, 'extra_files requires a value attribute'
+ extra_attributes = {}
+ extra_attributes['compare'] = extra.get( 'compare', 'diff' ).lower()
+ extra_attributes['delta'] = extra.get( 'delta', '0' )
+ extra_attributes['lines_diff'] = int( extra.get( 'lines_diff', '0' ) )
+ extra_attributes['sort'] = string_as_bool( extra.get( 'sort', False ) )
+ return extra_type, extra_value, extra_name, extra_attributes
+
def __add_param( self, name, value, extra ):
try:
if name not in self.tool.inputs:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
[View Less]
1
0
commit/galaxy-central: guerler: Grids: Remove console output
by commits-noreply@bitbucket.org 17 Nov '13
by commits-noreply@bitbucket.org 17 Nov '13
17 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/64cb656e95b2/
Changeset: 64cb656e95b2
User: guerler
Date: 2013-11-17 11:37:57
Summary: Grids: Remove console output
Affected #: 1 file
diff -r 567266a9f5ae16af522a62c0aaf3c47cab39ffc2 -r 64cb656e95b2f40ac5f6f1f26fc484ce88a11ad1 templates/webapps/galaxy/tracks/history_select_grid.mako
--- a/templates/webapps/galaxy/tracks/history_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/…
[View More]history_select_grid.mako
@@ -15,7 +15,6 @@
$(document).ready(function() {
$(".addtracktab, #grid-table a").off();
$(".addtracktab, #grid-table a").click(function() {
- console.log($(this).attr("href"));
var modal_body = $(".modal-body");
if (modal_body.length !== 0) {
modal_body.load($(this).attr("href"));
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.
[View Less]
1
0
commit/galaxy-central: guerler: Grids: Remove console output
by commits-noreply@bitbucket.org 17 Nov '13
by commits-noreply@bitbucket.org 17 Nov '13
17 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/567266a9f5ae/
Changeset: 567266a9f5ae
User: guerler
Date: 2013-11-17 11:16:54
Summary: Grids: Remove console output
Affected #: 1 file
diff -r f1cef709a9e5631cae2126ffff71dbba64611f87 -r 567266a9f5ae16af522a62c0aaf3c47cab39ffc2 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -222,7 +222,7 @@
$(function() {
## get configuration
…
[View More] var grid_config = ${ h.to_json_string( self.grid_config ) };
- console.log(grid_config);
+
// Create grid.
var grid = new Grid(grid_config);
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.
[View Less]
1
0
commit/galaxy-central: guerler: Grids: Reduce mako templating to json generation, introduce GridsView, bug fixes
by commits-noreply@bitbucket.org 17 Nov '13
by commits-noreply@bitbucket.org 17 Nov '13
17 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f1cef709a9e5/
Changeset: f1cef709a9e5
User: guerler
Date: 2013-11-17 11:08:25
Summary: Grids: Reduce mako templating to json generation, introduce GridsView, bug fixes
iG: changed templates/webapps/galaxy/tracks/history_select_grid.mako
Affected #: 14 files
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 lib/galaxy/web/framework/helpers/grids.…
[View More]py
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -321,7 +321,7 @@
class GridColumn( object ):
def __init__( self, label, key=None, model_class=None, method=None, format=None, \
- link=None, attach_popup=False, visible=True, ncells=1, nowrap=False, \
+ link=None, attach_popup=False, visible=True, nowrap=False, \
# Valid values for filterable are ['standard', 'advanced', None]
filterable=None, sortable=True, label_id_prefix=None ):
"""Create a grid column."""
@@ -334,7 +334,6 @@
self.nowrap = nowrap
self.attach_popup = attach_popup
self.visible = visible
- self.ncells = ncells
self.filterable = filterable
# Column must have a key to be sortable.
self.sortable = ( self.key is not None and sortable )
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -100,7 +100,7 @@
grids.TextColumn( "Name", key="name",
# Link name to dataset's history.
link=( lambda item: iff( item.history.deleted, None, dict( operation="switch", id=item.id ) ) ), filterable="advanced", attach_popup=True ),
- HistoryColumn( "History", key="history",
+ HistoryColumn( "History", key="history", sortable=False,
link=( lambda item: iff( item.history.deleted, None, dict( operation="switch_history", id=item.id ) ) ) ),
grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid" ),
StatusColumn( "Status", key="deleted", attach_popup=False ),
@@ -113,11 +113,12 @@
key="free-text-search", visible=False, filterable="standard" )
)
operations = [
- grids.GridOperation( "Copy to current history", condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "Copy to current history", condition=( lambda item: not item.deleted ), async_compatible=True ),
]
standard_filters = []
default_filter = dict( name="All", deleted="False", tags="All" )
preserve_state = False
+ use_async = True
use_paging = True
num_rows_per_page = 50
def build_initial_query( self, trans, **kwargs ):
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -30,16 +30,13 @@
def get_value( self, trans, grid, history ):
state_count_dict = self.get_hda_state_counts( trans, history )
- rval = []
+ rval = ''
for state in ( 'ok', 'running', 'queued', 'error' ):
count = state_count_dict.get( state, 0 )
if count:
- rval.append( '<div class="count-box state-color-%s">%s</div>' % ( state, count ) )
- else:
- rval.append( '' )
+ rval += '<div class="count-box state-color-%s">%s</div>' % (state, count)
return rval
-
class HistoryListNameColumn( NameColumn ):
def get_link( self, trans, grid, history ):
link = None
@@ -72,7 +69,7 @@
default_sort_key = "-update_time"
columns = [
HistoryListNameColumn( "Name", key="name", attach_popup=True, filterable="advanced" ),
- DatasetsByStateColumn( "Datasets", key="datasets_by_state", ncells=4, sortable=False ),
+ DatasetsByStateColumn( "Datasets", key="datasets_by_state", sortable=False ),
grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryTagAssociation, \
filterable="advanced", grid_name="HistoryListGrid" ),
grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False ),
@@ -118,13 +115,11 @@
# Custom column types
class DatasetsByStateColumn( grids.GridColumn ):
def get_value( self, trans, grid, history ):
- rval = []
+ rval = ''
for state in ( 'ok', 'running', 'queued', 'error' ):
total = sum( 1 for d in history.active_datasets if d.state == state )
if total:
- rval.append( '<div class="count-box state-color-%s">%s</div>' % ( state, total ) )
- else:
- rval.append( '' )
+ rval += '<div class="count-box state-color-%s">%s</div>' % ( state, total )
return rval
class SharedByColumn( grids.GridColumn ):
@@ -138,7 +133,7 @@
default_filter = {}
columns = [
grids.GridColumn( "Name", key="name", attach_popup=True ), # link=( lambda item: dict( operation="View", id=item.id ) ), attach_popup=True ),
- DatasetsByStateColumn( "Datasets", ncells=4, sortable=False ),
+ DatasetsByStateColumn( "Datasets", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
SharedByColumn( "Shared by", key="user_id" )
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -147,11 +147,11 @@
# Grid definition.
title = "Insert into visualization"
template = "/tracks/add_to_viz.mako"
- async_template = "/page/select_items_grid_async.mako"
model_class = model.Visualization
default_sort_key = "-update_time"
use_async = True
use_paging = False
+ show_item_checkboxes = True
columns = [
grids.TextColumn( "Title", key="title", model_class=model.Visualization, filterable="standard" ),
grids.TextColumn( "Dbkey", key="dbkey", model_class=model.Visualization ),
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 static/scripts/galaxy.grids.js
--- a/static/scripts/galaxy.grids.js
+++ b/static/scripts/galaxy.grids.js
@@ -119,433 +119,456 @@
}
// Add filter arguments to data, placing "f-" in front of all arguments.
- // FIXME: when underscore updated, use pairs function().
var self = this;
- _.each(_.keys(self.attributes.filters), function(k) {
- url_data['f-' + k] = self.attributes.filters[k];
+ _.each(_.pairs(self.attributes.filters), function(k) {
+ url_data['f-' + k[0]] = k[1];
});
return url_data;
}
});
-//
-// Code to handle grid operations: filtering, sorting, paging, and operations.
-//
+// grid view
+var GridView = Backbone.View.extend({
-// Initialize grid controls
-function init_grid_controls() {
- // Initialize submit image elements.
- $('.submit-image').each( function() {
- // On mousedown, add class to simulate click.
- $(this).mousedown( function() {
- $(this).addClass('gray-background');
+ // model
+ grid: null,
+
+ // Initialize
+ initialize: function(grid)
+ {
+ this.grid = grid;
+ this.init_grid_elements();
+ this.init_grid_controls();
+
+ // Initialize text filters to select text on click and use normal font when user is typing.
+ $('input[type=text]').each(function() {
+ $(this).click(function() { $(this).select(); } )
+ .keyup(function () { $(this).css("font-style", "normal"); });
+ });
+ },
+
+ // Initialize grid controls
+ init_grid_controls: function() {
+ // Initialize submit image elements.
+ $('.submit-image').each( function() {
+ // On mousedown, add class to simulate click.
+ $(this).mousedown( function() {
+ $(this).addClass('gray-background');
+ });
+
+ // On mouseup, add class to simulate click.
+ $(this).mouseup( function() {
+ $(this).removeClass('gray-background');
+ });
});
- // On mouseup, add class to simulate click.
- $(this).mouseup( function() {
- $(this).removeClass('gray-background');
+ // link
+ var self = this;
+
+ // Initialize sort links.
+ $('.sort-link').each( function() {
+ $(this).click( function() {
+ self.set_sort_condition( $(this).attr('sort_key') );
+ return false;
+ });
});
- });
+
+ // Initialize page links.
+ $('.page-link > a').each( function() {
+ $(this).click( function() {
+ self.set_page( $(this).attr('page_num') );
+ return false;
+ });
+ });
+
+ // Initialize categorical filters.
+ $('.categorical-filter > a').each( function() {
+ $(this).click( function() {
+ self.set_categorical_filter( $(this).attr('filter_key'), $(this).attr('filter_val') );
+ return false;
+ });
+ });
+
+ // Initialize text filters.
+ $('.text-filter-form').each( function() {
+ $(this).submit( function() {
+ var column_key = $(this).attr('column_key');
+ var text_input_obj = $('#input-' + column_key + '-filter');
+ var text_input = text_input_obj.val();
+ text_input_obj.val('');
+ self.add_filter_condition(column_key, text_input, true);
+ return false;
+ });
+ });
+
+ // Initialize autocomplete for text inputs in search UI.
+ var t = $("#input-tags-filter");
+ if (t.length) {
+ t.autocomplete(this.grid.history_tag_autocomplete_url,
+ { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
+ }
+
+ var t2 = $("#input-name-filter");
+ if (t2.length) {
+ t2.autocomplete(this.grid.history_name_autocomplete_url,
+ { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
+ }
+
+ // Initialize standard, advanced search toggles.
+ $('.advanced-search-toggle').each( function() {
+ $(this).click( function() {
+ $("#standard-search").slideToggle('fast');
+ $('#advanced-search').slideToggle('fast');
+ return false;
+ });
+ });
+ },
+
+ // Initialize grid elements.
+ init_grid_elements : function() {
- // Initialize sort links.
- $('.sort-link').each( function() {
- $(this).click( function() {
- set_sort_condition( $(this).attr('sort_key') );
- return false;
+ // Initialize grid selection checkboxes.
+ $(".grid").each( function() {
+ var checkboxes = $(this).find("input.grid-row-select-checkbox");
+ var check_count = $(this).find("span.grid-selected-count");
+ var update_checked = function() {
+ check_count.text( $(checkboxes).filter(":checked").length );
+ };
+
+ $(checkboxes).each( function() {
+ $(this).change(update_checked);
+ });
+ update_checked();
});
- });
-
- // Initialize page links.
- $('.page-link > a').each( function() {
- $(this).click( function() {
- set_page( $(this).attr('page_num') );
- return false;
+
+ // Initialize item labels.
+ var self = this;
+ $(".label").each( function() {
+ // If href has an operation in it, do operation when clicked. Otherwise do nothing.
+ var href = $(this).attr('href');
+ if ( href !== undefined && href.indexOf('operation=') != -1 ) {
+ $(this).click( function() {
+ self.do_operation_from_href( $(this).attr('href') );
+ return false;
+ });
+ }
});
- });
+
+ // Initialize ratings.
+ if ($('.community_rating_star').length !== 0)
+ $('.community_rating_star').rating({});
+
+ // Initialize item menu operations.
+ make_popup_menus();
+ },
- // Initialize categorical filters.
- $('.categorical-filter > a').each( function() {
- $(this).click( function() {
- set_categorical_filter( $(this).attr('filter_key'), $(this).attr('filter_val') );
+ // Go back to page one; this is useful when a filter is applied.
+ go_page_one: function () {
+ // Need to go back to page 1 if not showing all.
+ var cur_page = this.grid.get('cur_page');
+ if (cur_page !== null && cur_page !== undefined && cur_page !== 'all') {
+ this.grid.set('cur_page', 1);
+ }
+ },
+
+ // Add a condition to the grid filter; this adds the condition and refreshes the grid.
+ add_filter_condition: function (name, value, append) {
+ // Do nothing is value is empty.
+ if (value === "") {
return false;
+ }
+
+ // Add condition to grid.
+ this.grid.add_filter(name, value, append);
+
+ // Add button that displays filter and provides a button to delete it.
+ var t = $("<span>" + value + "<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");
+ t.addClass('text-filter-val');
+ var self = this;
+ t.click(function() {
+ // Remove filter condition.
+ self.grid.remove_filter(name, value);
+
+ // Remove visible element.
+ $(this).remove();
+
+ self.go_page_one();
+ self.update_grid();
});
- });
-
- // Initialize text filters.
- $('.text-filter-form').each( function() {
- $(this).submit( function() {
- var column_key = $(this).attr('column_key');
- var text_input_obj = $('#input-' + column_key + '-filter');
- var text_input = text_input_obj.val();
- text_input_obj.val('');
- add_filter_condition(column_key, text_input, true);
+
+ var container = $('#' + name + "-filtering-criteria");
+ container.append(t);
+
+ this.go_page_one();
+ this.update_grid();
+ },
+
+ // Set sort condition for grid.
+ set_sort_condition: function (col_key) {
+ // Set new sort condition. New sort is col_key if sorting new column; if reversing sort on
+ // currently sorted column, sort is reversed.
+ var cur_sort = this.grid.get('sort_key');
+ var new_sort = col_key;
+ if (cur_sort.indexOf(col_key) !== -1) {
+ // Reverse sort.
+ if (cur_sort.substring(0,1) !== '-') {
+ new_sort = '-' + col_key;
+ } else {
+ // Sort reversed by using just col_key.
+ }
+ }
+
+ // Remove sort arrows elements.
+ $('.sort-arrow').remove();
+
+ // Add sort arrow element to new sort column.
+ var sort_arrow = (new_sort.substring(0,1) == '-') ? "↑" : "↓";
+ var t = $("<span>" + sort_arrow + "</span>").addClass('sort-arrow');
+ var th = $("#" + col_key + '-header');
+ th.append(t);
+
+ // Update grid.
+ this.grid.set('sort_key', new_sort);
+ this.go_page_one();
+ this.update_grid();
+ },
+
+ // Set new value for categorical filter.
+ set_categorical_filter: function (name, new_value) {
+ // Update filter hyperlinks to reflect new filter value.
+ var category_filter = this.grid.get('categorical_filters')[name],
+ cur_value = this.grid.get('filters')[name];
+ var self = this;
+ $("." + name + "-filter").each( function() {
+ var text = $.trim( $(this).text() );
+ var filter = category_filter[text];
+ var filter_value = filter[name];
+ if (filter_value == new_value) {
+ // Remove filter link since grid will be using this filter. It is assumed that
+ // this element has a single child, a hyperlink/anchor with text.
+ $(this).empty();
+ $(this).addClass("current-filter");
+ $(this).append(text);
+ } else if (filter_value == cur_value) {
+ // Add hyperlink for this filter since grid will no longer be using this filter. It is assumed that
+ // this element has a single child, a hyperlink/anchor.
+ $(this).empty();
+ var t = $("<a href='#'>" + text + "</a>");
+ t.click(function() {
+ self.set_categorical_filter( name, filter_value );
+ });
+ $(this).removeClass("current-filter");
+ $(this).append(t);
+ }
+ });
+
+ // Update grid.
+ this.grid.add_filter(name, new_value);
+ this.go_page_one();
+ this.update_grid();
+ },
+
+ // Set page to view.
+ set_page: function (new_page) {
+ // Update page hyperlink to reflect new page.
+ var self = this;
+ $(".page-link").each( function() {
+ var id = $(this).attr('id'),
+ page_num = parseInt( id.split("-")[2], 10 ), // Id has form 'page-link-<page_num>
+ cur_page = self.grid.get('cur_page'),
+ text;
+ if (page_num === new_page) {
+ // Remove link to page since grid will be on this page. It is assumed that
+ // this element has a single child, a hyperlink/anchor with text.
+ text = $(this).children().text();
+ $(this).empty();
+ $(this).addClass("inactive-link");
+ $(this).text(text);
+ }
+ else if (page_num === cur_page) {
+ // Add hyperlink to this page since grid will no longer be on this page. It is assumed that
+ // this element has a single child, a hyperlink/anchor.
+ text = $(this).text();
+ $(this).empty();
+ $(this).removeClass("inactive-link");
+ var t = $("<a href='#'>" + text + "</a>");
+ t.click(function() {
+ set_page(page_num);
+ });
+ $(this).append(t);
+ }
+ });
+
+ var maintain_page_links = true;
+ if (new_page === "all") {
+ this.grid.set('cur_page', new_page);
+ maintain_page_links = false;
+ } else {
+ this.grid.set('cur_page', parseInt(new_page, 10));
+ }
+ this.update_grid(maintain_page_links);
+ },
+
+ // Perform a grid operation.
+ do_operation: function (operation, item_ids) {
+ operation = operation.toLowerCase();
+
+ // Update grid.
+ this.grid.set({
+ operation: operation,
+ item_ids: item_ids
+ });
+
+ // Do operation. If operation cannot be performed asynchronously, redirect to location.
+ if (this.grid.can_async_op(operation)) {
+ this.update_grid(true);
+ }
+ else {
+ this.go_to_URL();
+ }
+ },
+
+ // Perform a hyperlink click that initiates an operation. If there is no operation, ignore click.
+ do_operation_from_href: function (href) {
+ // Get operation, id in hyperlink's href.
+ var href_parts = href.split("?");
+ if (href_parts.length > 1) {
+ var href_parms_str = href_parts[1];
+ var href_parms = href_parms_str.split("&");
+ var operation = null;
+ var id = -1;
+ for (var index = 0; index < href_parms.length; index++) {
+ if (href_parms[index].indexOf('operation') != -1) {
+ // Found operation parm; get operation value.
+ operation = href_parms[index].split('=')[1];
+ } else if (href_parms[index].indexOf('id') != -1) {
+ // Found id parm; get id value.
+ id = href_parms[index].split('=')[1];
+ }
+ }
+ // Do operation.
+ this.do_operation(operation, id);
return false;
+ }
+ },
+
+ // Navigate window to the URL defined by url_args. This method can be used to short-circuit grid AJAXing.
+ go_to_URL: function () {
+ // Not async request.
+ this.grid.set('async', false);
+
+ // Go.
+ window.location = this.grid.get('url_base') + "?" + $.param(this.grid.get_url_data());
+
+ // Clear grid of transient request attributes.
+ this.grid.set({
+ operation: undefined,
+ item_ids: undefined
});
- });
-
- // Initialize autocomplete for text inputs in search UI.
- var t = $("#input-tags-filter");
- if (t.length) {
- t.autocomplete(history_tag_autocomplete_url,
- { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
- }
-
- var t2 = $("#input-name-filter");
- if (t2.length) {
- t2.autocomplete(history_name_autocomplete_url,
- { selectFirst: false, autoFill: false, highlight: false, mustMatch: false });
- }
-
- // Initialize standard, advanced search toggles.
- $('.advanced-search-toggle').each( function() {
- $(this).click( function() {
- $("#standard-search").slideToggle('fast');
- $('#advanced-search').slideToggle('fast');
- return false;
- });
- });
-}
-
-// Initialize grid elements.
-function init_grid_elements() {
- // Initialize grid selection checkboxes.
- $(".grid").each( function() {
- var checkboxes = $(this).find("input.grid-row-select-checkbox");
- var check_count = $(this).find("span.grid-selected-count");
- var update_checked = function() {
- check_count.text( $(checkboxes).filter(":checked").length );
- };
-
- $(checkboxes).each( function() {
- $(this).change(update_checked);
- });
- update_checked();
- });
-
- // Initialize item labels.
- $(".label").each( function() {
- // If href has an operation in it, do operation when clicked. Otherwise do nothing.
- var href = $(this).attr('href');
- if ( href !== undefined && href.indexOf('operation=') != -1 ) {
- $(this).click( function() {
- do_operation_from_href( $(this).attr('href') );
- return false;
- });
- }
- });
-
- // Initialize ratings.
- if ($('.community_rating_star').length !== 0)
- $('.community_rating_star').rating({});
-
- // Initialize item menu operations.
- make_popup_menus();
-}
-
-// Go back to page one; this is useful when a filter is applied.
-function go_page_one() {
- // Need to go back to page 1 if not showing all.
- var cur_page = grid.get('cur_page');
- if (cur_page !== null && cur_page !== undefined && cur_page !== 'all') {
- grid.set('cur_page', 1);
- }
-}
-
-// Add a condition to the grid filter; this adds the condition and refreshes the grid.
-function add_filter_condition(name, value, append) {
- // Do nothing is value is empty.
- if (value === "") {
- return false;
- }
-
- // Add condition to grid.
- grid.add_filter(name, value, append);
-
- // Add button that displays filter and provides a button to delete it.
- var t = $("<span>" + value + "<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");
- t.addClass('text-filter-val');
- t.click(function() {
- // Remove filter condition.
- grid.remove_filter(name, value);
-
- // Remove visible element.
- $(this).remove();
-
- go_page_one();
- update_grid();
- });
-
- var container = $('#' + name + "-filtering-criteria");
- container.append(t);
-
- go_page_one();
- update_grid();
-}
-
-// Add tag to grid filter.
-function add_tag_to_grid_filter(tag_name, tag_value) {
- // Put tag name and value together.
- var tag = tag_name + (tag_value !== undefined && tag_value !== "" ? ":" + tag_value : "");
- $('#advanced-search').show('fast');
- add_filter_condition("tags", tag, true);
-}
-
-// Set sort condition for grid.
-function set_sort_condition(col_key) {
- // Set new sort condition. New sort is col_key if sorting new column; if reversing sort on
- // currently sorted column, sort is reversed.
- var cur_sort = grid.get('sort_key');
- var new_sort = col_key;
- if (cur_sort.indexOf(col_key) !== -1) {
- // Reverse sort.
- if (cur_sort.substring(0,1) !== '-') {
- new_sort = '-' + col_key;
- } else {
- // Sort reversed by using just col_key.
- }
- }
-
- // Remove sort arrows elements.
- $('.sort-arrow').remove();
-
- // Add sort arrow element to new sort column.
- var sort_arrow = (new_sort.substring(0,1) == '-') ? "↑" : "↓";
- var t = $("<span>" + sort_arrow + "</span>").addClass('sort-arrow');
- var th = $("#" + col_key + '-header');
- th.append(t);
-
- // Update grid.
- grid.set('sort_key', new_sort);
- go_page_one();
- update_grid();
-}
-
-// Set new value for categorical filter.
-function set_categorical_filter(name, new_value) {
- // Update filter hyperlinks to reflect new filter value.
- var category_filter = grid.get('categorical_filters')[name],
- cur_value = grid.get('filters')[name];
- $("." + name + "-filter").each( function() {
- var text = $.trim( $(this).text() );
- var filter = category_filter[text];
- var filter_value = filter[name];
- if (filter_value == new_value) {
- // Remove filter link since grid will be using this filter. It is assumed that
- // this element has a single child, a hyperlink/anchor with text.
- $(this).empty();
- $(this).addClass("current-filter");
- $(this).append(text);
- } else if (filter_value == cur_value) {
- // Add hyperlink for this filter since grid will no longer be using this filter. It is assumed that
- // this element has a single child, a hyperlink/anchor.
- $(this).empty();
- var t = $("<a href='#'>" + text + "</a>");
- t.click(function() {
- set_categorical_filter( name, filter_value );
- });
- $(this).removeClass("current-filter");
- $(this).append(t);
- }
- });
-
- // Update grid.
- grid.add_filter(name, new_value);
- go_page_one();
- update_grid();
-}
-
-// Set page to view.
-function set_page(new_page) {
- // Update page hyperlink to reflect new page.
- $(".page-link").each( function() {
- var id = $(this).attr('id'),
- page_num = parseInt( id.split("-")[2], 10 ), // Id has form 'page-link-<page_num>
- cur_page = grid.get('cur_page'),
- text;
- if (page_num === new_page) {
- // Remove link to page since grid will be on this page. It is assumed that
- // this element has a single child, a hyperlink/anchor with text.
- text = $(this).children().text();
- $(this).empty();
- $(this).addClass("inactive-link");
- $(this).text(text);
- }
- else if (page_num === cur_page) {
- // Add hyperlink to this page since grid will no longer be on this page. It is assumed that
- // this element has a single child, a hyperlink/anchor.
- text = $(this).text();
- $(this).empty();
- $(this).removeClass("inactive-link");
- var t = $("<a href='#'>" + text + "</a>");
- t.click(function() {
- set_page(page_num);
- });
- $(this).append(t);
- }
- });
-
- var maintain_page_links = true;
- if (new_page === "all") {
- grid.set('cur_page', new_page);
- maintain_page_links = false;
- } else {
- grid.set('cur_page', parseInt(new_page, 10));
- }
- update_grid(maintain_page_links);
-}
-
-// Perform a grid operation.
-function do_operation(operation, item_ids) {
- operation = operation.toLowerCase();
+ },
// Update grid.
- grid.set({
- operation: operation,
- item_ids: item_ids
- });
-
- // Do operation. If operation cannot be performed asynchronously, redirect to location.
- if (grid.can_async_op(operation)) {
- update_grid(true);
- }
- else {
- go_to_URL();
- }
-}
+ update_grid: function (maintain_page_links) {
+ // If grid is not using async, then go to URL.
+ if (!this.grid.get('async')) {
+ this.go_to_URL();
+ return;
+ }
-// Perform a hyperlink click that initiates an operation. If there is no operation, ignore click.
-function do_operation_from_href(href) {
- // Get operation, id in hyperlink's href.
- var href_parts = href.split("?");
- if (href_parts.length > 1) {
- var href_parms_str = href_parts[1];
- var href_parms = href_parms_str.split("&");
- var operation = null;
- var id = -1;
- for (var index = 0; index < href_parms.length; index++) {
- if (href_parms[index].indexOf('operation') != -1) {
- // Found operation parm; get operation value.
- operation = href_parms[index].split('=')[1];
- } else if (href_parms[index].indexOf('id') != -1) {
- // Found id parm; get id value.
- id = href_parms[index].split('=')[1];
+ // If there's an operation, do POST; otherwise, do GET.
+ var method = (this.grid.get('operation') ? "POST" : "GET" );
+ $('.loading-elt-overlay').show(); // Show overlay to indicate loading and prevent user actions.
+ var self = this;
+ $.ajax({
+ type: method,
+ url: self.grid.get('url_base'),
+ data: self.grid.get_url_data(),
+ error: function() { alert( "Grid refresh failed" ); },
+ success: function(response_text) {
+ // HACK: use a simple string to separate the elements in the
+ // response: (1) table body; (2) number of pages in table; and (3) message.
+ var parsed_response_text = response_text.split("*****");
+
+ // Update grid body and footer.
+ $('#grid-table-body').html(parsed_response_text[0]);
+ // FIXME: this does not work at all; what's needed is a function
+ // that updates page links when number of pages changes.
+ $('#grid-table-footer').html(parsed_response_text[1]);
+
+ // Trigger custom event to indicate grid body has changed.
+ $('#grid-table-body').trigger('update');
+
+ // Init grid.
+ self.init_grid_elements();
+ make_popup_menus();
+
+ // Hide loading overlay.
+ $('.loading-elt-overlay').hide();
+
+ // Show message if there is one.
+ var message = $.trim( parsed_response_text[2] );
+ if (message !== "") {
+ $('#grid-message').html( message ).show();
+ setTimeout( function() { $('#grid-message').hide(); }, 5000);
+ }
+ },
+ complete: function() {
+ // Clear grid of transient request attributes.
+ self.grid.set({
+ operation: undefined,
+ item_ids: undefined
+ });
+ }
+ });
+ },
+
+ check_all_items: function () {
+ var chk_all = document.getElementById('check_all'),
+ checks = document.getElementsByTagName('input'),
+ total = 0,
+ i;
+ if ( chk_all.checked === true ) {
+ for ( i=0; i < checks.length; i++ ) {
+ if ( checks[i].name.indexOf( 'id' ) !== -1) {
+ checks[i].checked = true;
+ total++;
+ }
}
}
- // Do operation.
- do_operation(operation, id);
- return false;
- }
-}
+ else {
+ for ( i=0; i < checks.length; i++ ) {
+ if ( checks[i].name.indexOf( 'id' ) !== -1) {
+ checks[i].checked = false;
+ }
-// Navigate window to the URL defined by url_args. This method can be used to short-circuit grid AJAXing.
-function go_to_URL() {
- // Not async request.
- grid.set('async', false);
-
- // Go.
- window.location = grid.get('url_base') + "?" + $.param(grid.get_url_data());
-}
-
-// Update grid.
-function update_grid(maintain_page_links) {
- // If grid is not using async, then go to URL.
- if (!grid.get('async')) {
- go_to_URL();
- return;
- }
-
- // If there's an operation, do POST; otherwise, do GET.
- var method = (grid.get('operation') ? "POST" : "GET" );
- $('.loading-elt-overlay').show(); // Show overlay to indicate loading and prevent user actions.
- $.ajax({
- type: method,
- url: grid.get('url_base'),
- data: grid.get_url_data(),
- error: function() { alert( "Grid refresh failed" ); },
- success: function(response_text) {
- // HACK: use a simple string to separate the elements in the
- // response: (1) table body; (2) number of pages in table; and (3) message.
- var parsed_response_text = response_text.split("*****");
-
- // Update grid body and footer.
- $('#grid-table-body').html(parsed_response_text[0]);
- // FIXME: this does not work at all; what's needed is a function
- // that updates page links when number of pages changes.
- $('#grid-table-footer').html(parsed_response_text[1]);
-
- // Trigger custom event to indicate grid body has changed.
- $('#grid-table-body').trigger('update');
-
- // Init grid.
- init_grid_elements();
- make_popup_menus();
-
- // Hide loading overlay.
- $('.loading-elt-overlay').hide();
-
- // Show message if there is one.
- var message = $.trim( parsed_response_text[2] );
- if (message !== "") {
- $('#grid-message').html( message ).show();
- setTimeout( function() { $('#grid-message').hide(); }, 5000);
- }
- },
- complete: function() {
- // Clear grid of transient request attributes.
- grid.set({
- operation: undefined,
- item_ids: undefined
- });
- }
- });
-}
-
-function check_all_items() {
- var chk_all = document.getElementById('check_all'),
- checks = document.getElementsByTagName('input'),
- total = 0,
- i;
- if ( chk_all.checked === true ) {
- for ( i=0; i < checks.length; i++ ) {
- if ( checks[i].name.indexOf( 'id' ) !== -1) {
- checks[i].checked = true;
- total++;
}
}
+ this.init_grid_elements();
+ },
+
+ // confirmation/submission of operation request
+ submit_operation: function (selected_button, confirmation_text)
+ {
+ // verify in any item is selected
+ var number_of_checked_ids = $('input[name="id"]:checked').length;
+ if (!number_of_checked_ids > 0)
+ return false;
+
+ // show confirmation box
+ if (confirmation_text != 'None' && confirmation_text != '')
+ if(!confirm(confirmation_text))
+ return false;
+
+ // collect ids
+ var operation_name = $(selected_button).val();
+ var item_ids = [];
+ $('input[name=id]:checked').each(function() {
+ item_ids.push( $(this).val() );
+ });
+ this.do_operation(operation_name, item_ids);
+
+ // return
+ return true;
}
- else {
- for ( i=0; i < checks.length; i++ ) {
- if ( checks[i].name.indexOf( 'id' ) !== -1) {
- checks[i].checked = false;
- }
- }
- }
- init_grid_elements();
-}
-
-
-// confirmation/submission of operation request
-function submit_operation(selected_button, confirmation_text)
-{
- // verify in any item is selected
- var number_of_checked_ids = $('input[name="id"]:checked').length;
- if (!number_of_checked_ids > 0)
- return false;
-
- // show confirmation box
- if (confirmation_text != 'None' && confirmation_text != '')
- if(!confirm(confirmation_text))
- return false;
-
- // add ids
- var operation_name = selected_button.value;
- var item_ids = [];
- $('input[name=id]:checked').each(function() {
- item_ids.push( $(this).val() );
- });
- do_operation(operation_name, item_ids);
-
- // return
- return true;
-}
+});
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 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;var Grid=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(a){return _.indexOf(this.attributes.async_ops,a)!==-1},add_filter:function(e,f,b){if(b){var c=this.attributes.filters[e],a;if(c===null||c===undefined){a=f}else{if(typeof(c)=="string"){if(c=="All"){a=f}else{var d=[];d[0]=c;d[1]=f;a=d}}else{a=c;a.push(f)}}this.attributes.filters[e]=a}else{this.attributes.filters[e]=f}},remove_filter:function(b,e){var a=this.attributes.filters[b];if(a===null||a===undefined){return false}var d=true;if(typeof(a)==="string"){if(a=="All"){d=false}else{delete this.attributes.filters[b]}}else{var c=_.indexOf(a,e);if(c!==-1){a.splice(c,1)}else{d=false}}return d},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes};if(this.attributes.operation){a.operation=this.attributes.operation}if(this.attributes.item_ids){a.id=this.attributes.item_ids}var b=this;_.each(_.keys(b.attributes.filters),function(c){a["f-"+c]=b.attributes.filters[c]});return a}});function init_grid_controls(){$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});$(".sort-link").each(function(){$(this).click(function(){set_sort_condition($(this).attr("sort_key"));return false})});$(".page-link > a").each(function(){$(this).click(function(){set_page($(this).attr("page_num"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var d=$(this).attr("column_key");var c=$("#input-"+d+"-filter");var e=c.val();c.val("");add_filter_condition(d,e,true);return false})});var a=$("#input-tags-filter");if(a.length){a.autocomplete(history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var b=$("#input-name-filter");if(b.length){b.autocomplete(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})})}function init_grid_elements(){$(".grid").each(function(){var b=$(this).find("input.grid-row-select-checkbox");var a=$(this).find("span.grid-selected-count");var c=function(){a.text($(b).filter(":checked").length)};$(b).each(function(){$(this).change(c)});c()});$(".label").each(function(){var a=$(this).attr("href");if(a!==undefined&&a.indexOf("operation=")!=-1){$(this).click(function(){do_operation_from_href($(this).attr("href"));return false})}});if($(".community_rating_star").length!==0){$(".community_rating_star").rating({})}make_popup_menus()}function go_page_one(){var a=grid.get("cur_page");if(a!==null&&a!==undefined&&a!=="all"){grid.set("cur_page",1)}}function add_filter_condition(c,e,a){if(e===""){return false}grid.add_filter(c,e,a);var d=$("<span>"+e+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");d.addClass("text-filter-val");d.click(function(){grid.remove_filter(c,e);$(this).remove();go_page_one();update_grid()});var b=$("#"+c+"-filtering-criteria");b.append(d);go_page_one();update_grid()}function add_tag_to_grid_filter(c,b){var a=c+(b!==undefined&&b!==""?":"+b:"");$("#advanced-search").show("fast");add_filter_condition("tags",a,true)}function set_sort_condition(f){var e=grid.get("sort_key");var d=f;if(e.indexOf(f)!==-1){if(e.substring(0,1)!=="-"){d="-"+f}else{}}$(".sort-arrow").remove();var c=(d.substring(0,1)=="-")?"↑":"↓";var a=$("<span>"+c+"</span>").addClass("sort-arrow");var b=$("#"+f+"-header");b.append(a);grid.set("sort_key",d);go_page_one();update_grid()}function set_categorical_filter(b,d){var a=grid.get("categorical_filters")[b],c=grid.get("filters")[b];$("."+b+"-filter").each(function(){var h=$.trim($(this).text());var f=a[h];var g=f[b];if(g==d){$(this).empty();$(this).addClass("current-filter");$(this).append(h)}else{if(g==c){$(this).empty();var e=$("<a href='#'>"+h+"</a>");e.click(function(){set_categorical_filter(b,g)});$(this).removeClass("current-filter");$(this).append(e)}}});grid.add_filter(b,d);go_page_one();update_grid()}function set_page(a){$(".page-link").each(function(){var g=$(this).attr("id"),e=parseInt(g.split("-")[2],10),c=grid.get("cur_page"),f;if(e===a){f=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(f)}else{if(e===c){f=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var d=$("<a href='#'>"+f+"</a>");d.click(function(){set_page(e)});$(this).append(d)}}});var b=true;if(a==="all"){grid.set("cur_page",a);b=false}else{grid.set("cur_page",parseInt(a,10))}update_grid(b)}function do_operation(b,a){b=b.toLowerCase();grid.set({operation:b,item_ids:a});if(grid.can_async_op(b)){update_grid(true)}else{go_to_URL()}}function do_operation_from_href(c){var f=c.split("?");if(f.length>1){var a=f[1];var e=a.split("&");var b=null;var g=-1;for(var d=0;d<e.length;d++){if(e[d].indexOf("operation")!=-1){b=e[d].split("=")[1]}else{if(e[d].indexOf("id")!=-1){g=e[d].split("=")[1]}}}do_operation(b,g);return false}}function go_to_URL(){grid.set("async",false);window.location=grid.get("url_base")+"?"+$.param(grid.get_url_data())}function update_grid(a){if(!grid.get("async")){go_to_URL();return}var b=(grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();$.ajax({type:b,url:grid.get("url_base"),data:grid.get_url_data(),error:function(){alert("Grid refresh failed")},success:function(d){var c=d.split("*****");$("#grid-table-body").html(c[0]);$("#grid-table-footer").html(c[1]);$("#grid-table-body").trigger("update");init_grid_elements();make_popup_menus();$(".loading-elt-overlay").hide();var e=$.trim(c[2]);if(e!==""){$("#grid-message").html(e).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){grid.set({operation:undefined,item_ids:undefined})}})}function check_all_items(){var a=document.getElementById("check_all"),b=document.getElementsByTagName("input"),d=0,c;if(a.checked===true){for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=true;d++}}}else{for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=false}}}init_grid_elements()}function submit_operation(d,e){var c=$('input[name="id"]:checked').length;if(!c>0){return false}if(e!="None"&&e!=""){if(!confirm(e)){return false}}var b=d.value;var a=[];$("input[name=id]:checked").each(function(){a.push($(this).val())});do_operation(b,a);return true};
\ No newline at end of file
+jQuery.ajaxSettings.traditional=true;var Grid=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(a){return _.indexOf(this.attributes.async_ops,a)!==-1},add_filter:function(e,f,b){if(b){var c=this.attributes.filters[e],a;if(c===null||c===undefined){a=f}else{if(typeof(c)=="string"){if(c=="All"){a=f}else{var d=[];d[0]=c;d[1]=f;a=d}}else{a=c;a.push(f)}}this.attributes.filters[e]=a}else{this.attributes.filters[e]=f}},remove_filter:function(b,e){var a=this.attributes.filters[b];if(a===null||a===undefined){return false}var d=true;if(typeof(a)==="string"){if(a=="All"){d=false}else{delete this.attributes.filters[b]}}else{var c=_.indexOf(a,e);if(c!==-1){a.splice(c,1)}else{d=false}}return d},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes};if(this.attributes.operation){a.operation=this.attributes.operation}if(this.attributes.item_ids){a.id=this.attributes.item_ids}var b=this;_.each(_.pairs(b.attributes.filters),function(c){a["f-"+c[0]]=c[1]});return a}});var GridView=Backbone.View.extend({grid:null,initialize:function(a){this.grid=a;this.init_grid_elements();this.init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})},init_grid_controls:function(){$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});var a=this;$(".sort-link").each(function(){$(this).click(function(){a.set_sort_condition($(this).attr("sort_key"));return false})});$(".page-link > a").each(function(){$(this).click(function(){a.set_page($(this).attr("page_num"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){a.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var e=$(this).attr("column_key");var d=$("#input-"+e+"-filter");var f=d.val();d.val("");a.add_filter_condition(e,f,true);return false})});var b=$("#input-tags-filter");if(b.length){b.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var c=$("#input-name-filter");if(c.length){c.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 c=$(this).find("input.grid-row-select-checkbox");var b=$(this).find("span.grid-selected-count");var d=function(){b.text($(c).filter(":checked").length)};$(c).each(function(){$(this).change(d)});d()});var a=this;$(".label").each(function(){var b=$(this).attr("href");if(b!==undefined&&b.indexOf("operation=")!=-1){$(this).click(function(){a.do_operation_from_href($(this).attr("href"));return false})}});if($(".community_rating_star").length!==0){$(".community_rating_star").rating({})}make_popup_menus()},go_page_one:function(){var a=this.grid.get("cur_page");if(a!==null&&a!==undefined&&a!=="all"){this.grid.set("cur_page",1)}},add_filter_condition:function(d,f,a){if(f===""){return false}this.grid.add_filter(d,f,a);var e=$("<span>"+f+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");e.addClass("text-filter-val");var c=this;e.click(function(){c.grid.remove_filter(d,f);$(this).remove();c.go_page_one();c.update_grid()});var b=$("#"+d+"-filtering-criteria");b.append(e);this.go_page_one();this.update_grid()},set_sort_condition:function(f){var e=this.grid.get("sort_key");var d=f;if(e.indexOf(f)!==-1){if(e.substring(0,1)!=="-"){d="-"+f}else{}}$(".sort-arrow").remove();var c=(d.substring(0,1)=="-")?"↑":"↓";var a=$("<span>"+c+"</span>").addClass("sort-arrow");var b=$("#"+f+"-header");b.append(a);this.grid.set("sort_key",d);this.go_page_one();this.update_grid()},set_categorical_filter:function(c,e){var b=this.grid.get("categorical_filters")[c],d=this.grid.get("filters")[c];var a=this;$("."+c+"-filter").each(function(){var i=$.trim($(this).text());var g=b[i];var h=g[c];if(h==e){$(this).empty();$(this).addClass("current-filter");$(this).append(i)}else{if(h==d){$(this).empty();var f=$("<a href='#'>"+i+"</a>");f.click(function(){a.set_categorical_filter(c,h)});$(this).removeClass("current-filter");$(this).append(f)}}});this.grid.add_filter(c,e);this.go_page_one();this.update_grid()},set_page:function(a){var b=this;$(".page-link").each(function(){var h=$(this).attr("id"),f=parseInt(h.split("-")[2],10),d=b.grid.get("cur_page"),g;if(f===a){g=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(g)}else{if(f===d){g=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var e=$("<a href='#'>"+g+"</a>");e.click(function(){set_page(f)});$(this).append(e)}}});var c=true;if(a==="all"){this.grid.set("cur_page",a);c=false}else{this.grid.set("cur_page",parseInt(a,10))}this.update_grid(c)},do_operation:function(b,a){b=b.toLowerCase();this.grid.set({operation:b,item_ids:a});if(this.grid.can_async_op(b)){this.update_grid(true)}else{this.go_to_URL()}},do_operation_from_href:function(c){var f=c.split("?");if(f.length>1){var a=f[1];var e=a.split("&");var b=null;var g=-1;for(var d=0;d<e.length;d++){if(e[d].indexOf("operation")!=-1){b=e[d].split("=")[1]}else{if(e[d].indexOf("id")!=-1){g=e[d].split("=")[1]}}}this.do_operation(b,g);return false}},go_to_URL:function(){this.grid.set("async",false);window.location=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data());this.grid.set({operation:undefined,item_ids:undefined})},update_grid:function(b){if(!this.grid.get("async")){this.go_to_URL();return}var c=(this.grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();var a=this;$.ajax({type:c,url:a.grid.get("url_base"),data:a.grid.get_url_data(),error:function(){alert("Grid refresh failed")},success:function(e){var d=e.split("*****");$("#grid-table-body").html(d[0]);$("#grid-table-footer").html(d[1]);$("#grid-table-body").trigger("update");a.init_grid_elements();make_popup_menus();$(".loading-elt-overlay").hide();var f=$.trim(d[2]);if(f!==""){$("#grid-message").html(f).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){a.grid.set({operation:undefined,item_ids:undefined})}})},check_all_items:function(){var a=document.getElementById("check_all"),b=document.getElementsByTagName("input"),d=0,c;if(a.checked===true){for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=true;d++}}}else{for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=false}}}this.init_grid_elements()},submit_operation:function(d,e){var c=$('input[name="id"]:checked').length;if(!c>0){return false}if(e!="None"&&e!=""){if(!confirm(e)){return false}}var b=$(d).val();var a=[];$("input[name=id]:checked").each(function(){a.push($(this).val())});this.do_operation(b,a);return true}});
\ No newline at end of file
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/base.mako
--- a/templates/base.mako
+++ b/templates/base.mako
@@ -2,6 +2,7 @@
<!DOCTYPE HTML><html><!--base.mako-->
+ ${self.init()}
<head><title>${self.title()}</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
@@ -17,6 +18,9 @@
## Default title
<%def name="title()"></%def>
+## Default init
+<%def name="init()"></%def>
+
## Default stylesheets
<%def name="stylesheets()">
${h.css('base')}
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -12,16 +12,167 @@
return '/base.mako'
%><%inherit file="${inherit(context)}"/>
-<%namespace file="/display_common.mako" import="render_message" />
+<%namespace file="./grid_common.mako" import="*" /><%namespace file="/refresh_frames.mako" import="handle_refresh_frames" />
+<%namespace file="/display_common.mako" import="get_class_plural" /><%def name="init()"><%
- self.has_left_panel=False
- self.has_right_panel=False
- self.message_box_visible=False
- self.active_view="user"
- self.overlay_visible=False
+ self.has_left_panel = False
+ self.has_right_panel = False
+ self.message_box_visible = False
+ self.overlay_visible = False
+ self.active_view = 'user'
+
+ self.grid_config = {
+ 'title' : grid.title,
+ 'url_base' : trans.request.path_url,
+ 'async' : grid.use_async,
+ 'async_ops' : [],
+ 'categorical_filters' : {},
+ 'filters' : cur_filter_dict,
+ 'sort_key' : sort_key,
+ 'show_item_checkboxes' : context.get('show_item_checkboxes', False),
+ 'cur_page_num' : cur_page_num,
+ 'num_pages' : num_pages,
+ 'history_tag_autocomplete_url' : url( controller='tag', action='tag_autocomplete_data', item_class='History' ),
+ 'history_name_autocomplete_url' : url( controller='history', action='name_autocomplete_data' ),
+ 'status' : status,
+ 'message' : util.restore_text(message),
+ 'global_actions' : [],
+ 'operations' : [],
+ 'items' : [],
+ 'columns' : [],
+ 'multiple_item_ops_exist' : None,
+ 'get_class_plural' : get_class_plural( grid.model_class ).lower(),
+ 'use_paging' : grid.use_paging,
+ 'legend' : grid.legend,
+ 'current_item_id' : ''
+ }
+
+ ## add current item if exists
+ if current_item:
+ self.grid_config['current_item_id'] = current_item.id
+ endif
+
+ ## column
+ for column in grid.columns:
+
+ ## add column sort links
+ href = None
+ extra = ''
+ if column.sortable:
+ if sort_key.endswith(column.key):
+ if not sort_key.startswith("-"):
+ href = url( sort=( "-" + column.key ) )
+ extra = "↓"
+ else:
+ href = url( sort=( column.key ) )
+ extra = "↑"
+ else:
+ href = url( sort=column.key )
+
+ ## add to configuration
+ self.grid_config['columns'].append({
+ 'key' : column.key,
+ 'visible' : column.visible,
+ 'nowrap' : column.nowrap,
+ 'attach_popup' : column.attach_popup,
+ 'label_id_prefix' : column.label_id_prefix,
+ 'sortable' : column.sortable,
+ 'label' : column.label,
+ 'href' : href,
+ 'extra' : extra
+ })
+ endfor
+
+ ## operations
+ for operation in grid.operations:
+ self.grid_config['operations'].append({
+ 'allow_multiple' : operation.allow_multiple,
+ 'allow_popup' : operation.allow_popup,
+ 'target' : operation.target,
+ 'label' : operation.label,
+ 'confirm' : operation.confirm,
+ 'global_operation' : False
+ })
+ if operation.allow_multiple:
+ self.grid_config['multiple_item_ops_exist'] = True
+
+ if operation.global_operation:
+ self.grid_config['global_operation'] = url( ** (operation.global_operation()) )
+ endfor
+
+ ## global actions
+ for action in grid.global_actions:
+ self.grid_config['global_actions'].append({
+ 'url_args' : url(**action.url_args),
+ 'label' : action.label
+ })
+ endfor
+
+ ## Operations that are async (AJAX) compatible.
+ for operation in [op for op in grid.operations if op.async_compatible]:
+ self.grid_config['async_ops'].append(operation.label.lower());
+ endfor
+
+ ## Filter values for categorical filters.
+ for column in grid.columns:
+ if column.filterable is not None and not isinstance( column, TextColumn ):
+ self.grid_config['categorical_filters'][column.key] = dict([ (filter.label, filter.args) for filter in column.get_accepted_filters() ])
+ endif
+ endfor
+
+ # items
+ for i, item in enumerate( query ):
+ item_dict = {
+ 'id' : item.id,
+ 'encode_id' : trans.security.encode_id(item.id),
+ 'link' : [],
+ 'operation_config' : {},
+ 'column_config' : {}
+ }
+
+ ## data columns
+ for column in grid.columns:
+ if column.visible:
+ ## get link
+ link = column.get_link(trans, grid, item)
+ if link:
+ link = url(**link)
+ else:
+ link = None
+ endif
+
+ ## get value
+ value = column.get_value( trans, grid, item )
+
+ # Handle non-ascii chars.
+ if isinstance(value, str):
+ value = unicode(value, 'utf-8')
+
+ # escape string
+ value = value.replace('/', '//')
+ endif
+
+ ## Item dictionary
+ item_dict['column_config'][column.label] = {
+ 'link' : link,
+ 'value' : value
+ }
+ endif
+ endfor
+ ## add operation details to item
+ for operation in grid.operations:
+ item_dict['operation_config'][operation.label] = {
+ 'allowed' : operation.allowed(item),
+ 'url_args' : url( **operation.get_url_args( item ) )
+ }
+ endfor
+
+ ## add item to list
+ self.grid_config['items'].append(item_dict)
+ endfor
%></%def>
@@ -45,7 +196,7 @@
${self.make_grid( grid )}
</%def>
-<%def name="title()">${grid.title}</%def>
+<%def name="title()">${self.grid_config['title']}</%def><%def name="javascripts()">
${parent.javascripts()}
@@ -57,65 +208,33 @@
${handle_refresh_frames()}
<script type="text/javascript">
-
- // Needed URLs for grid history searching.
- var history_tag_autocomplete_url = "${url( controller='tag', action='tag_autocomplete_data', item_class='History' )}",
- history_name_autocomplete_url = "${url( controller='history', action='name_autocomplete_data' )}";
- //
- // Create grid object.
- //
+ var gridView = null;
- // Operations that are async (AJAX) compatible.
- var async_ops = [];
- %for operation in [op for op in grid.operations if op.async_compatible]:
- async_ops.push('${operation.label.lower()}');
- %endfor
+ function add_tag_to_grid_filter (tag_name, tag_value)
+ {
+ // Put tag name and value together.
+ var tag = tag_name + (tag_value !== undefined && tag_value !== "" ? ":" + tag_value : "");
+ $('#advanced-search').show('fast');
+ gridView.add_filter_condition("tags", tag, true);
+ };
- // Filter values for categorical filters.
- var categorical_filters = {};
- %for column in grid.columns:
- %if column.filterable is not None and not isinstance( column, TextColumn ):
- var ${column.key}_filters = ${ h.to_json_string( dict([ (filter.label, filter.args) for filter in column.get_accepted_filters() ]) ) };
- categorical_filters['${column.key}'] = ${column.key}_filters;
- %endif
- %endfor
-
- /** Returns true if string denotes true. */
- var is_true = function(s) { return _.indexOf(['True', 'true', 't'], s) !== -1; };
-
- // Create grid.
- var grid = new Grid({
- url_base: '${trans.request.path_url}',
- async: is_true('${grid.use_async}'),
- async_ops: async_ops,
- categorical_filters: categorical_filters,
- filters: ${h.to_json_string( cur_filter_dict )},
- sort_key: '${sort_key}',
- show_item_checkboxes: is_true('${context.get('show_item_checkboxes', False)}'),
- cur_page: ${cur_page_num},
- // persistent page="all"
- //cur_page: ('${cur_page_num}' === 'all')?('all'):(Number('${cur_page_num}')),
- num_pages: ${num_pages}
- });
-
- // Initialize grid objects on load.
- // FIXME: use a grid view object eventually.
- $(document).ready(function() {
+ $(function() {
+ ## get configuration
+ var grid_config = ${ h.to_json_string( self.grid_config ) };
+ console.log(grid_config);
+ // Create grid.
+ var grid = new Grid(grid_config);
// strip protocol and domain
var url = grid.get('url_base');
url = url.replace(/^.*\/\/[^\/]+/, '');
grid.set('url_base', url);
-
- init_grid_elements();
- init_grid_controls();
- // Initialize text filters to select text on click and use normal font when user is typing.
- $('input[type=text]').each(function() {
- $(this).click(function() { $(this).select(); } )
- .keyup(function () { $(this).css("font-style", "normal"); });
- });
+
+ // Create view.
+ gridView = new GridView(grid);
});
+
</script></%def>
@@ -127,17 +246,12 @@
%if context.get('use_panels'):
div#center {
padding: 10px;
+ overflow: auto;
}
%endif
</style></%def>
-##
-## Custom grid methods.
-##
-
-<%namespace file="./grid_common.mako" import="*" />
-
<%def name="make_grid( grid )"><div class="loading-elt-overlay"></div><table>
@@ -147,7 +261,14 @@
<td></td></tr><tr>
- <td width="100%" id="grid-message" valign="top">${render_message( message, status )}</td>
+ <td width="100%" id="grid-message" valign="top">
+ %if message:
+ <p>
+ <div class="${self.grid_config['status']}message transient-message">${self.grid_config['message']}</div>
+ <div style="clear: both"></div>
+ </p>
+ %endif
+ </td><td></td><td></td></tr>
@@ -157,7 +278,7 @@
</%def><%def name="grid_title()">
- <h2>${grid.title}</h2>
+ <h2>${self.grid_config['title']}</h2></%def>
## Render grid header.
@@ -166,18 +287,18 @@
%if render_title:
${self.grid_title()}
%endif
-
- %if grid.global_actions:
+
+ %if self.grid_config['global_actions']:
<ul class="manage-table-actions">
- %if len( grid.global_actions ) < 3:
- %for action in grid.global_actions:
- <li><a class="action-button" href="${url( **action.url_args )}">${action.label}</a></li>
+ %if len( self.grid_config['global_actions'] ) < 3:
+ %for action in self.grid_config['global_actions']:
+ <li><a class="action-button" href="${action['url_args']}">${action['label']}</a></li>
%endfor
%else:
<li><a class="action-button" id="action-8675309-popup" class="menubutton">Actions</a></li><div popupmenu="action-8675309-popup">
- %for action in grid.global_actions:
- <a class="action-button" href="${url( **action.url_args )}">${action.label}</a>
+ %for action in self.grid_config['global_actions']:
+ <a class="action-button" href="${action['url_args']}">${action['label']}</a>
%endfor
</div>
%endif
@@ -191,55 +312,37 @@
## Render grid.
<%def name="render_grid_table( grid, show_item_checkboxes=False)"><%
- # Set flag to indicate whether grid has operations that operate on multiple items.
- multiple_item_ops_exist = False
- for operation in grid.operations:
- if operation.allow_multiple:
- multiple_item_ops_exist = True
-
+ # get configuration
+ show_item_checkboxes = self.grid_config['show_item_checkboxes']
+ multiple_item_ops_exist = self.grid_config['multiple_item_ops_exist']
+ sort_key = self.grid_config['sort_key']
+
# Show checkboxes if flag is set or if multiple item ops exist.
if show_item_checkboxes or multiple_item_ops_exist:
show_item_checkboxes = True
%>
- <form action="${url()}" method="post" onsubmit="return false;">
+ <form method="post" onsubmit="return false;"><table id="grid-table" class="grid"><thead id="grid-table-header"><tr>
%if show_item_checkboxes:
<th>
- %if query.count() > 0:
- <input type="checkbox" id="check_all" name=select_all_checkbox value="true" onclick='check_all_items(1);'><input type="hidden" name=select_all_checkbox value="true">
+ %if len(self.grid_config['items']) > 0:
+ <input type="checkbox" id="check_all" name=select_all_checkbox value="true" onclick='gridView.check_all_items(1);'><input type="hidden" name=select_all_checkbox value="true">
%endif
</th>
%endif
- %for column in grid.columns:
- %if column.visible:
- <%
- href = ""
- extra = ""
- if column.sortable:
- if sort_key.endswith(column.key):
- if not sort_key.startswith("-"):
- href = url( sort=( "-" + column.key ) )
- extra = "↓"
- else:
- href = url( sort=( column.key ) )
- extra = "↑"
- else:
- href = url( sort=column.key )
- %>
+ %for column in self.grid_config['columns']:
+ %if column['visible']:
<th\
- id="${column.key}-header"
- %if column.ncells > 1:
- colspan="${column.ncells}"
- %endif
+ id="${column['key']}-header"
>
- %if href:
- <a href="${href}" class="sort-link" sort_key="${column.key}">${column.label}</a>
+ %if column['href']:
+ <a href="${column['href']}" class="sort-link" sort_key="${column['key']}">${column['label']}</a>
%else:
- ${column.label}
+ ${column['label']}
%endif
- <span class="sort-arrow">${extra}</span>
+ <span class="sort-arrow">${column['extra']}</span></th>
%endif
%endfor
@@ -259,15 +362,16 @@
## Render grid table body contents.
<%def name="render_grid_table_body_contents(grid, show_item_checkboxes=False)"><% num_rows_rendered = 0 %>
- %if query.count() == 0:
+ %if len(self.grid_config['items']) == 0:
## No results.
<tr><td colspan="100"><em>No Items</em></td></tr><% num_rows_rendered = 1 %>
%endif
- %for i, item in enumerate( query ):
- <% encoded_id = trans.security.encode_id( item.id ) %>
+ %for i, item in enumerate( self.grid_config['items'] ):
+ <% encoded_id = item['encode_id'] %>
+ <% popupmenu_id = "grid-" + str(i) + "-popup" %><tr \
- %if current_item == item:
+ %if self.grid_config['current_item_id'] == item['id']:
class="current" \
%endif
>
@@ -278,71 +382,72 @@
</td>
%endif
## Data columns
- %for column in grid.columns:
- %if column.visible:
+ %for column in self.grid_config['columns']:
+ %if column['visible']:
<%
- # Nowrap
+ ## Nowrap
nowrap = ""
- if column.nowrap:
- nowrap = 'style="white-space:nowrap;"'
- # Link
- link = column.get_link( trans, grid, item )
- if link:
- href = url( **link )
- else:
- href = None
- # Value (coerced to list so we can loop)
- value = column.get_value( trans, grid, item )
- if column.ncells == 1:
- value = [ value ]
+ if column['nowrap']:
+ nowrap = 'style="white-space:nowrap;"'
+
+ # get column settings
+ column_settings = item['column_config'][column['label']]
+
+ # load attributes
+ link = column_settings['link']
+ value = column_settings['value']
+
+ # check if formatting is defined
+ value = str(value).replace('//', '/')
+
+ # Attach popup menu?
+ id = ""
+ if column['attach_popup']:
+ id = 'grid-%d-popup' % i
+ endif
+
+ # Determine appropriate class
+ cls = ""
+ if column['attach_popup']:
+ cls = "menubutton"
+ if link:
+ cls += " split"
+ endif
+ endif
%>
- %for cellnum, v in enumerate( value ):
- <%
- id = ""
- # Handle non-ascii chars.
- if isinstance(v, str):
- v = unicode(v, 'utf-8')
- # Attach popup menu?
- if column.attach_popup and cellnum == 0:
- id = 'grid-%d-popup' % i
- # Determine appropriate class
- cls = ""
- if column.attach_popup:
- cls = "menubutton"
- if href:
- cls += " split"
-
- %>
- <td ${nowrap}>
- %if href:
- %if len(grid.operations) != 0:
+ <td ${nowrap}>
+ %if link:
+ %if len(self.grid_config['operations']) != 0:
<div id="${id}" class="${cls}" style="float: left;">
- %endif
- <a class="label" href="${href}">${v}</a>
- %if len(grid.operations) != 0:
+ %endif
+ <a class="label" href="${link}">${value}</a>
+ %if len(self.grid_config['operations']) != 0:
</div>
- %endif
- %else:
- <div id="${id}" class="${cls}"><label id="${column.label_id_prefix}${encoded_id}" for="${encoded_id}">${v}</label></div>
%endif
- </td>
- %endfor
+ %else:
+ <div id="${id}" class="${cls}"><label id="${column['label_id_prefix']}${encoded_id}" for="${encoded_id}">${value}</label></div>
+ %endif
+ </td>
%endif
%endfor
## Actions column
<td>
- <div popupmenu="grid-${i}-popup">
- %for operation in grid.operations:
- %if operation.allowed( item ) and operation.allow_popup:
+ <div popupmenu="${popupmenu_id}">
+ %for operation in self.grid_config['operations']:
+ <%
+ operation_id = operation['label']
+ operation_settings = item['operation_config'][operation_id]
+ %>
+ %if operation_settings['allowed'] and operation['allow_popup']:
<%
target = ""
- if operation.target:
- target = "target='" + operation.target + "'"
+ if operation['target']:
+ target = "target='" + operation['target'] + "'"
%>
- %if operation.confirm:
- <a class="action-button" ${target} confirm="${operation.confirm}" href="${ url( **operation.get_url_args( item ) ) }">${operation.label}</a>
+ %if operation['confirm']:
+ <a class="action-button" ${target} confirm="${operation['confirm']}" href="${operation_settings['url_args']}">${operation_id}</a>
%else:
- <a class="action-button" ${target} href="${ url( **operation.get_url_args( item ) ) }">${operation.label}</a>
+ <a class="action-button" ${target} href="${operation_settings['url_args']}">${operation_id}</a>
%endif
%endif
%endfor
@@ -351,20 +456,16 @@
</tr><% num_rows_rendered += 1 %>
%endfor
- ## Dummy rows to prevent table for moving too much.
- ##%if grid.use_paging:
- ## %for i in range( num_rows_rendered , grid.num_rows_per_page ):
- ## <tr><td colspan="1000"></td></tr>
- ## %endfor
- ##%endif
</%def>
## Render grid table footer contents.
<%def name="render_grid_table_footer_contents(grid, show_item_checkboxes=False)">
- ## Row for navigating among pages.
- <%namespace file="/display_common.mako" import="get_class_plural" />
- <% items_plural = get_class_plural( grid.model_class ).lower() %>
- %if grid.use_paging and num_pages > 1:
+ <%
+ items_plural = self.grid_config['get_class_plural']
+ num_pages = self.grid_config['num_pages']
+ cur_page_num = self.grid_config['cur_page_num']
+ %>
+ %if self.grid_config['use_paging'] and num_pages > 1:
<tr id="page-links-row">
%if show_item_checkboxes:
<td></td>
@@ -438,33 +539,29 @@
<td></td><td colspan="100">
For <span class="grid-selected-count"></span> selected ${items_plural}:
- %for operation in grid.operations:
- %if operation.allow_multiple:
- <input type="button" value="${operation.label}" class="action-button" onclick="submit_operation(this, '${operation.confirm}')">
+ %for operation in self.grid_config['operations']:
+ %if operation['allow_multiple']:
+ <input type="button" value="${operation['label']}" class="action-button" onclick="gridView.submit_operation(this, '${operation['confirm']}')">
%endif
%endfor
</td></tr>
%endif
- %if len([o for o in grid.operations if o.global_operation]) > 0:
+ %if len([o for o in self.grid_config['operations'] if o['global_operation']]) > 0:
<tr><td colspan="100">
- %for operation in grid.operations:
- %if operation.global_operation:
- <%
- link = operation.global_operation()
- href = url( **link )
- %>
- <a class="action-button" href="${href}">${operation.label}</a>
- %endif
+ %for operation in self.grid_config['operations']:
+ %if operation['global_operation']:
+ <a class="action-button" href="${operation['global_operation']}">${operation['label']}</a>
+ %endif
%endfor
</td></tr>
%endif
- %if grid.legend:
+ %if self.grid_config['legend']:
<tr><td colspan="100">
- ${grid.legend}
+ ${self.grid_config['legend']}
</td></tr>
%endif
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/grid_base_async.mako
--- a/templates/grid_base_async.mako
+++ b/templates/grid_base_async.mako
@@ -1,6 +1,8 @@
<%namespace file="./grid_base.mako" import="*" /><%namespace file="/display_common.mako" import="render_message" />
+${init()}
+
<%
# Set flag to indicate whether grid has operations that operate on multiple items.
multiple_item_ops_exist = False
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/webapps/galaxy/page/select_items_grid.mako
--- a/templates/webapps/galaxy/page/select_items_grid.mako
+++ b/templates/webapps/galaxy/page/select_items_grid.mako
@@ -1,6 +1,6 @@
## Template generates a grid that enables user to select items.
<%namespace file="../grid_base.mako" import="*" />
-
+${init()}
${grid_javascripts()}
${stylesheets()}
${render_grid_header( grid, False )}
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/webapps/galaxy/page/select_items_grid_async.mako
--- a/templates/webapps/galaxy/page/select_items_grid_async.mako
+++ b/templates/webapps/galaxy/page/select_items_grid_async.mako
@@ -1,6 +1,6 @@
<%namespace file="../grid_base.mako" import="*" /><%namespace file="/display_common.mako" import="render_message" />
-
+${init()}
## Always show item checkboxes so that users can select items.
${render_grid_table_body_contents( grid, show_item_checkboxes=show_item_checkboxes )}
*****
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/webapps/galaxy/tracks/add_to_viz.mako
--- a/templates/webapps/galaxy/tracks/add_to_viz.mako
+++ b/templates/webapps/galaxy/tracks/add_to_viz.mako
@@ -1,6 +1,6 @@
## Template generates a grid that enables user to add tracks
<%namespace file="../grid_base.mako" import="*" />
-
+${init()}
${stylesheets()}
${grid_javascripts()}
${render_grid_header( grid, False )}
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/webapps/galaxy/tracks/add_tracks.mako
--- a/templates/webapps/galaxy/tracks/add_tracks.mako
+++ b/templates/webapps/galaxy/tracks/add_tracks.mako
@@ -1,6 +1,6 @@
## Template generates a grid that enables user to add tracks
<%namespace file="../grid_base.mako" import="*" />
-
+${init()}
${stylesheets()}
${grid_javascripts()}
${render_grid_header( grid, False )}
diff -r 5e534cc8da856ad598d63b8b9f03fe20629df05f -r f1cef709a9e5631cae2126ffff71dbba64611f87 templates/webapps/galaxy/tracks/history_select_grid.mako
--- a/templates/webapps/galaxy/tracks/history_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/history_select_grid.mako
@@ -4,7 +4,7 @@
## not make it possible to easily subclass templates.
##
<%namespace file="../grid_base.mako" import="*" />
-
+${init()}
${stylesheets()}
${grid_javascripts()}
@@ -12,18 +12,16 @@
<script type="text/javascript">
// Load all grid URLs into modal-body element so that
// grid + links stays embedded.
- var load_urls_into_modal_body = function() {
+ $(document).ready(function() {
+ $(".addtracktab, #grid-table a").off();
$(".addtracktab, #grid-table a").click(function() {
+ console.log($(this).attr("href"));
var modal_body = $(".modal-body");
if (modal_body.length !== 0) {
modal_body.load($(this).attr("href"));
return false;
}
});
- };
- // Need to process label URLs when document loaded and when grid changes.
- $(document).ready(function() {
- load_urls_into_modal_body();
});
</script><style>
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.
[View Less]
1
0
commit/galaxy-central: jmchilton: Functional tool test fix.
by commits-noreply@bitbucket.org 17 Nov '13
by commits-noreply@bitbucket.org 17 Nov '13
17 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5e534cc8da85/
Changeset: 5e534cc8da85
User: jmchilton
Date: 2013-11-17 09:03:28
Summary: Functional tool test fix.
No tests with a repeat and min=1 were ever going to past.
Affected #: 1 file
diff -r ef9968a089db28349b22c302ca07e9aa152bfe51 -r 5e534cc8da856ad598d63b8b9f03fe20629df05f test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
…
[View More]@@ -93,7 +93,8 @@
repeat_name = None
for input_name, input_value in testdef.tool.inputs_by_page[0].items():
if isinstance( input_value, grouping.Repeat ) and all_inputs.get( input_name, 1 ) not in [ 0, "0" ]: # default behavior is to test 1 repeat, for backwards compatibility
- repeat_name = input_name
+ if not input_value.min: # If input_value.min == 1, the element is already on the page don't add new element.
+ repeat_name = input_name
break
#check if we need to verify number of outputs created dynamically by tool
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.
[View Less]
1
0