details:
http://www.bx.psu.edu/hg/galaxy/rev/846f6a7ee80c
changeset: 2556:846f6a7ee80c
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Wed Aug 12 15:56:03 2009 -0400
description:
1) Enhancements for sharing histories based on feedback from Assaf Gordon ( resolves
ticket # 125 ):
- Make "Histories shared with you by others" page a grid
- Eliminate the option to clone deleted or all items for the user to which the history has
been shared
- Eliminate the "don't share" option when sharing histories
- When the "share anyway" option is chosen, make sure there is something in
"no_change_needed" dict
2) Fix library view template display for ldda information page ( resolves ticket 128 )
13 file(s) affected in this change:
lib/galaxy/web/controllers/admin.py
lib/galaxy/web/controllers/history.py
lib/galaxy/web/controllers/library.py
lib/galaxy/web/framework/helpers/grids.py
templates/admin/requests/grid.mako
templates/history/grid.mako
templates/history/list_shared.mako
templates/history/options.mako
templates/history/share.mako
templates/history/shared_grid.mako
templates/history/stored_grid.mako
test/base/twilltestcase.py
test/functional/test_history_functions.py
diffs (1262 lines):
diff -r 2630316ff75e -r 846f6a7ee80c lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py Tue Aug 11 16:56:47 2009 -0400
+++ b/lib/galaxy/web/controllers/admin.py Wed Aug 12 15:56:03 2009 -0400
@@ -1214,7 +1214,6 @@
template = info_association.template
# See if we have any field contents
info = info_association.info
- log.debug("####In library_dataset_dataset_association, info.content:
%s" % str( info.content))
if info:
field_contents = {}
for index, value in enumerate( info.content ):
diff -r 2630316ff75e -r 846f6a7ee80c lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Tue Aug 11 16:56:47 2009 -0400
+++ b/lib/galaxy/web/controllers/history.py Wed Aug 12 15:56:03 2009 -0400
@@ -12,7 +12,6 @@
# States for passing messages
SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning",
"error"
-
class HistoryListGrid( grids.Grid ):
# Custom column types
@@ -70,8 +69,43 @@
def apply_default_filter( self, trans, query ):
return query.filter_by( user=trans.user, purged=False )
+class SharedHistoryListGrid( grids.Grid ):
+ # Custom column types
+ class DatasetsByStateColumn( grids.GridColumn ):
+ def get_value( self, trans, grid, history ):
+ 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( '' )
+ return rval
+ class SharedByColumn( grids.GridColumn ):
+ def get_value( self, trans, grid, history ):
+ return history.user.email
+ # Grid definition
+ title = "Histories shared with you by others"
+ model_class = model.History
+ default_sort_key = "-update_time"
+ columns = [
+ grids.GridColumn( "Name", key="name" ),
+ DatasetsByStateColumn( "Datasets (by state)", ncells=4 ),
+ 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" )
+ ]
+ operations = [
+ grids.GridOperation( "Clone" ),
+ grids.GridOperation( "Unshare" )
+ ]
+ standard_filters = []
+ def build_initial_query( self, session ):
+ return session.query( self.model_class ).join( 'users_shared_with' )
+ def apply_default_filter( self, trans, query ):
+ return query.filter( model.HistoryUserShareAssociation.user == trans.user )
+
class HistoryController( BaseController ):
-
@web.expose
def index( self, trans ):
return ""
@@ -80,7 +114,8 @@
"""XML history list for functional tests"""
return trans.fill_template( "/history/list_as_xml.mako" )
- list_grid = HistoryListGrid()
+ stored_list_grid = HistoryListGrid()
+ shared_list_grid = SharedHistoryListGrid()
@web.expose
@web.require_login( "work with multiple histories" )
@@ -91,7 +126,6 @@
if 'operation' in kwargs:
history_ids = util.listify( kwargs.get( 'id', [] ) )
histories = []
- shared_by_others = []
operation = kwargs['operation'].lower()
if operation == "share":
return self.share( trans, **kwargs )
@@ -127,7 +161,7 @@
status, message = self._list_undelete( trans, histories )
trans.sa_session.flush()
# Render the list view
- return self.list_grid( trans, status=status, message=message,
template='/history/grid.mako', **kwargs )
+ return self.stored_list_grid( trans, status=status, message=message,
template='/history/stored_grid.mako', **kwargs )
def _list_delete( self, trans, histories ):
"""Delete histories"""
n_deleted = 0
@@ -195,18 +229,38 @@
# No message
return None, None
@web.expose
- def list_shared( self, trans, **kwd ):
+ def list_shared( self, trans, **kwargs ):
"""List histories shared with current user by
others"""
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- shared_by_others = trans.sa_session \
- .query( model.HistoryUserShareAssociation ) \
- .filter_by( user=trans.user ) \
- .join( 'history' ) \
- .filter( model.History.deleted == False ) \
- .order_by( desc( model.History.update_time ) ) \
- .all()
- return trans.fill_template( "/history/list_shared.mako",
shared_by_others=shared_by_others, msg=msg, messagetype='done' )
+ msg = util.restore_text( kwargs.get( 'msg', '' ) )
+ status = message = None
+ if 'operation' in kwargs:
+ id = kwargs.get( 'id', None )
+ operation = kwargs['operation'].lower()
+ if operation == "clone":
+ if not id:
+ message = "Select a history to clone"
+ return self.shared_list_grid( trans, status='error',
message=message, template='/history/shared_grid.mako', **kwargs )
+ # When cloning shared histories, only copy active datasets
+ new_kwargs = { 'clone_choice' : 'active' }
+ return self.clone( trans, id, **new_kwargs )
+ elif operation == 'unshare':
+ if not id:
+ message = "Select a history to unshare"
+ return self.shared_list_grid( trans, status='error',
message=message, template='/history/shared_grid.mako', **kwargs )
+ ids = util.listify( id )
+ histories = []
+ for history_id in ids:
+ history = get_history( trans, history_id, check_ownership=False )
+ histories.append( history )
+ for history in histories:
+ # Current user is the user with which the histories were shared
+ association = trans.app.model.HistoryUserShareAssociation.filter_by(
user=trans.user, history=history ).one()
+ association.delete()
+ association.flush()
+ message = "Unshared %d shared histories" % len( ids )
+ status = 'done'
+ # Render the list view
+ return self.shared_list_grid( trans, status=status, message=message,
template='/history/shared_grid.mako', **kwargs )
@web.expose
def delete_current( self, trans ):
"""Delete just the active history -- this does not require a
logged in user."""
@@ -323,6 +377,9 @@
can_change, cannot_change, no_change_needed, unique_no_change_needed,
send_to_err = \
self._populate_restricted( trans, user, histories, send_to_users, None,
send_to_err, unique=True )
send_to_err += err_msg
+ if cannot_change and not no_change_needed and not can_change:
+ send_to_err = "The histories you are sharing do not contain any
datasets that can be accessed by the users with which you are sharing."
+ return trans.fill_template( "/history/share.mako",
histories=histories, email=email, send_to_err=send_to_err )
if can_change or cannot_change:
return trans.fill_template( "/history/share.mako",
histories=histories,
@@ -350,8 +407,6 @@
email=email,
err_msg=err_msg,
share_button=True ) )
- if action == "no_share":
- trans.response.send_redirect( url_for( controller='root',
action='history_options' ) )
user = trans.get_user()
histories, send_to_users, send_to_err = self._get_histories_and_users( trans,
user, id, email )
send_to_err = ''
@@ -629,29 +684,38 @@
@web.expose
@web.require_login( "clone shared Galaxy history" )
def clone( self, trans, id, **kwd ):
- history = get_history( trans, id, check_ownership=False )
+ """Clone a list of histories"""
params = util.Params( kwd )
+ ids = util.listify( id )
+ histories = []
+ for history_id in ids:
+ history = get_history( trans, history_id, check_ownership=False )
+ histories.append( history )
clone_choice = params.get( 'clone_choice', None )
if not clone_choice:
return trans.fill_template( "/history/clone.mako", history=history
)
user = trans.get_user()
- if history.user == user:
- owner = True
+ for history in histories:
+ if history.user == user:
+ owner = True
+ else:
+ if trans.sa_session.query( trans.app.model.HistoryUserShareAssociation )
\
+ .filter_by( user=user, history=history ).count() == 0:
+ return trans.show_error_message( "The history you are attempting
to clone is not owned by you or shared with you. " )
+ owner = False
+ name = "Clone of '%s'" % history.name
+ if not owner:
+ name += " shared by '%s'" % history.user.email
+ if clone_choice == 'activatable':
+ new_history = history.copy( name=name, target_user=user, activatable=True
)
+ elif clone_choice == 'active':
+ name += " (active items only)"
+ new_history = history.copy( name=name, target_user=user )
+ if len( histories ) == 1:
+ msg = 'Clone with name "%s" is now included in your previously
stored histories.' % new_history.name
else:
- if trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ) \
- .filter_by( user=user, history=history ).count() == 0:
- return trans.show_error_message( "The history you are attempting to
clone is not owned by you or shared with you. " )
- owner = False
- name = "Clone of '%s'" % history.name
- if not owner:
- name += " shared by '%s'" % history.user.email
- if clone_choice == 'activatable':
- new_history = history.copy( name=name, target_user=user, activatable=True )
- elif clone_choice == 'active':
- name += " (active items only)"
- new_history = history.copy( name=name, target_user=user )
- # Render the list view
- return trans.show_ok_message( 'Clone with name "%s" is now included
in your list of stored histories.' % new_history.name )
+ msg = '%d cloned histories are now included in your previously stored
histories.' % len( histories )
+ return trans.show_ok_message( msg )
## ---- Utility methods -------------------------------------------------------
diff -r 2630316ff75e -r 846f6a7ee80c lib/galaxy/web/controllers/library.py
--- a/lib/galaxy/web/controllers/library.py Tue Aug 11 16:56:47 2009 -0400
+++ b/lib/galaxy/web/controllers/library.py Wed Aug 12 15:56:03 2009 -0400
@@ -469,7 +469,7 @@
msg=util.sanitize_text(
msg ),
messagetype='error' ) )
# See if we have any associated templates
- info_association = folder.get_info_association()
+ info_association = ldda.get_info_association()
if info_association:
template = info_association.template
# See if we have any field contents
diff -r 2630316ff75e -r 846f6a7ee80c lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py Tue Aug 11 16:56:47 2009 -0400
+++ b/lib/galaxy/web/framework/helpers/grids.py Wed Aug 12 15:56:03 2009 -0400
@@ -156,9 +156,7 @@
elif column_filter == "All":
del filter_args[self.key]
return query
-
-
-
+
class GridOperation( object ):
def __init__( self, label, key=None, condition=None, allow_multiple=True ):
self.label = label
diff -r 2630316ff75e -r 846f6a7ee80c templates/admin/requests/grid.mako
--- a/templates/admin/requests/grid.mako Tue Aug 11 16:56:47 2009 -0400
+++ b/templates/admin/requests/grid.mako Wed Aug 12 15:56:03 2009 -0400
@@ -101,7 +101,7 @@
%if not len(query.all()):
- There are no request(s).
+ There are no requests.
%else:
<form name="history_actions" action="${url()}"
method="post" >
<table class="grid">
diff -r 2630316ff75e -r 846f6a7ee80c templates/history/grid.mako
--- a/templates/history/grid.mako Tue Aug 11 16:56:47 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-<%inherit file="/base.mako"/>
-<%def name="title()">${grid.title}</%def>
-
-%if message:
- <p>
- <div class="${message_type}message
transient-message">${message}</div>
- <div style="clear: both"></div>
- </p>
-%endif
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- <script type="text/javascript">
- ## TODO: generalize and move into galaxy.base.js
- $(document).ready(function() {
- $(".grid").each( function() {
- var grid = this;
- var checkboxes =
$(this).find("input.grid-row-select-checkbox");
- var update = $(this).find( "span.grid-selected-count" );
- $(checkboxes).each( function() {
- $(this).change( function() {
- var n = $(checkboxes).filter("[checked]").size();
- update.text( n );
- });
- })
- });
- });
- ## Can this be moved into base.mako?
- %if refresh_frames:
- %if 'masthead' in refresh_frames:
- ## Refresh masthead == user changes (backward compatibility)
- if ( parent.user_changed ) {
- %if trans.user:
- parent.user_changed( "${trans.user.email}", ${int(
app.config.is_admin_user( trans.user ) )} );
- %else:
- parent.user_changed( null, false );
- %endif
- }
- %endif
- %if 'history' in refresh_frames:
- if ( parent.frames && parent.frames.galaxy_history ) {
- parent.frames.galaxy_history.location.href="${h.url_for(
controller='root', action='history')}";
- if ( parent.force_right_panel ) {
- parent.force_right_panel( 'show' );
- }
- }
- %endif
- %if 'tools' in refresh_frames:
- if ( parent.frames && parent.frames.galaxy_tools ) {
- parent.frames.galaxy_tools.location.href="${h.url_for(
controller='root', action='tool_menu')}";
- if ( parent.force_left_panel ) {
- parent.force_left_panel( 'show' );
- }
- }
- %endif
- %endif
- </script>
-</%def>
-
-<%def name="stylesheets()">
- <link href="${h.url_for('/static/style/base.css')}"
rel="stylesheet" type="text/css" />
- <style>
- ## Not generic to all grids -- move to base?
- .count-box {
- min-width: 1.1em;
- padding: 5px;
- border-width: 1px;
- border-style: solid;
- text-align: center;
- display: inline-block;
- }
- </style>
-</%def>
-
-<div class="grid-header">
- <h2>${grid.title}</h2>
- <span class="title">Filter:</span>
- %for i, filter in enumerate( grid.standard_filters ):
- %if i > 0:
- <span>|</span>
- %endif
- <span class="filter"><a href="${url(
filter.get_url_args() )}">${filter.label}</a></span>
- %endfor
-</div>
-
-<form name="history_actions" action="${url()}"
method="post" >
- <table class="grid">
- <thead>
- <tr>
- <th></th>
- %for column in grid.columns:
- %if column.visible:
- <%
- href = ""
- extra = ""
- if column.sortable:
- if sort_key == column.key:
- if sort_order == "asc":
- href = url( sort=( "-" + column.key )
)
- extra = "↓"
- else:
- href = url( sort=( column.key ) )
- extra = "↑"
- else:
- href = url( sort=column.key )
- %>
- <th\
- %if column.ncells > 1:
- colspan="${column.ncells}"
- %endif
- >
- %if href:
- <a
href="${href}">${column.label}</a>
- %else:
- ${column.label}
- %endif
- <span>${extra}</span>
- </th>
- %endif
- %endfor
- <th></th>
- </tr>
- </thead>
- <tbody>
- %for i, item in enumerate( query ):
- <tr \
- %if current_item == item:
- class="current" \
- %endif
- >
- ## Item selection column
- <td style="width: 1.5em;">
- <input type="checkbox" name="id"
value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox"
/>
- </td>
- ## Data columns
- %for column in grid.columns:
- %if column.visible:
- <%
- # 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 ]
- %>
- %for cellnum, v in enumerate( value ):
- <%
- # Attach popup menu?
- if column.attach_popup and cellnum == 0:
- extra = '<a id="grid-%d-popup"
class="popup-arrow" style="display:
none;">▼</a>' % i
- else:
- extra = ""
- %>
- %if href:
- <td><a
href="${href}">${v}</a> ${extra}</td>
- %else:
- <td >${v}${extra}</td>
- %endif
- </td>
- %endfor
- %endif
- %endfor
- ## Actions column
- <td>
- <div popupmenu="grid-${i}-popup">
- %for operation in grid.operations:
- %if operation.allowed( item ):
- <a class="action-button"
href="${url( operation=operation.label, id=item.id
)}">${operation.label}</a>
- %endif
- %endfor
- </div>
- </td>
- </tr>
- %endfor
- </tbody>
- <tfoot>
- <tr>
- <td></td>
- <td colspan="100">
- For <span class="grid-selected-count"></span>
selected histories:
- %for operation in grid.operations:
- %if operation.allow_multiple:
- <input type="submit" name="operation"
value="${operation.label}" class="action-button">
- %endif
- %endfor
- </td>
- </tr>
- </tfoot>
- </table>
-</form>
diff -r 2630316ff75e -r 846f6a7ee80c templates/history/list_shared.mako
--- a/templates/history/list_shared.mako Tue Aug 11 16:56:47 2009 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-%if msg:
- ${render_msg( msg, messagetype )}
-%endif
-
-%if shared_by_others:
- <table class="colored" border="0" cellspacing="0"
cellpadding="0" width="100%">
- <tr class="header">
- <th>Name</th>
- <th>Owner</th>
- </tr>
- %for i, association in enumerate( shared_by_others ):
- <% history = association.history %>
- <tr>
- <td>
- ${history.name}
- <a id="shared-${i}-popup" class="popup-arrow"
style="display: none;">▼</a>
- <div popupmenu="shared-${i}-popup">
- <a class="action-button" href="${h.url_for(
controller='history', action='clone', id=trans.security.encode_id(
history.id ) )}">Clone</a>
- </div>
- </td>
- <td>${history.user.email}</td>
- </tr>
- %endfor
- </table>
-%else:
- No histories have been shared with you.
-%endif
diff -r 2630316ff75e -r 846f6a7ee80c templates/history/options.mako
--- a/templates/history/options.mako Tue Aug 11 16:56:47 2009 -0400
+++ b/templates/history/options.mako Wed Aug 12 15:56:03 2009 -0400
@@ -12,7 +12,7 @@
<ul>
%if user:
- <li><a href="${h.url_for( controller='history',
action='list')}" target="galaxy_main">List</a> previously
stored histories</li>
+ <li><a href="${h.url_for( controller='history',
action='list')}" target="galaxy_main">Previously</a>
stored histories</li>
%if len( history.active_datasets ) > 0:
<li><a href="${h.url_for( controller='root',
action='history_new' )}">Create</a> a new empty history</li>
<li><a href="${h.url_for( controller='workflow',
action='build_from_current_history' )}">Construct workflow</a> from
current history</li>
@@ -27,6 +27,6 @@
<li><a href="${h.url_for( controller='history',
action='rename', id=trans.security.encode_id( history.id ) )}"
target="galaxy_main">Rename</a> current history (stored as
"${history.name}")</li>
<li><a href="${h.url_for( controller='history',
action='delete_current' )}" confirm="Are you sure you want to delete the
current history?">Delete</a> current history</div>
%if user and user.histories_shared_by_others:
- <li><a href="${h.url_for( controller='history',
action='list_shared')}" target="galaxy_main">List</a>
histories shared with you by others</li>
+ <li><a href="${h.url_for( controller='history',
action='list_shared')}" target="galaxy_main">Histories</a>
shared with you by others</li>
%endif
</ul>
diff -r 2630316ff75e -r 846f6a7ee80c templates/history/share.mako
--- a/templates/history/share.mako Tue Aug 11 16:56:47 2009 -0400
+++ b/templates/history/share.mako Wed Aug 12 15:56:03 2009 -0400
@@ -57,134 +57,136 @@
</form>
%else:
## We are sharing restricted histories
- <form name='share_restricted' id=share_restricted'
action="${h.url_for( controller='history', action='share_restricted'
)}" method="post">
- %if send_to_err:
- <div style="clear: both"></div>
- <div class="form-row">
- <div
class="errormessage">${send_to_err}</div>
- </div>
- %endif
- ## Needed for rebuilding dicts
- <input type="hidden" name="email"
value="${email}" size="40">
- %for history in histories:
- <input type="hidden" name="id"
value="${trans.security.encode_id( history.id )}">
- %endfor
- %if no_change_needed:
- ## no_change_needed looks like: {historyX : [hda, hda], historyY :
[hda] }
- <div style="clear: both"></div>
- <div class="form-row">
- <div class="donemessage">
- The following datasets can be shared with ${email} with no
changes
- </div>
- </div>
- %for history, hdas in no_change_needed.items():
- <div class="form-row">
- <label>History</label>
- ${history.name}
- </div>
+ %if no_change_needed or can_change:
+ <form name='share_restricted' id=share_restricted'
action="${h.url_for( controller='history', action='share_restricted'
)}" method="post">
+ %if send_to_err:
<div style="clear: both"></div>
<div class="form-row">
- <label>Datasets</label>
+ <div
class="errormessage">${send_to_err}</div>
</div>
- %for hda in hdas:
- <div class="form-row">
- ${hda.name}
- %if hda.deleted:
- (deleted)
- %endif
- </div>
- %endfor
+ %endif
+ ## Needed for rebuilding dicts
+ <input type="hidden" name="email"
value="${email}" size="40">
+ %for history in histories:
+ <input type="hidden" name="id"
value="${trans.security.encode_id( history.id )}">
%endfor
- %endif
- %if can_change:
- ## can_change looks like: {historyX : [hda, hda], historyY : [hda] }
- <div style="clear: both"></div>
- <div class="form-row">
- <div class="warningmessage">
- The following datasets can be shared with ${email} by
updating their permissions
- </div>
- </div>
- %for history, hdas in can_change.items():
- <div class="form-row">
- <label>History</label>
- ${history.name}
- </div>
+ %if no_change_needed:
+ ## no_change_needed looks like: {historyX : [hda, hda], historyY
: [hda] }
<div style="clear: both"></div>
<div class="form-row">
- <label>Datasets</label>
- </div>
- %for hda in hdas:
+ <div class="donemessage">
+ The following datasets can be shared with ${email} with
no changes
+ </div>
+ </div>
+ %for history, hdas in no_change_needed.items():
<div class="form-row">
- ${hda.name}
- %if hda.deleted:
- (deleted)
- %endif
+ <label>History</label>
+ ${history.name}
</div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <label>Datasets</label>
+ </div>
+ %for hda in hdas:
+ <div class="form-row">
+ ${hda.name}
+ %if hda.deleted:
+ (deleted)
+ %endif
+ </div>
+ %endfor
%endfor
- %endfor
- %endif
- %if cannot_change:
- ## cannot_change looks like: {historyX : [hda, hda], historyY : [hda]
}
- <div style="clear: both"></div>
- <div class="form-row">
- <div class="errormessage">
- The following datasets cannot be shared with ${email} because
you are not authorized to
- change the permissions on them
- </div>
- </div>
- %for history, hdas in cannot_change.items():
- <div class="form-row">
- <label>History</label>
- ${history.name}
- </div>
+ %endif
+ %if can_change:
+ ## can_change looks like: {historyX : [hda, hda], historyY :
[hda] }
<div style="clear: both"></div>
<div class="form-row">
- <label>Datasets</label>
+ <div class="warningmessage">
+ The following datasets can be shared with ${email} by
updating their permissions
+ </div>
</div>
- %for hda in hdas:
+ %for history, hdas in can_change.items():
<div class="form-row">
- ${hda.name}
- %if hda.deleted:
- (deleted)
- %endif
+ <label>History</label>
+ ${history.name}
</div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <label>Datasets</label>
+ </div>
+ %for hda in hdas:
+ <div class="form-row">
+ ${hda.name}
+ %if hda.deleted:
+ (deleted)
+ %endif
+ </div>
+ %endfor
%endfor
- %endfor
- %endif
- <div class="toolFormTitle"></div>
- <div class="form-row">
- Deleted items can be eliminated by the users with which you are
sharing the history.
- </div>
- <div class="form-row">
- <label>How would you like to proceed?</label>
- </div>
- %if can_change:
+ %endif
+ %if cannot_change:
+ ## cannot_change looks like: {historyX : [hda, hda], historyY :
[hda] }
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <div class="errormessage">
+ The following datasets cannot be shared with ${email}
because you are not authorized to
+ change the permissions on them
+ </div>
+ </div>
+ %for history, hdas in cannot_change.items():
+ <div class="form-row">
+ <label>History</label>
+ ${history.name}
+ </div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <label>Datasets</label>
+ </div>
+ %for hda in hdas:
+ <div class="form-row">
+ ${hda.name}
+ %if hda.deleted:
+ (deleted)
+ %endif
+ </div>
+ %endfor
+ %endfor
+ %endif
+ <div class="toolFormTitle"></div>
<div class="form-row">
- <input type="radio" name="action"
value="public"> Make datasets public so anyone can access them
- %if cannot_change:
- (where possible)
- %endif
+ <label>How would you like to proceed?</label>
</div>
+ %if can_change:
+ <div class="form-row">
+ <input type="radio" name="action"
value="public"> Make datasets public so anyone can access them
+ %if cannot_change:
+ (where possible)
+ %endif
+ </div>
+ <div class="form-row">
+ %if no_change_needed:
+ <input type="radio" name="action"
value="private"> Make datasets private to me and the user(s) with whom I am
sharing
+ %else:
+ <input type="radio" name="action"
value="private" checked> Make datasets private to me and the user(s) with
whom I am sharing
+ %endif
+ %if cannot_change:
+ (where possible)
+ %endif
+ </div>
+ %endif
+ %if no_change_needed:
+ <div class="form-row">
+ <input type="radio" name="action"
value="share_anyway" checked> Share anyway
+ %if can_change:
+ (don't change any permissions)
+ %endif
+ </div>
+ %endif
<div class="form-row">
- <input type="radio" name="action"
value="private"> Make datasets private to me and the user(s) with whom I am
sharing
- %if cannot_change:
- (where possible)
- %endif
+ <input type="submit"
name="share_restricted_button" value="Go"><br/>
</div>
- %endif
- <div class="form-row">
- <input type="radio" name="action"
value="share_anyway"> Share anyway
- %if can_change:
- (don't change any permissions)
- %endif
- </div>
- <div class="form-row">
- <input type="radio" name="action"
value="no_share" checked> Don't share
- </div>
- <div class="form-row">
- <input type="submit"
name="share_restricted_button" value="Go"><br/>
- </div>
- </form>
+ </form>
+ %endif
%endif
</div>
</div>
diff -r 2630316ff75e -r 846f6a7ee80c templates/history/shared_grid.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/history/shared_grid.mako Wed Aug 12 15:56:03 2009 -0400
@@ -0,0 +1,197 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<%def name="title()">${grid.title}</%def>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ ## TODO: generalize and move into galaxy.base.js
+ $(document).ready(function() {
+ $(".grid").each( function() {
+ var grid = this;
+ var checkboxes =
$(this).find("input.grid-row-select-checkbox");
+ var update = $(this).find( "span.grid-selected-count" );
+ $(checkboxes).each( function() {
+ $(this).change( function() {
+ var n = $(checkboxes).filter("[checked]").size();
+ update.text( n );
+ });
+ })
+ });
+ });
+ ## Can this be moved into base.mako?
+ %if refresh_frames:
+ %if 'masthead' in refresh_frames:
+ ## Refresh masthead == user changes (backward compatibility)
+ if ( parent.user_changed ) {
+ %if trans.user:
+ parent.user_changed( "${trans.user.email}", ${int(
app.config.is_admin_user( trans.user ) )} );
+ %else:
+ parent.user_changed( null, false );
+ %endif
+ }
+ %endif
+ %if 'history' in refresh_frames:
+ if ( parent.frames && parent.frames.galaxy_history ) {
+ parent.frames.galaxy_history.location.href="${h.url_for(
controller='root', action='history')}";
+ if ( parent.force_right_panel ) {
+ parent.force_right_panel( 'show' );
+ }
+ }
+ %endif
+ %if 'tools' in refresh_frames:
+ if ( parent.frames && parent.frames.galaxy_tools ) {
+ parent.frames.galaxy_tools.location.href="${h.url_for(
controller='root', action='tool_menu')}";
+ if ( parent.force_left_panel ) {
+ parent.force_left_panel( 'show' );
+ }
+ }
+ %endif
+ %endif
+ </script>
+</%def>
+
+<%def name="stylesheets()">
+ <link href="${h.url_for('/static/style/base.css')}"
rel="stylesheet" type="text/css" />
+ <style>
+ ## Not generic to all grids -- move to base?
+ .count-box {
+ min-width: 1.1em;
+ padding: 5px;
+ border-width: 1px;
+ border-style: solid;
+ text-align: center;
+ display: inline-block;
+ }
+ </style>
+</%def>
+
+%if grid.standard_filters:
+ <div class="grid-header">
+ <h2>${grid.title}</h2>
+ <span class="title">Filter:</span>
+ %for i, filter in enumerate( grid.standard_filters ):
+ %if i > 0:
+ <span>|</span>
+ %endif
+ <span class="filter"><a href="${url(
filter.get_url_args() )}">${filter.label}</a></span>
+ %endfor
+ </div>
+%endif
+
+%if message:
+ <p>
+ <div class="${message_type}message
transient-message">${message}</div>
+ <div style="clear: both"></div>
+ </p>
+%endif
+%if msg:
+ ${render_msg( msg, messagetype )}
+%endif
+
+<form name="history_shared_by_others" action="${url()}"
method="post" >
+ <table class="grid">
+ <thead>
+ <tr>
+ <th></th>
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ href = ""
+ extra = ""
+ if column.sortable:
+ if sort_key == column.key:
+ if sort_order == "asc":
+ href = url( sort=( "-" + column.key )
)
+ extra = "↓"
+ else:
+ href = url( sort=( column.key ) )
+ extra = "↑"
+ else:
+ href = url( sort=column.key )
+ %>
+ <th\
+ %if column.ncells > 1:
+ colspan="${column.ncells}"
+ %endif
+ >
+ %if href:
+ <a
href="${href}">${column.label}</a>
+ %else:
+ ${column.label}
+ %endif
+ <span>${extra}</span>
+ </th>
+ %endif
+ %endfor
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ %for i, history in enumerate( query ):
+ <tr>
+ ## Item selection column
+ <td style="width: 1.5em;">
+ <input type="checkbox" name="id"
value=${trans.security.encode_id( history.id )} class="grid-row-select-checkbox"
/>
+ </td>
+ ## Data columns
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ # Link
+ link = column.get_link( trans, grid, history )
+ if link:
+ href = url( **link )
+ else:
+ href = None
+ # Value (coerced to list so we can loop)
+ value = column.get_value( trans, grid, history )
+ if column.ncells == 1:
+ value = [ value ]
+ %>
+ %for cellnum, v in enumerate( value ):
+ <%
+ # Attach popup menu?
+ if column.attach_popup and cellnum == 0:
+ extra = '<a id="grid-%d-popup"
class="popup-arrow" style="display:
none;">▼</a>' % i
+ else:
+ extra = ""
+ %>
+ %if href:
+ <td><a
href="${href}">${v}</a> ${extra}</td>
+ %else:
+ <td >${v}${extra}</td>
+ %endif
+ </td>
+ %endfor
+ %endif
+ %endfor
+ ## Actions column
+ <td>
+ <div popupmenu="grid-${i}-popup">
+ %for operation in grid.operations:
+ %if operation.allowed( history ):
+ <a class="action-button"
href="${url( operation=operation.label, id=history.id
)}">${operation.label}</a>
+ %endif
+ %endfor
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </tbody>
+ <tfoot>
+ <tr>
+ <td></td>
+ <td colspan="100">
+ For <span class="grid-selected-count"></span>
selected histories:
+ %for operation in grid.operations:
+ %if operation.allow_multiple:
+ <input type="submit" name="operation"
value="${operation.label}" class="action-button">
+ %endif
+ %endfor
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
diff -r 2630316ff75e -r 846f6a7ee80c templates/history/stored_grid.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/history/stored_grid.mako Wed Aug 12 15:56:03 2009 -0400
@@ -0,0 +1,196 @@
+<%inherit file="/base.mako"/>
+<%def name="title()">${grid.title}</%def>
+
+%if message:
+ <p>
+ <div class="${message_type}message
transient-message">${message}</div>
+ <div style="clear: both"></div>
+ </p>
+%endif
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ ## TODO: generalize and move into galaxy.base.js
+ $(document).ready(function() {
+ $(".grid").each( function() {
+ var grid = this;
+ var checkboxes =
$(this).find("input.grid-row-select-checkbox");
+ var update = $(this).find( "span.grid-selected-count" );
+ $(checkboxes).each( function() {
+ $(this).change( function() {
+ var n = $(checkboxes).filter("[checked]").size();
+ update.text( n );
+ });
+ })
+ });
+ });
+ ## Can this be moved into base.mako?
+ %if refresh_frames:
+ %if 'masthead' in refresh_frames:
+ ## Refresh masthead == user changes (backward compatibility)
+ if ( parent.user_changed ) {
+ %if trans.user:
+ parent.user_changed( "${trans.user.email}", ${int(
app.config.is_admin_user( trans.user ) )} );
+ %else:
+ parent.user_changed( null, false );
+ %endif
+ }
+ %endif
+ %if 'history' in refresh_frames:
+ if ( parent.frames && parent.frames.galaxy_history ) {
+ parent.frames.galaxy_history.location.href="${h.url_for(
controller='root', action='history')}";
+ if ( parent.force_right_panel ) {
+ parent.force_right_panel( 'show' );
+ }
+ }
+ %endif
+ %if 'tools' in refresh_frames:
+ if ( parent.frames && parent.frames.galaxy_tools ) {
+ parent.frames.galaxy_tools.location.href="${h.url_for(
controller='root', action='tool_menu')}";
+ if ( parent.force_left_panel ) {
+ parent.force_left_panel( 'show' );
+ }
+ }
+ %endif
+ %endif
+ </script>
+</%def>
+
+<%def name="stylesheets()">
+ <link href="${h.url_for('/static/style/base.css')}"
rel="stylesheet" type="text/css" />
+ <style>
+ ## Not generic to all grids -- move to base?
+ .count-box {
+ min-width: 1.1em;
+ padding: 5px;
+ border-width: 1px;
+ border-style: solid;
+ text-align: center;
+ display: inline-block;
+ }
+ </style>
+</%def>
+
+%if grid.standard_filters:
+ <div class="grid-header">
+ <h2>${grid.title}</h2>
+ <span class="title">Filter:</span>
+ %for i, filter in enumerate( grid.standard_filters ):
+ %if i > 0:
+ <span>|</span>
+ %endif
+ <span class="filter"><a href="${url(
filter.get_url_args() )}">${filter.label}</a></span>
+ %endfor
+ </div>
+%endif
+
+<form name="history_actions" action="${url()}"
method="post" >
+ <table class="grid">
+ <thead>
+ <tr>
+ <th></th>
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ href = ""
+ extra = ""
+ if column.sortable:
+ if sort_key == column.key:
+ if sort_order == "asc":
+ href = url( sort=( "-" + column.key )
)
+ extra = "↓"
+ else:
+ href = url( sort=( column.key ) )
+ extra = "↑"
+ else:
+ href = url( sort=column.key )
+ %>
+ <th\
+ %if column.ncells > 1:
+ colspan="${column.ncells}"
+ %endif
+ >
+ %if href:
+ <a
href="${href}">${column.label}</a>
+ %else:
+ ${column.label}
+ %endif
+ <span>${extra}</span>
+ </th>
+ %endif
+ %endfor
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ %for i, item in enumerate( query ):
+ <tr \
+ %if current_item == item:
+ class="current" \
+ %endif
+ >
+ ## Item selection column
+ <td style="width: 1.5em;">
+ <input type="checkbox" name="id"
value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox"
/>
+ </td>
+ ## Data columns
+ %for column in grid.columns:
+ %if column.visible:
+ <%
+ # 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 ]
+ %>
+ %for cellnum, v in enumerate( value ):
+ <%
+ # Attach popup menu?
+ if column.attach_popup and cellnum == 0:
+ extra = '<a id="grid-%d-popup"
class="popup-arrow" style="display:
none;">▼</a>' % i
+ else:
+ extra = ""
+ %>
+ %if href:
+ <td><a
href="${href}">${v}</a> ${extra}</td>
+ %else:
+ <td >${v}${extra}</td>
+ %endif
+ </td>
+ %endfor
+ %endif
+ %endfor
+ ## Actions column
+ <td>
+ <div popupmenu="grid-${i}-popup">
+ %for operation in grid.operations:
+ %if operation.allowed( item ):
+ <a class="action-button"
href="${url( operation=operation.label, id=item.id
)}">${operation.label}</a>
+ %endif
+ %endfor
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </tbody>
+ <tfoot>
+ <tr>
+ <td></td>
+ <td colspan="100">
+ For <span class="grid-selected-count"></span>
selected histories:
+ %for operation in grid.operations:
+ %if operation.allow_multiple:
+ <input type="submit" name="operation"
value="${operation.label}" class="action-button">
+ %endif
+ %endfor
+ </td>
+ </tr>
+ </tfoot>
+ </table>
+</form>
diff -r 2630316ff75e -r 846f6a7ee80c test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Tue Aug 11 16:56:47 2009 -0400
+++ b/test/base/twilltestcase.py Wed Aug 12 15:56:03 2009 -0400
@@ -182,7 +182,7 @@
self.home()
self.visit_page( "root/history_options" )
if user:
- self.check_page_for_string( 'List</a> previously stored
histories' )
+ self.check_page_for_string( 'Previously</a> stored histories'
)
if active_datasets:
self.check_page_for_string( 'Create</a> a new empty
history' )
self.check_page_for_string( 'Construct workflow</a> from
current history' )
@@ -190,7 +190,7 @@
self.check_page_for_string( 'Share</a> current history' )
self.check_page_for_string( 'Change default permissions</a> for
current history' )
if histories_shared_by_others:
- self.check_page_for_string( 'List</a> histories shared with you
by others' )
+ self.check_page_for_string( 'Histories</a> shared with you by
others' )
if activatable_datasets:
self.check_page_for_string( 'Show deleted</a> datasets in current
history' )
self.check_page_for_string( 'Rename</a> current history' )
diff -r 2630316ff75e -r 846f6a7ee80c test/functional/test_history_functions.py
--- a/test/functional/test_history_functions.py Tue Aug 11 16:56:47 2009 -0400
+++ b/test/functional/test_history_functions.py Wed Aug 12 15:56:03 2009 -0400
@@ -183,7 +183,7 @@
self.view_shared_histories( check_str=history3.name, check_str2=admin_user.email
)
self.clone_history( self.security.encode_id( history3.id ),
'activatable',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history3_clone1
history3_clone1 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user1.id ) ) \
@@ -216,7 +216,7 @@
# Test cloning activatable datasets
self.clone_history( self.security.encode_id( history3.id ),
'activatable',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history3_clone2
history3_clone2 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
@@ -244,7 +244,7 @@
# Test cloning only active datasets
self.clone_history( self.security.encode_id( history3.id ),
'active',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history3_clone3
history3_clone3 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==admin_user.id ) ) \
@@ -355,7 +355,7 @@
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
'activatable',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history5_clone1
history5_clone1 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user1.id ) ) \
@@ -411,7 +411,7 @@
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
'activatable',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history5_clone2
history5_clone2 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user2.id ) ) \
@@ -484,7 +484,7 @@
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
'activatable',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history5_clone3
history5_clone3 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user2.id ) ) \
@@ -522,7 +522,7 @@
# Clone restricted history5
self.clone_history( self.security.encode_id( history5.id ),
'activatable',
- check_str_after_submit='is now included in your list of
stored histories.' )
+ check_str_after_submit='is now included in your
previously stored histories.' )
global history5_clone4
history5_clone4 = galaxy.model.History.filter( and_(
galaxy.model.History.table.c.deleted==False,
galaxy.model.History.table.c.user_id==regular_user3.id ) ) \
@@ -591,15 +591,6 @@
pass
self.logout()
self.login( email=admin_user.email )
- email = '%s,%s' % ( regular_user2.email, regular_user3.email )
- check_str_after_submit = 'The following datasets can be shared with %s with
no changes' % email
- check_str_after_submit2 = 'The following datasets can be shared with %s by
updating their permissions' % email
- action_check_str_after_submit = 'History Options'
- self.share_current_history( email,
- check_str_after_submit=check_str_after_submit,
- check_str_after_submit2=check_str_after_submit2,
- action='no_share',
-
action_check_str_after_submit=action_check_str_after_submit )
def test_070_history_show_and_hide_deleted_datasets( self ):
"""Testing displaying deleted history items"""
# Logged in as admin_user