Enhancements and fixes for sharing framework: (a) sharing/publishing webpages can now be displayed in frames; (b) sharing webpages can display messages; (c) workflow sharing highlights correct tab; (d) history sharing for individual users now uses sharing framework; (e) item sharing with individual users now uses common template.

This commit is contained in:
Jeremy Goecks
2010-08-16 17:05:59 -04:00
parent dfaf32acbb
commit bf8e01ceff
10 changed files with 201 additions and 332 deletions
+10 -8
View File
@@ -1114,16 +1114,18 @@ class HistoryController( BaseController, Sharable, UsesAnnotations, UsesItemRati
history.importable = history.published = False
elif 'unshare_user' in kwargs:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( kwargs[ 'unshare_user' ] ) )
if not user:
message = 'History (%s) does not seem to be shared with user (%s)' % ( history.name, user.email )
return trans.fill_template( 'history/sharing.mako',
histories=histories,
message=message,
status='error' )
# Look for and delete sharing relation for history-user.
deleted_sharing_relation = False
husas = trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ).filter_by( user=user, history=history ).all()
if husas:
deleted_sharing_relation = True
for husa in husas:
trans.sa_session.delete( husa )
trans.sa_session.delete( husa )
if not deleted_sharing_relation:
message = "History '%s' does not seem to be shared with user '%s'" % ( history.name, user.email )
return trans.fill_template( '/sharing_base.mako', item=history,
message=message, status='error' )
# Legacy issue: histories made accessible before recent updates may not have a slug. Create slug for any histories that need them.
for history in histories:
@@ -1188,7 +1190,7 @@ class HistoryController( BaseController, Sharable, UsesAnnotations, UsesItemRati
elif not send_to_err:
# User seems to be sharing an empty history
send_to_err = "You cannot share an empty history. "
return trans.fill_template( "/history/share.mako", histories=histories, email=email, send_to_err=send_to_err )
return trans.fill_template( "/ind_sharing_base.mako", histories=histories, email=email, send_to_err=send_to_err )
@web.expose
@web.require_login( "share restricted histories with other users" )
+5 -4
View File
@@ -470,11 +470,11 @@ class PageController( BaseController, Sharable, UsesAnnotations, UsesHistory,
session.flush()
return trans.fill_template( "/sharing_base.mako",
item=page )
item=page, use_panels=True )
@web.expose
@web.require_login( "use Galaxy pages" )
def share( self, trans, id, email="" ):
def share( self, trans, id, email="", use_panels=False ):
""" Handle sharing with an individual user. """
msg = mtype = None
page = trans.sa_session.query( model.Page ).get( trans.security.decode_id( id ) )
@@ -503,11 +503,12 @@ class PageController( BaseController, Sharable, UsesAnnotations, UsesHistory,
session.flush()
trans.set_message( "Page '%s' shared with user '%s'" % ( page.title, other.email ) )
return trans.response.send_redirect( url_for( controller='page', action='sharing', id=id ) )
return trans.fill_template( "/share_base.mako",
return trans.fill_template( "/ind_share_base.mako",
message = msg,
messagetype = mtype,
item=page,
email=email )
email=email,
use_panels=use_panels )
@web.expose
@web.require_login()
+5 -4
View File
@@ -225,11 +225,11 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi
session.flush()
return trans.fill_template( "/sharing_base.mako", item=visualization )
return trans.fill_template( "/sharing_base.mako", item=visualization, use_panels=True )
@web.expose
@web.require_login( "share Galaxy visualizations" )
def share( self, trans, id=None, email="", **kwd ):
def share( self, trans, id=None, email="", use_panels=False ):
""" Handle sharing a visualization with a particular user. """
msg = mtype = None
visualization = trans.sa_session.query( model.Visualization ).get( trans.security.decode_id( id ) )
@@ -258,11 +258,12 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi
session.flush()
trans.set_message( "Visualization '%s' shared with user '%s'" % ( visualization.title, other.email ) )
return trans.response.send_redirect( url_for( action='sharing', id=id ) )
return trans.fill_template( "/share_base.mako",
return trans.fill_template( "/ind_share_base.mako",
message = msg,
messagetype = mtype,
item=visualization,
email=email )
email=email,
use_panels=use_panels )
@web.expose
+6 -6
View File
@@ -239,7 +239,7 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
@web.expose
@web.require_login( "use Galaxy workflows" )
def share( self, trans, id, email="" ):
def share( self, trans, id, email="", use_panels=False ):
msg = mtype = None
# Load workflow from database
stored = self.get_stored_workflow( trans, id )
@@ -268,11 +268,12 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
session.flush()
trans.set_message( "Workflow '%s' shared with user '%s'" % ( stored.name, other.email ) )
return trans.response.send_redirect( url_for( controller='workflow', action='sharing', id=id ) )
return trans.fill_template( "workflow/share.mako",
return trans.fill_template( "/ind_share_base.mako",
message = msg,
messagetype = mtype,
stored=stored,
email=email )
item=stored,
email=email,
use_panels=use_panels )
@web.expose
@web.require_login( "use Galaxy workflows" )
@@ -312,8 +313,7 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
session.flush()
return trans.fill_template( "/sharing_base.mako",
item=stored )
return trans.fill_template( "/workflow/sharing.mako", use_panels=True, item=stored )
@web.expose
@web.require_login( "to import a workflow", use_panels=True )
-71
View File
@@ -1,71 +0,0 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/display_base.mako" import="get_history_link" />
##<h2>Import via link</h2>
%if message:
${render_msg( message, status )}
%endif
<h2>Histories that you've shared with others or enabled to be imported</h2>
%if not histories:
You have no histories that you've shared with others or enabled to be imported
%else:
%for history in histories:
<div class="toolForm">
<div class="toolFormTitle">History '${history.get_display_name()}' shared with</div>
<div class="toolFormBody">
<div class="form-row">
<div style="float: right;">
<a class="action-button" href="${h.url_for( controller='history', action='share', id=trans.security.encode_id( history.id ) )}">
<span>Share with another user</span>
</a>
</div>
</div>
%if history.users_shared_with:
%for i, association in enumerate( history.users_shared_with ):
<% user = association.user %>
<div class="form-row">
<a class="action-button" href="${h.url_for( controller='history', action='sharing', id=trans.security.encode_id( history.id ), unshare_user=trans.security.encode_id( user.id ) )}">Unshare</a>
${user.email}
</div>
%endfor
%endif
%if history.importable:
<div class="form-row">
<% url = get_history_link( history, True )%>
<a href="${url}" target="_blank">${url}</a>
<div class="toolParamHelp" style="clear: both;">
Send the above link to users as an easy way for them to view the history.
</div>
</div>
<div class="form-row">
<% url = h.url_for( controller='history', action='imp', id=trans.security.encode_id(history.id), qualified=True ) %>
<a href="${url}">${url}</a>
<div class="toolParamHelp" style="clear: both;">
Send the above link to users as an easy way for them to import the history, making a copy of their own.
</div>
</div>
<div class="form-row">
<form action="${h.url_for( controller='history', action='sharing', id=trans.security.encode_id( history.id ) )}" method="POST">
<div class="form-row">
<input class="action-button" type="submit" name="disable_import_via_link" value="Disable import via link">
</div>
</form>
</div>
%else:
<form action="${h.url_for( action='sharing', id=trans.security.encode_id(history.id) )}" method="POST">
<div class="form-row">
<input class="action-button" type="submit" name="enable_import_via_link" value="Enable import via link">
<div class="toolParamHelp" style="clear: both;">
Click to generate a URL that you can give to a user to allow them to import this history, making a copy of their own
</div>
</div>
</form>
%endif
</div>
</div>
%endfor
%endif
+108
View File
@@ -0,0 +1,108 @@
##
## Base template for sharing an item with an individual user. Template expects the following parameters:
## (a) item - item to be shared.
##
<%!
def inherit(context):
if context.get('use_panels'):
if context.get('webapp'):
webapp = context.get('webapp')
else:
webapp = 'galaxy'
return '/webapps/%s/base_panels.mako' % webapp
else:
return '/base.mako'
%>
<%inherit file="${inherit(context)}"/>
<%namespace file="./display_common.mako" import="*" />
##
## Page methods.
##
<%def name="init()">
<%
self.has_left_panel=False
self.has_right_panel=False
self.message_box_visible=False
self.overlay_visible=False
self.message_box_class=""
self.active_view=""
self.body_class=""
%>
</%def>
<%def name="stylesheets()">
${parent.stylesheets()}
<style>
## If page is displayed in panels, pad from edges for readabilit.
%if context.get('use_panels'):
div#center
{
padding: 10px;
}
%endif
</style>
</%def>
<%def name="center_panel()">
${self.body()}
</%def>
<%def name="body()">
%if message:
<%
if messagetype is UNDEFINED:
mt = "done"
else:
mt = messagetype
%>
<p />
<div class="${mt}message">
${message}
</div>
<p />
%endif
<%
#
# Setup and variables needed for page.
#
# Get class name strings.
item_class_name = get_class_display_name( item.__class__ )
item_class_name_lc = item_class_name.lower()
item_class_plural_name = get_class_plural_display_name( item.__class__ )
item_class_plural_name_lc = item_class_plural_name.lower()
# Get item name.
item_name = get_item_name(item)
%>
<div class="toolForm">
<div class="toolFormTitle">Share ${item_class_name} '${item_name}' with Another User</div>
<div class="toolFormBody">
<form action="${h.url_for( action='share', id=trans.security.encode_id( item.id ) )}" method="POST">
<div class="form-row">
<label>
Email address of user to share with
</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="email" value="${email}" size="40">
</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<input type="submit" value="Share"></input>
</div>
<div class="form-row">
<a href="${h.url_for( action="sharing", id=trans.security.encode_id( item.id ) )}">Back to ${item_class_name}'s Sharing Home</a>
</div>
</form>
</div>
</div>
</div>
</%def>
-36
View File
@@ -1,36 +0,0 @@
<%inherit file="/base.mako"/>
%if message:
<%
if messagetype is UNDEFINED:
mt = "done"
else:
mt = messagetype
%>
<p />
<div class="${mt}message">
${message}
</div>
<p />
%endif
<div class="toolForm">
<div class="toolFormTitle">Share page '${item.title}'</div>
<div class="toolFormBody">
<form action="${h.url_for( action='share', id=trans.security.encode_id( item.id ) )}" method="POST">
<div class="form-row">
<label>
Email address of user to share with
</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="email" value="${email}" size="40">
</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<input type="submit" value="Share"></input>
</div>
</form>
</div>
</div>
</div>
+60 -12
View File
@@ -1,16 +1,39 @@
##
## Base template for sharing an item. Template expects the following parameters:
## Base template for sharing/publishing/exporting an item. Template expects the following parameters:
## (a) item - item to be shared.
##
<%inherit file="/base.mako"/>
<%!
def inherit(context):
if context.get('use_panels', False) == True:
if context.get('webapp'):
webapp = context.get('webapp')
else:
webapp = 'galaxy'
return '/webapps/%s/base_panels.mako' % webapp
else:
return '/base.mako'
%>
<%inherit file="${inherit(context)}"/>
<%namespace file="./display_common.mako" import="*" />
<%namespace file="/message.mako" import="render_msg" />
##
## Page methods.
##
<%def name="init()">
<%
self.has_left_panel=False
self.has_right_panel=False
self.message_box_visible=False
self.overlay_visible=False
self.message_box_class=""
self.active_view=""
self.body_class=""
%>
</%def>
<%def name="title()">
Sharing and Publishing ${get_class_display_name( item.__class__ )} '${get_item_name( item )}'
</%def>
@@ -57,18 +80,38 @@
<%def name="stylesheets()">
${parent.stylesheets()}
<style>
div.indent
## Put some whitespace before each section header.
h3
{
margin-left: 1em;
margin-top: 2em;
}
input.action-button
{
margin-left: 0;
}
## If page is displayed in panels, pad from edges for readabilit.
%if context.get('use_panels'):
div#center
{
padding: 10px;
}
%endif
</style>
</%def>
<%def name="center_panel()">
${self.body()}
</%def>
<%def name="body()">
## Set use_panels var for use in page's URLs.
<% use_panels = context.get('use_panels', False) %>
## Render message.
%if message:
${render_msg( message, status )}
%endif
<%
#
# Setup and variables needed for page.
@@ -79,8 +122,10 @@
item_class_name_lc = item_class_name.lower()
item_class_plural_name = get_class_plural_display_name( item.__class__ )
item_class_plural_name_lc = item_class_plural_name.lower()
# Get item name.
item_name = get_item_name(item)
%>
<% item_name = get_item_name(item) %>
<h2>Sharing and Publishing ${item_class_name} '${item_name}'</h2>
@@ -103,7 +148,6 @@
</form>
%else:
## User has a public username, so private sharing and publishing options.
<div class="indent" style="margin-top: 2em">
<h3>Making ${item_class_name} Accessible via Link and Publishing It</h3>
<div>
@@ -174,8 +218,10 @@
</form>
%endif
</div>
##
## Sharing with Galaxy users.
##
<h3>Sharing ${item_class_name} with Specific Users</h3>
<div>
@@ -183,7 +229,7 @@
<p>
The following users will see this ${item_class_name_lc} in their ${item_class_name_lc} list and will be
able to run/view and import it.
able to view, import, and run it.
</p>
<table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
@@ -200,7 +246,7 @@
</td>
<td>
<div popupmenu="user-${i}-popup">
<a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ), unshare_user=trans.security.encode_id( user.id ) )}">Unshare</a>
<a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id( item.id ), unshare_user=trans.security.encode_id( user.id ), use_panels=use_panels )}">Unshare</a>
</div>
</td>
</tr>
@@ -208,7 +254,8 @@
</table>
<p>
<a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(item.id) )}">
<a class="action-button"
href="${h.url_for( action='share', id=trans.security.encode_id(item.id), use_panels=use_panels )}">
<span>Share with another user</span>
</a>
@@ -216,7 +263,8 @@
<p>You have not shared this ${item_class_name_lc} with any users.</p>
<a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(item.id) )}">
<a class="action-button"
href="${h.url_for( action='share', id=trans.security.encode_id(item.id), use_panels=use_panels )}">
<span>Share with a user</span>
</a>
<br>
-36
View File
@@ -1,36 +0,0 @@
<%inherit file="/base.mako"/>
%if message:
<%
if messagetype is UNDEFINED:
mt = "done"
else:
mt = messagetype
%>
<p />
<div class="${mt}message">
${message}
</div>
<p />
%endif
<div class="toolForm">
<div class="toolFormTitle">Share workflow '${stored.name}'</div>
<div class="toolFormBody">
<form action="${h.url_for( action='share', id=trans.security.encode_id(stored.id) )}" method="POST">
<div class="form-row">
<label>
Email address of user to share with
</label>
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="text" name="email" value="${email}" size="40">
</div>
<div style="clear: both"></div>
</div>
<div class="form-row">
<input type="submit" value="Share"></input>
</div>
</form>
</div>
</div>
</div>
+7 -155
View File
@@ -1,161 +1,13 @@
<%inherit file="/base.mako"/>
<%! from galaxy import model %>
<%inherit file="/sharing_base.mako"/>
##
## Page methods.
##
<%def name="title()">
Sharing Workflow '${stored.name}'
</%def>
<%def name="stylesheets()">
${parent.stylesheets()}
<style>
div.indent
{
margin-left: 1em;
}
input.action-button
{
margin-left: 0;
}
</style>
</%def>
## Get display name for a class.
<%def name="get_class_display_name( a_class )">
<%def name="init()">
<%
if a_class is model.History:
return "History"
elif a_class is model.StoredWorkflow:
return "Workflow"
elif a_class is model.Page:
return "Page"
parent.init()
self.active_view="workflow"
%>
</%def>
##
## Page content.
##
<%def name="center_panel()">
${parent.body()}
</%def>
<h2>Sharing Workflow '${stored.name}'</h2>
<div class="indent" style="margin-top: 2em">
<h3>Making Workflow Accessible via Link and Publishing It</h3>
<div class="indent">
%if stored.importable:
<%
item_status = "accessible via link"
if stored.published:
item_status = item_status + " and published"
%>
This workflow <strong>${item_status}</strong>.
<div class="indent">
<p>Anyone can view and import this workflow by visiting the following URL:
<% url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=stored.slug, qualified=True ) %>
<blockquote>
<a href="${url}">${url}</a>
</blockquote>
%if stored.published:
This workflow is publicly listed and searchable in Galaxy's <a href='${h.url_for( action='list_published' )}'>Published Workflows</a> section.
%endif
</div>
<p>You can:
<div class="indent">
<form action="${h.url_for( action='sharing', id=trans.security.encode_id(stored.id) )}"
method="POST">
%if not stored.published:
## Item is importable but not published. User can disable importable or publish.
<input class="action-button" type="submit" name="disable_link_access" value="Disable Access to Workflow Link">
<div class="toolParamHelp">Disables workflow's link so that it is not accessible.</div>
<br>
<input class="action-button" type="submit" name="publish" value="Publish Workflow" method="POST">
<div class="toolParamHelp">Publishes the workflow to Galaxy's <a href='${h.url_for( action='list_published' )}'>Published Workflows</a> section, where it is publicly listed and searchable.</div>
<br>
%else: ## stored.published == True
## Item is importable and published. User can unpublish or disable import and unpublish.
<input class="action-button" type="submit" name="unpublish" value="Unpublish Workflow">
<div class="toolParamHelp">Removes workflow from Galaxy's <a href='${h.url_for( action='list_published' )}'>Published Workflows</a> section so that it is not publicly listed or searchable.</div>
<br>
<input class="action-button" type="submit" name="disable_link_access_and_unpublish" value="Disable Access to Workflow via Link and Unpublish">
<div class="toolParamHelp">Disables workflow's link so that it is not accessible and removes workflow from Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published Workflows</a> section so that it is not publicly listed or searchable.</div>
%endif
</form>
</div>
%else:
This workflow is currently restricted so that only you and the users listed below can access it. You can:
<p>
<form action="${h.url_for( action='sharing', id=trans.security.encode_id(stored.id) )}" method="POST">
<input class="action-button" type="submit" name="make_accessible_via_link" value="Make Workflow Accessible via Link">
<div class="toolParamHelp">Generates a web link that you can share with other people so that they can view and import the workflow.</div>
<br>
<input class="action-button" type="submit" name="make_accessible_and_publish" value="Make Workflow Accessible and Publish" method="POST">
<div class="toolParamHelp">Makes the workflow accessible via link (see above) and publishes the workflow to Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published Workflows</a> section, where it is publicly listed and searchable.</div>
</form>
%endif
</div>
<h3>Sharing Workflow with Specific Users</h3>
<div class="indent">
%if stored.users_shared_with:
<p>
The following users will see this workflow in their workflow list and will be
able to run/view and import it.
</p>
<ul class="manage-table-actions">
<li>
<a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(stored.id) )}">
<span>Share with another user</span>
</a>
</li>
</ul>
<table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr class="header">
<th>Email</th>
<th></th>
</tr>
%for i, association in enumerate( stored.users_shared_with ):
<% user = association.user %>
<tr>
<td>
${user.email}
<a id="user-${i}-popup" class="popup-arrow" style="display: none;">&#9660;</a>
</td>
<td>
<div popupmenu="user-${i}-popup">
<a class="action-button" href="${h.url_for( id=trans.security.encode_id( stored.id ), unshare_user=trans.security.encode_id( user.id ) )}">Unshare</a>
</div>
</td>
</tr>
%endfor
</table>
%else:
<p>You have not shared this workflow with any users.</p>
<a class="action-button" href="${h.url_for( action='share', id=trans.security.encode_id(stored.id) )}">
<span>Share with another user</span>
</a>
<br>
%endif
</div>
</div>
<p><br><br>
<a href=${h.url_for( action="list" )}>Back to Workflows List</a>