mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Asynchronous history updates. Start a job and don't click refresh.
Unfinished datasets update themselves every 3 seconds until they're done.
This commit is contained in:
@@ -406,6 +406,29 @@ class Universe( BaseController ):
|
||||
return trans.fill_template("history_imported.tmpl", history=new_history)
|
||||
return trans.fill_template("history_import.tmpl", history=import_history)
|
||||
|
||||
@web.expose
|
||||
def dataset_state ( self, trans, id=None ):
|
||||
if id is not None:
|
||||
try:
|
||||
data = self.app.model.Dataset.get( id )
|
||||
except:
|
||||
return trans.show_error_message( "Unable to check dataset $id.")
|
||||
else:
|
||||
return trans.show_error_message( "Must specify a dataset id.")
|
||||
trans.response.headers['X-Dataset-State'] = data.state
|
||||
return data.state
|
||||
|
||||
@web.expose
|
||||
def dataset_code( self, trans, id=None, hid=None ):
|
||||
if id is not None:
|
||||
try:
|
||||
data = self.app.model.Dataset.get( id )
|
||||
except:
|
||||
return trans.show_error_message( "Unable to check dataset $id.")
|
||||
else:
|
||||
return trans.show_error_message( "Must specify a dataset id.")
|
||||
return trans.fill_template("dataset_code.tmpl", data=data, hid=hid)
|
||||
|
||||
@web.expose
|
||||
def history_switch( self, trans, id=None ):
|
||||
if not id:
|
||||
|
||||
@@ -89,6 +89,13 @@ div.historyItemBody div
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
div.historyItemContainer
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
pre.peek
|
||||
{
|
||||
background: white;
|
||||
@@ -101,4 +108,4 @@ pre.peek th
|
||||
{
|
||||
color: white;
|
||||
background: #023858;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+3277
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,201 @@
|
||||
##
|
||||
## Render the dataset `$data`, using `$hid` as the displayed id
|
||||
##
|
||||
|
||||
#def render_script( $data )
|
||||
|
||||
<script type="text/javascript">
|
||||
q( document ).ready( function() {
|
||||
q( "div#historyItem-$data.id" ).children( "div.historyItemBody" ).hide();
|
||||
// Load saved state and show as neccesary
|
||||
var state = new CookieSet( "galaxy.history.expand_state" );
|
||||
for ( id in state.store ) {
|
||||
if ( id == "historyItem-$data.id" ) {
|
||||
q( "div#" + id ).children( "div.historyItemBody" ).show();
|
||||
}
|
||||
}
|
||||
// If Mozilla, hide scrollbars in hidden items since they cause animation bugs
|
||||
if ( q.browser.mozilla ) {
|
||||
q( "div#historyItem-$data.id" ).children( "div.historyItemBody" ).each( function() {
|
||||
if ( ! q(this).is( ":visible" ) ) q(this).find( "pre.peek" ).css( "overflow", "hidden" );
|
||||
})
|
||||
}
|
||||
delete state;
|
||||
// Add history item show / hide
|
||||
//q( "div.historyItemWrapper" ).each( function() {
|
||||
q( "div#historyItem-$data.id" ).each( function() {
|
||||
var id = this.id;
|
||||
var body = q(this).children( "div.historyItemBody" );
|
||||
var peek = body.find( "pre.peek" )
|
||||
q(this).children( "table" ).find( "span.historyItemTitle" ).wrap( "<a href='#'></a>" ).click( function() {
|
||||
if ( body.is(":visible") ) {
|
||||
if ( q.browser.mozilla ) { peek.css( "overflow", "hidden" ) }
|
||||
body.slideUp( "fast" );
|
||||
## other instances of this could be editing the cookie, refetch
|
||||
var state = new CookieSet( "galaxy.history.expand_state" );
|
||||
state.remove( id ); state.save();
|
||||
delete state;
|
||||
}
|
||||
else {
|
||||
body.slideDown( "fast", function() {
|
||||
if ( q.browser.mozilla ) { peek.css( "overflow", "auto" ); }
|
||||
});
|
||||
var state = new CookieSet( "galaxy.history.expand_state" );
|
||||
state.add( id ); state.save();
|
||||
delete state;
|
||||
}
|
||||
})
|
||||
})
|
||||
// Add AJAX delete buttons
|
||||
q( "a.historyItemDelete" ).each( function() {
|
||||
var data_id = this.id.split( "-" )[1];
|
||||
q(this).click( function() {
|
||||
q( '#progress-' + data_id ).show();
|
||||
q.ajax({
|
||||
url: "${h.url_for( action='delete_async', id='XXX' )}".replace( 'XXX', data_id ),
|
||||
error: function() { alert( "Delete failed" ) },
|
||||
success: function() { q( "#historyItem-" + data_id ).fadeOut( "fast", function() {
|
||||
q( "div#historyItemContainer-" + data_id ).remove();
|
||||
if ( q( "div.historyItemContainer" ).length < 1 ) {
|
||||
q ( "div#emptyHistoryMessage" ).show();
|
||||
}
|
||||
} ) }
|
||||
})
|
||||
return false;
|
||||
})
|
||||
})
|
||||
// Links with confirmation
|
||||
q( "a[@confirm]" ).click( function() {
|
||||
return confirm( q(this).attr( "confirm" ) )
|
||||
})
|
||||
// After all the above is applied, actually show the entire element.
|
||||
// This solves the problem of .hide() and .show() for the body div
|
||||
// not executing until after it's already rendered.
|
||||
q( "div#historyItem-$data.id" ).show()
|
||||
})
|
||||
</script>
|
||||
|
||||
#end def
|
||||
|
||||
#def render_dataset( $data, $hid )
|
||||
|
||||
#if $data.state in ["no state","",None]:
|
||||
#set $data_state = "queued"
|
||||
#else
|
||||
#set $data_state = $data.state
|
||||
#end if
|
||||
|
||||
<div class="historyItemWrapper historyItem historyItem-$data_state" id="historyItem-$data.id" style="display:none;">
|
||||
|
||||
##
|
||||
## Header row for history items (name, state, action buttons)
|
||||
##
|
||||
|
||||
<table cellpadding="0" cellspacing="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td>
|
||||
<div style='padding-right: 5px; display: none;' id="progress-$data.id">
|
||||
<img src="$h.url_for('/static/style/data_running.gif')" border="0" align="middle" >
|
||||
</div>
|
||||
#if $data_state == 'running'
|
||||
<div style='padding-right: 5px;'><img src="$h.url_for('/static/style/data_running.gif')" border="0" align="middle"></div>
|
||||
#elif $data_state == 'ok'
|
||||
#pass
|
||||
#else
|
||||
#set $src = $h.url_for( "/static/style/data_%s.png" % $data_state )
|
||||
<div style='padding-right: 5px;'><img src="$src" border="0" align="middle"></div>
|
||||
#end if
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<div style="float: right;"><a href="$h.url_for( 'display', id=data.id )" target="_top"><img src="$h.url_for('/static/images/eye_icon.png')" rollover="$h.url_for('/static/images/eye_icon_dark.png')" width='16' height='16' alt='display data' title='display data' class='displayButton' border='0'></a>
|
||||
<a href="edit?id=$data.id" target="galaxy_main"><img src="$h.url_for('/static/images/pencil_icon.png')" rollover="$h.url_for('/static/images/pencil_icon_dark.png')" width='16' height='16' alt='edit attributes' title='edit attributes' class='editButton' border='0'></a>
|
||||
<a href="delete?id=$data.id" class="historyItemDelete" id="historyItemDelter-${data.id}"><img src="$h.url_for('/static/images/delete_icon.png')" rollover="$h.url_for('/static/images/delete_icon_dark.png')" width='16' height='16' alt='delete' class='deleteButton' border='0'></a>
|
||||
<!--
|
||||
$h.link_to_remote( "<img src='%s' rollover='%s' width='16' height='16' alt='delete' class='deleteButton' border='0'>" % ( $h.url_for('/static/images/delete_icon.png'), $h.url_for('/static/images/delete_icon_dark.png') ),
|
||||
dict( url=$h.url( action="delete_async", id=$data.id ),
|
||||
before=( "$( 'progress-%s' ).show()" % $data.id ),
|
||||
success=( "delete_item( 'historyItem-%s' )" % $data.id ),
|
||||
failure="alert( 'delete failed' )" ),
|
||||
href="delete?id=%d" % $data.id,
|
||||
title='delete this item' ) -->
|
||||
</div>
|
||||
<span class="historyItemTitle"><b>$hid: $data.display_name</b></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
##
|
||||
## Body for history items, extra info and actions, data "peek"
|
||||
##
|
||||
|
||||
<div id="info$data.id" class="historyItemBody">
|
||||
#if $data_state == "queued"
|
||||
<div>Job is waiting to run</div>
|
||||
#elif $data_state == "running"
|
||||
<div>Job is currently running</div>
|
||||
#elif $data_state == "error"
|
||||
<div>
|
||||
An error occurred running this job: <i>$data.display_info.strip()</i>,
|
||||
<a href="${h.url_for( controller='dataset', action='errors', id=$data.id )}" target="galaxy_main">report this error</a>
|
||||
</div>
|
||||
#elif $data_state == "empty"
|
||||
<div>No data: <i>$data.display_info</i></div>
|
||||
#else
|
||||
<div>
|
||||
$data.blurb,
|
||||
format: <span class="$data.ext">$data.ext</span>,
|
||||
database:
|
||||
#if $data.dbkey == '?'
|
||||
<a href="edit?id=$data.id" target="galaxy_main"><span class="$data.dbkey">$data.dbkey</span></a>
|
||||
#else
|
||||
<span class="$data.dbkey">$data.dbkey</span>
|
||||
#end if
|
||||
</div>
|
||||
<div class="info">Info: $data.display_info </div>
|
||||
<div>
|
||||
#if $data.has_data:
|
||||
<a href="display?id=$data.id&tofile=yes&toext=$data.ext" target="_blank">save</a>
|
||||
#for $display_app in $data.datatype.get_display_types():
|
||||
#set $display_links = $data.datatype.get_display_links($data, $display_app, $app, $request.base)
|
||||
#if $len($display_links) > 0:
|
||||
| $data.datatype.get_display_label($display_app)
|
||||
#for $display_name, $display_link in display_links:
|
||||
<a target="_blank" href="$display_link">$display_name</a>
|
||||
#end for
|
||||
#end if
|
||||
#end for
|
||||
#end if
|
||||
</div>
|
||||
#if $data.peek != "no peek"
|
||||
<div><pre id="peek$data.id" class="peek">$data.display_peek</pre></div>
|
||||
#end if
|
||||
#end if
|
||||
|
||||
##
|
||||
## Child datasets
|
||||
##
|
||||
|
||||
#if $len( $data.children ) > 0:
|
||||
<div>
|
||||
There are ${len( $data.children )} secondary datasets.
|
||||
#for $idx, $child_assoc in $enumerate($data.children)
|
||||
#set $child = $child_assoc.child
|
||||
$render_dataset( $child, $idx + 1 )
|
||||
#end for
|
||||
</div>
|
||||
#end if
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
#end def
|
||||
|
||||
## this is necessary because this dataset remains in history.active_datasets
|
||||
## after deletion, until the history is reloaded
|
||||
## FIXME: still necessary now that we don't re-pull finished datasets? test.
|
||||
#if $data.deleted is not True
|
||||
$render_script( $data )
|
||||
$render_dataset( $data, $hid )
|
||||
#end if
|
||||
@@ -0,0 +1 @@
|
||||
$data.state
|
||||
+63
-78
@@ -1,14 +1,13 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
|
||||
#set $refresh = bool ( [ data for data in $history.active_datasets if data.state in ['running', 'queued', '', None ] ] )
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Galaxy History</title>
|
||||
|
||||
#if $refresh
|
||||
<meta http-equiv="refresh" content="10">
|
||||
## This is now only necessary for tests
|
||||
#set $running = bool ( [ data for data in $history.active_datasets if data.state in ['running', 'queued', '', None ] ] )
|
||||
#if $running
|
||||
<!-- running: do not change this comment, used by TwillTestCase.wait -->
|
||||
#end if
|
||||
|
||||
@@ -22,6 +21,7 @@
|
||||
## <script defer type="text/javascript" src="/static/scripts/ie_pngfix.js"></script>
|
||||
## <![endif]-->
|
||||
|
||||
<script type="text/javascript" src="$h.url_for('/static/scripts/prototype.js')"></script>
|
||||
<script type="text/javascript" src="$h.url_for('/static/scripts/jquery.js')"></script>
|
||||
<script type="text/javascript" src="$h.url_for('/static/scripts/jquery.cookie.js')"></script>
|
||||
<script type="text/javascript" src="$h.url_for('/static/scripts/cookie_set.js')"></script>
|
||||
@@ -29,35 +29,6 @@
|
||||
<script type="text/javascript">
|
||||
var q = jQuery.noConflict();
|
||||
q( document ).ready( function() {
|
||||
q( "div.historyItemBody" ).hide();
|
||||
// Load saved state and show as neccesary
|
||||
var state = new CookieSet( "galaxy.history.expand_state" );
|
||||
for ( id in state.store ) { q( "#" + id ).find( "div.historyItemBody" ).show(); }
|
||||
// If Mozilla, hide scrollbars in hidden items since they cause animation bugs
|
||||
if ( q.browser.mozilla ) {
|
||||
q( "div.historyItemBody" ).each( function() {
|
||||
if ( ! q(this).is( ":visible" ) ) q(this).find( "pre.peek" ).css( "overflow", "hidden" );
|
||||
})
|
||||
}
|
||||
// Add history item show / hide
|
||||
q( "div.historyItemWrapper" ).each( function() {
|
||||
var id = this.id;
|
||||
var body = q(this).children( "div.historyItemBody" );
|
||||
var peek = body.find( "pre.peek" )
|
||||
q(this).children( "table" ).find( "span.historyItemTitle" ).wrap( "<a href='#'></a>" ).click( function() {
|
||||
if ( body.is(":visible") ) {
|
||||
if ( q.browser.mozilla ) { peek.css( "overflow", "hidden" ) }
|
||||
body.slideUp( "fast" );
|
||||
state.remove( id); state.save();
|
||||
}
|
||||
else {
|
||||
body.slideDown( "fast", function() {
|
||||
if ( q.browser.mozilla ) { peek.css( "overflow", "auto" ); }
|
||||
});
|
||||
state.add( id ); state.save();
|
||||
}
|
||||
})
|
||||
})
|
||||
// Collapse all
|
||||
q("#top-links").append( "| " ).append( q("<a href='#'>collapse all</a>").click( function() {
|
||||
q( "div.historyItemBody:visible" ).each( function() {
|
||||
@@ -67,6 +38,7 @@
|
||||
}
|
||||
q(this).slideUp( "fast" );
|
||||
})
|
||||
var state = new CookieSet( "galaxy.history.expand_state" );
|
||||
state.removeAll().save();
|
||||
}))
|
||||
// Add footer show / hide
|
||||
@@ -78,37 +50,37 @@
|
||||
else { menu.slideDown( "fast" ) }
|
||||
}))
|
||||
})
|
||||
// Add AJAX delete buttons
|
||||
q( "a.historyItemDelete" ).each( function() {
|
||||
var data_id = this.id.split( "-" )[1];
|
||||
q(this).click( function() {
|
||||
q( '#progress-' + data_id ).show();
|
||||
q.ajax({
|
||||
url: "${h.url_for( action='delete_async', id='XXX' )}".replace( 'XXX', data_id ),
|
||||
error: function() { alert( "Delete failed" ) },
|
||||
success: function() { q( "#historyItem-" + data_id ).fadeOut( "fast", function() { q(this).remove(); } ) }
|
||||
})
|
||||
return false;
|
||||
})
|
||||
})
|
||||
// Links with confirmation
|
||||
q( "a[@confirm]" ).click( function() {
|
||||
return confirm( q(this).attr( "confirm" ) )
|
||||
})
|
||||
// Refresh
|
||||
#if $refresh:
|
||||
function add_refresh( i ) {
|
||||
if ( i > 0 ) {
|
||||
q( "#refreshCounterSpan" ).text( i.toString() );
|
||||
setTimeout( function() { add_refresh( i - 1 ) }, 1000 );
|
||||
}
|
||||
else {
|
||||
window.location.href = 'history';
|
||||
}
|
||||
}
|
||||
add_refresh( 9 )
|
||||
#end if
|
||||
})
|
||||
function updater( id, state_url, code_url, orig_state ) {
|
||||
this.id = id
|
||||
this.state_url = state_url
|
||||
this.code_url = code_url
|
||||
this.old_state = orig_state
|
||||
this.stop_states = new Array( "ok", "error" );
|
||||
}
|
||||
updater.prototype.go = function() {
|
||||
stop_states = new Array( "ok", "error" );
|
||||
if (stop_states.indexOf(this.old_state) >= 0) { return; }
|
||||
this.executer = new PeriodicalExecuter( function() {
|
||||
## IE will cache if we use a GET
|
||||
## this.request = new Ajax.Request( this.state_url, {asynchronous:true, method:"get",
|
||||
this.request = new Ajax.Request( this.state_url, {asynchronous:true,
|
||||
onSuccess:function () {
|
||||
var new_state = this.request.getHeader('x-dataset-state');
|
||||
if (stop_states.indexOf(new_state) >= 0) { this.executer.stop(); }
|
||||
if (this.old_state != new_state) {
|
||||
new Ajax.Updater('historyItemContainer-' + this.id, this.code_url,
|
||||
## {asynchronous:true, method:"get", evalScripts:true});
|
||||
{asynchronous:true, evalScripts:true});
|
||||
}
|
||||
this.old_state = new_state;
|
||||
}.bind(this)
|
||||
});
|
||||
}.bind(this), 3 );
|
||||
}
|
||||
updater.prototype.stop = function() {
|
||||
this.executer.stop();
|
||||
}
|
||||
</script>
|
||||
|
||||
<![if gte IE 7]>
|
||||
@@ -160,11 +132,7 @@ div#footer {
|
||||
<body class="historyPage">
|
||||
|
||||
<div id="top-links" class="historyLinks">
|
||||
#if $refresh
|
||||
<a href="$h.url_for('/history')">refreshing in <span id="refreshCounterSpan">10</span> sec</a>
|
||||
#else
|
||||
<a href="$h.url_for('/history')">refresh</a>
|
||||
#end if
|
||||
<a href="$h.url_for('/history')">refresh</a>
|
||||
</div>
|
||||
|
||||
#if $history.deleted
|
||||
@@ -178,6 +146,7 @@ div#footer {
|
||||
## Render the dataset `$data`, using `$hid` as the displayed id
|
||||
##
|
||||
|
||||
## FIXME: duplicated in dataset_code, argh!
|
||||
#def render_dataset( $data, $hid )
|
||||
|
||||
#if $data.state in ["no state","",None]:
|
||||
@@ -208,9 +177,9 @@ div#footer {
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<div style="float: right;"><a href="$h.url_for( 'display', id=data.id )" target="_top"><img src="$h.url_for('/static/images/eye_icon.png')" rollover="$h.url_for('/static/images/eye_icon_dark.png')" width='16' height='16' alt='display data' title='display data' class='displayButton' border='0'></a>#*
|
||||
*#<a href="edit?id=$data.id" target="galaxy_main"><img src="$h.url_for('/static/images/pencil_icon.png')" rollover="$h.url_for('/static/images/pencil_icon_dark.png')" width='16' height='16' alt='edit attributes' title='edit attributes' class='editButton' border='0'></a>#*
|
||||
*#<a href="delete?id=$data.id" class="historyItemDelete" id="historyItemDelter-${data.id}"><img src="$h.url_for('/static/images/delete_icon.png')" rollover="$h.url_for('/static/images/delete_icon_dark.png')" width='16' height='16' alt='delete' class='deleteButton' border='0'></a>
|
||||
<div style="float: right;"><a href="$h.url_for( 'display', id=data.id )" target="_top"><img src="$h.url_for('/static/images/eye_icon.png')" rollover="$h.url_for('/static/images/eye_icon_dark.png')" width='16' height='16' alt='display data' title='display data' class='displayButton' border='0'></a>
|
||||
<a href="edit?id=$data.id" target="galaxy_main"><img src="$h.url_for('/static/images/pencil_icon.png')" rollover="$h.url_for('/static/images/pencil_icon_dark.png')" width='16' height='16' alt='edit attributes' title='edit attributes' class='editButton' border='0'></a>
|
||||
<a href="delete?id=$data.id" class="historyItemDelete" id="historyItemDelter-${data.id}"><img src="$h.url_for('/static/images/delete_icon.png')" rollover="$h.url_for('/static/images/delete_icon_dark.png')" width='16' height='16' alt='delete' class='deleteButton' border='0'></a>
|
||||
<!--
|
||||
$h.link_to_remote( "<img src='%s' rollover='%s' width='16' height='16' alt='delete' class='deleteButton' border='0'>" % ( $h.url_for('/static/images/delete_icon.png'), $h.url_for('/static/images/delete_icon_dark.png') ),
|
||||
dict( url=$h.url( action="delete_async", id=$data.id ),
|
||||
@@ -276,7 +245,7 @@ div#footer {
|
||||
##
|
||||
## Child datasets
|
||||
##
|
||||
|
||||
|
||||
#if $len( $data.children ) > 0:
|
||||
#set $children = []
|
||||
#for $child_assoc in $data.children:
|
||||
@@ -293,24 +262,40 @@ div#footer {
|
||||
</div>
|
||||
#end if
|
||||
#end if
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
#end def
|
||||
|
||||
#if $len($history.active_datasets)<1
|
||||
<div class="infomessagesmall">
|
||||
Your history is empty. Click 'Get Data' on the left pane to start
|
||||
</div>
|
||||
<div class="infomessagesmall" id="emptyHistoryMessage">
|
||||
#else
|
||||
## Render all active (not deleted) datasets, ordered from newest to oldest
|
||||
#for $data in reversed( $history.active_datasets )
|
||||
#if $data.visible:
|
||||
$render_dataset( $data, $data.hid )
|
||||
## FIXME: uncessary overhead here, find a way to prevent this if javascript is on
|
||||
<div class="historyItemContainer" id="historyItemContainer-$data.id"><noscript>
|
||||
$render_dataset( $data, $data.hid )
|
||||
</noscript></div>
|
||||
#end if
|
||||
#end for
|
||||
<script type="text/javascript">
|
||||
#for $data in reversed( $history.active_datasets )
|
||||
#if $data.visible:
|
||||
#set $state_url = $h.url_for( action='dataset_state', id=$data.id )
|
||||
#set $code_url = $h.url_for( action='dataset_code', id=$data.id, hid=$data.hid )
|
||||
## new Ajax.Updater('historyItemContainer-$data.id', '$code_url', {asynchronous:true, method:"get", evalScripts:"true"});
|
||||
new Ajax.Updater('historyItemContainer-$data.id', '$code_url', {asynchronous:true, evalScripts:"true"});
|
||||
var updater_${data.id} = new updater( $data.id, '$state_url', '$code_url', '$data.state' );
|
||||
updater_${data.id}.go();
|
||||
#end if
|
||||
#end for
|
||||
</script>
|
||||
<div class="infomessagesmall" id="emptyHistoryMessage" style="display:none;">
|
||||
#end if
|
||||
Your history is empty. Click 'Get Data' on the left pane to start
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -346,4 +331,4 @@ div#footer {
|
||||
</div>
|
||||
#end if
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user