galaxy-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- 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
- 15302 discussions

commit/galaxy-central: greg: Add the ability to search for repositories in the new review grids.
by Bitbucket 18 Oct '12
by Bitbucket 18 Oct '12
18 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/2914e5d87851/
changeset: 2914e5d87851
user: greg
date: 2012-10-18 22:14:35
summary: Add the ability to search for repositories in the new review grids.
affected #: 1 file
diff -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 -r 2914e5d87851afcc9cadb7de02200a1eb75cc7e5 lib/galaxy/webapps/community/controllers/repository_review.py
--- a/lib/galaxy/webapps/community/controllers/repository_review.py
+++ b/lib/galaxy/webapps/community/controllers/repository_review.py
@@ -76,6 +76,11 @@
ReviewersColumn( "Reviewers",
attach_popup=False )
]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
operations = [
grids.GridOperation( "Inspect repository revisions",
allow_multiple=False,
@@ -103,6 +108,11 @@
RepositoriesWithReviewsGrid.UserColumn( "Owner",
attach_popup=False )
]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
operations = [ grids.GridOperation( "Inspect repository revisions",
allow_multiple=False,
condition=( lambda item: not item.deleted ),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/0698fc666bd0/
changeset: 0698fc666bd0
user: greg
date: 2012-10-18 21:47:06
summary: Add the ability to review a defined (but flexible) set of repository components for repositories in the tool shed. Reviews are performed on specific revisions of the repository that are installable at the time of review. Each repository component can be reviewed and approved (or not) as well as rated. The repository revision is automatically rated as the average of all component ratings. The repository revision can be approved (or not) in addition to each component. Component reviews can be marked "private", in which case they are only accessible by the owner and the group of reviewers. The ability to review repositories is restricted by the tool shed's role-base access security components. Initially, all member of the Intergalactic Utilities Commission can review repositories.
affected #: 24 files
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/controllers/admin.py
--- a/lib/galaxy/webapps/community/controllers/admin.py
+++ b/lib/galaxy/webapps/community/controllers/admin.py
@@ -699,7 +699,7 @@
successful_count = 0
unsuccessful_count = 0
for repository_name_owner_str in repository_names_by_owner:
- repository_name_owner_list = repository_name_owner_str.split( '__ESEP__' )
+ repository_name_owner_list = repository_name_owner_str.split( STRSEP )
name = repository_name_owner_list[ 0 ]
owner = repository_name_owner_list[ 1 ]
repository = get_repository_by_name_and_owner( trans, name, owner )
@@ -737,7 +737,7 @@
trans.model.Repository.table.c.user_id ):
owner = repository.user.username
option_label = '%s (%s)' % ( repository.name, owner )
- option_value = '%s__ESEP__%s' % ( repository.name, owner )
+ option_value = '%s%s%s' % ( repository.name, STRSEP, owner )
repositories_select_field.add_option( option_label, option_value )
return trans.fill_template( '/webapps/community/admin/reset_metadata_on_selected_repositories.mako',
repositories_select_field=repositories_select_field,
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -79,6 +79,9 @@
'${host}'
"""
+# String separator
+STRSEP = '__ESEP__'
+
# States for passing messages
SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
@@ -150,6 +153,15 @@
if repository_metadata:
return repository_metadata.malicious
return False
+def changeset_revision_reviewed_by_user( trans, user, repository, changeset_revision ):
+ """Determine if the current changeset revision has been reviewed by the current user."""
+ changeset_revision_reviewed_by_user = False
+ for reviewed_revision in repository.reviewed_revisions:
+ if reviewed_revision.changeset_revision == changeset_revision:
+ for review in repository.reviews:
+ if review.changeset_revision == changeset_revision and review.user == user:
+ return True
+ return False
def check_file_contents( trans ):
# See if any admin users have chosen to receive email alerts when a repository is updated.
# If so, the file contents of the update must be checked for inappropriate content.
@@ -386,7 +398,28 @@
"""Get all categories from the database"""
return trans.sa_session.query( trans.model.Category ) \
.filter( trans.model.Category.table.c.deleted==False ) \
- .order_by( trans.model.Category.table.c.name ).all()
+ .order_by( trans.model.Category.table.c.name ) \
+ .all()
+def get_component( trans, id ):
+ """Get a component from the database"""
+ return trans.sa_session.query( trans.model.Component ).get( trans.security.decode_id( id ) )
+def get_component_by_name( trans, name ):
+ return trans.sa_session.query( trans.app.model.Component ) \
+ .filter( trans.app.model.Component.table.c.name==name ) \
+ .first()
+def get_component_review( trans, id ):
+ """Get a component_review from the database"""
+ return trans.sa_session.query( trans.model.ComponentReview ).get( trans.security.decode_id( id ) )
+def get_component_review_by_repository_review_id_component_id( trans, repository_review_id, component_id ):
+ """Get a component_review from the database via repository_review_id and component_id"""
+ return trans.sa_session.query( trans.model.ComponentReview ) \
+ .filter( and_( trans.model.ComponentReview.table.c.repository_review_id == trans.security.decode_id( repository_review_id ),
+ trans.model.ComponentReview.table.c.component_id == trans.security.decode_id( component_id ) ) ) \
+ .first()
+def get_components( trans ):
+ return trans.sa_session.query( trans.app.model.Component ) \
+ .order_by( trans.app.model.Component.name ) \
+ .all()
def get_latest_repository_metadata( trans, decoded_repository_id ):
"""Get last metadata defined for a specified repository from the database"""
return trans.sa_session.query( trans.model.RepositoryMetadata ) \
@@ -469,6 +502,46 @@
return INITIAL_CHANGELOG_HASH
else:
previous_changeset_revision = current_changeset_revision
+def get_previous_repository_reviews( trans, repository, changeset_revision ):
+ """Return an ordered dictionary of repository reviews up to and including the received changeset revision."""
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
+ reviewed_revision_hashes = [ reviewed_revisions.changeset_revision for reviewed_revisions in repository.reviewed_revisions ]
+ previous_reviews_dict = odict()
+ for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
+ previous_changeset_revision = str( repo.changectx( changeset ) )
+ if previous_changeset_revision in reviewed_revision_hashes:
+ previous_rev, previous_changeset_revision_label = get_rev_label_from_changeset_revision( repo, previous_changeset_revision )
+ revision_reviews = get_reviews_by_repository_id_changeset_revision( trans, trans.security.encode_id( repository.id ), previous_changeset_revision )
+ previous_reviews_dict[ previous_changeset_revision ] = dict( changeset_revision_label=previous_changeset_revision_label,
+ reviews=revision_reviews )
+ return previous_reviews_dict
+def get_rev_label_changeset_revision_from_repository_metadata( repository_metadata, repository=None ):
+ if repository is None:
+ repository = repository_metadata.repository
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
+ changeset_revision = repository_metadata.changeset_revision
+ ctx = get_changectx_for_changeset( repo, changeset_revision )
+ if ctx:
+ rev = '%04d' % ctx.rev()
+ label = "%s:%s" % ( str( ctx.rev() ), changeset_revision )
+ else:
+ rev = '-1'
+ label = "-1:%s" % changeset_revision
+ return rev, label, changeset_revision
+def get_rev_label_from_changeset_revision( repo, changeset_revision ):
+ ctx = get_changectx_for_changeset( repo, changeset_revision )
+ if ctx:
+ rev = '%04d' % ctx.rev()
+ label = "%s:%s" % ( str( ctx.rev() ), changeset_revision )
+ else:
+ rev = '-1'
+ label = "-1:%s" % changeset_revision
+ return rev, label
+def get_reversed_changelog_changesets( repo ):
+ reversed_changelog = []
+ for changeset in repo.changelog:
+ reversed_changelog.insert( 0, changeset )
+ return reversed_changelog
def get_repository( trans, id ):
"""Get a repository from the database via id"""
return trans.sa_session.query( trans.model.Repository ).get( trans.security.decode_id( id ) )
@@ -489,6 +562,41 @@
"""Get all metadata records for a specified repository."""
return trans.sa_session.query( trans.model.RepositoryMetadata ) \
.filter( trans.model.RepositoryMetadata.table.c.repository_id == trans.security.decode_id( id ) )
+def get_repository_metadata_revisions_for_review( repository, reviewed=True ):
+ repository_metadata_revisions = []
+ metadata_changeset_revision_hashes = []
+ if reviewed:
+ for metadata_revision in repository.metadata_revisions:
+ metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision )
+ for review in repository.reviews:
+ if review.changeset_revision in metadata_changeset_revision_hashes:
+ rmcr_hashes = [ rmr.changeset_revision for rmr in repository_metadata_revisions ]
+ if review.changeset_revision not in rmcr_hashes:
+ repository_metadata_revisions.append( review.repository_metadata )
+ else:
+ for review in repository.reviews:
+ if review.changeset_revision not in metadata_changeset_revision_hashes:
+ metadata_changeset_revision_hashes.append( review.changeset_revision )
+ for metadata_revision in repository.metadata_revisions:
+ if metadata_revision.changeset_revision not in metadata_changeset_revision_hashes:
+ repository_metadata_revisions.append( metadata_revision )
+ return repository_metadata_revisions
+def get_review( trans, id ):
+ """Get a repository_review from the database via id"""
+ return trans.sa_session.query( trans.model.RepositoryReview ).get( trans.security.decode_id( id ) )
+def get_review_by_repository_id_changeset_revision_user_id( trans, repository_id, changeset_revision, user_id ):
+ """Get a repository_review from the database via repository id, changeset_revision and user_id"""
+ return trans.sa_session.query( trans.model.RepositoryReview ) \
+ .filter( and_( trans.model.RepositoryReview.repository_id == trans.security.decode_id( repository_id ),
+ trans.model.RepositoryReview.changeset_revision == changeset_revision,
+ trans.model.RepositoryReview.user_id == trans.security.decode_id( user_id ) ) ) \
+ .first()
+def get_reviews_by_repository_id_changeset_revision( trans, repository_id, changeset_revision ):
+ """Get all repository_reviews from the database via repository id and changeset_revision"""
+ return trans.sa_session.query( trans.model.RepositoryReview ) \
+ .filter( and_( trans.model.RepositoryReview.repository_id == trans.security.decode_id( repository_id ),
+ trans.model.RepositoryReview.changeset_revision == changeset_revision ) ) \
+ .all()
def get_revision_label( trans, repository, changeset_revision ):
"""
Return a string consisting of the human read-able
@@ -590,6 +698,15 @@
util.send_mail( frm, to, subject, body, trans.app.config )
except Exception, e:
log.exception( "An error occurred sending a tool shed repository update alert by email." )
+def has_previous_repository_reviews( trans, repository, changeset_revision ):
+ """Determine if a repository has a changeset revision review prior to the received changeset revision."""
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
+ reviewed_revision_hashes = [ reviewed_revisions.changeset_revision for reviewed_revisions in repository.reviewed_revisions ]
+ for changeset in reversed_upper_bounded_changelog( repo, changeset_revision ):
+ previous_changeset_revision = str( repo.changectx( changeset ) )
+ if previous_changeset_revision in reviewed_revision_hashes:
+ return True
+ return False
def is_downloadable( metadata_dict ):
return 'datatypes' in metadata_dict or 'tools' in metadata_dict or 'workflows' in metadata_dict
def load_tool_from_changeset_revision( trans, repository_id, changeset_revision, tool_config_filename ):
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -110,14 +110,42 @@
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
def get_value( self, trans, grid, repository ):
- """Display a SelectField whose options are the changeset_revision strings of all revisions of this repository."""
+ """Display a SelectField whose options are the changeset_revision strings of all metadata revisions of this repository."""
# A repository's metadata revisions may not all be installable, as some may contain only invalid tools.
- select_field = build_changeset_revision_select_field( trans, repository, downloadable_only=False )
+ select_field = build_changeset_revision_select_field( trans, repository, downloadable=False )
if len( select_field.options ) > 1:
return select_field.get_html()
elif len( select_field.options ) == 1:
return select_field.options[ 0 ][ 0 ]
return ''
+ class WithReviewsRevisionColumn( grids.GridColumn ):
+ def __init__( self, col_name ):
+ grids.GridColumn.__init__( self, col_name )
+ def get_value( self, trans, grid, repository ):
+ # Restrict to revisions that have been reviewed.
+ repository_metadata_revisions = get_repository_metadata_revisions_for_review( repository, reviewed=True )
+ if repository_metadata_revisions:
+ rval = ''
+ for repository_metadata in repository_metadata_revisions:
+ rev, label, changeset_revision = get_rev_label_changeset_revision_from_repository_metadata( repository_metadata, repository=repository )
+ rval += '<a href="manage_repository_reviews_of_revision'
+ rval += '?id=%s&changeset_revision=%s">%s</a><br/>' % ( trans.security.encode_id( repository.id ), changeset_revision, label )
+ return rval
+ return ''
+ class WithoutReviewsRevisionColumn( grids.GridColumn ):
+ def __init__( self, col_name ):
+ grids.GridColumn.__init__( self, col_name )
+ def get_value( self, trans, grid, repository ):
+ # Restrict the options to revisions that have not yet been reviewed.
+ repository_metadata_revisions = get_repository_metadata_revisions_for_review( repository, reviewed=False )
+ if repository_metadata_revisions:
+ rval = ''
+ for repository_metadata in repository_metadata_revisions:
+ rev, label, changeset_revision = get_rev_label_changeset_revision_from_repository_metadata( repository_metadata, repository=repository )
+ rval += '<a href="manage_repository_reviews_of_revision'
+ rval += '?id=%s&changeset_revision=%s">%s</a><br/>' % ( trans.security.encode_id( repository.id ), changeset_revision, label )
+ return rval
+ return ''
class TipRevisionColumn( grids.GridColumn ):
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
@@ -224,8 +252,7 @@
columns = [
RepositoryListGrid.NameColumn( "Name",
key="name",
- link=( lambda item: dict( operation="view_or_manage_repository",
- id=item.id ) ),
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
attach_popup=False ),
RepositoryListGrid.DescriptionColumn( "Synopsis",
key="description",
@@ -295,7 +322,7 @@
grids.GridColumn.__init__( self, col_name )
def get_value( self, trans, grid, repository ):
"""Display a SelectField whose options are the changeset_revision strings of all download-able revisions of this repository."""
- select_field = build_changeset_revision_select_field( trans, repository, downloadable_only=True )
+ select_field = build_changeset_revision_select_field( trans, repository, downloadable=True )
if len( select_field.options ) > 1:
return select_field.get_html()
elif len( select_field.options ) == 1:
@@ -511,17 +538,9 @@
if 'operation' in kwd:
operation = kwd['operation'].lower()
if operation == "view_or_manage_repository":
- repository_id = kwd[ 'id' ]
- repository = get_repository( trans, repository_id )
- is_admin = trans.user_is_admin()
- if is_admin or repository.user == trans.user:
- return trans.response.send_redirect( web.url_for( controller='repository',
- action='manage_repository',
- **kwd ) )
- else:
- return trans.response.send_redirect( web.url_for( controller='repository',
- action='view_repository',
- **kwd ) )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_or_manage_repository',
+ **kwd ) )
elif operation == "edit_repository":
return trans.response.send_redirect( web.url_for( controller='repository',
action='edit_repository',
@@ -546,6 +565,9 @@
if k.startswith( 'f-' ):
del kwd[ k ]
kwd[ 'f-email' ] = trans.user.email
+ elif operation == "reviewed_repositories_i_own":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='reviewed_repositories_i_own' ) )
elif operation == "writable_repositories":
kwd[ 'username' ] = trans.user.username
return self.writable_repository_list_grid( trans, **kwd )
@@ -1385,8 +1407,17 @@
status = params.get( 'status', 'done' )
# See if there are any RepositoryMetadata records since menu items require them.
repository_metadata = trans.sa_session.query( model.RepositoryMetadata ).first()
+ # See if the current user owns any repositories that have been reviewed.
+ has_reviewed_repositories = False
+ current_user = trans.user
+ if current_user:
+ for repository in current_user.active_repositories:
+ if repository.reviewed_revisions:
+ has_reviewed_repositories = True
+ break
return trans.fill_template( '/webapps/community/index.mako',
repository_metadata=repository_metadata,
+ has_reviewed_repositories=has_reviewed_repositories,
message=message,
status=status )
@web.expose
@@ -1508,6 +1539,7 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
+ cntrller = params.get( 'cntrller', 'repository' )
repository = get_repository( trans, id )
repo_dir = repository.repo_path
repo = hg.repository( get_configured_ui(), repo_dir )
@@ -1614,7 +1646,7 @@
repository,
selected_value=changeset_revision,
add_id_to_name=False,
- downloadable_only=False )
+ downloadable=False )
revision_label = get_revision_label( trans, repository, repository.tip )
repository_metadata_id = None
metadata = None
@@ -1645,7 +1677,10 @@
malicious_check_box = CheckboxField( 'malicious', checked=is_malicious )
categories = get_categories( trans )
selected_categories = [ rca.category_id for rca in repository.categories ]
+ # Determine if the current changeset revision has been reviewed by the current user.
+ reviewed_by_user = changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
return trans.fill_template( '/webapps/community/repository/manage_repository.mako',
+ cntrller=cntrller,
repo_name=repo_name,
description=description,
long_description=long_description,
@@ -1655,6 +1690,7 @@
repository=repository,
repository_metadata_id=repository_metadata_id,
changeset_revision=changeset_revision,
+ reviewed_by_user=reviewed_by_user,
changeset_revision_select_field=changeset_revision_select_field,
revision_label=revision_label,
selected_categories=selected_categories,
@@ -1669,6 +1705,12 @@
message=message,
status=status )
@web.expose
+ @web.require_login( "review repository revision" )
+ def manage_repository_reviews_of_revision( self, trans, mine=False, **kwd ):
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_repository_reviews_of_revision',
+ **kwd ) )
+ @web.expose
@web.require_login( "multi select email alerts" )
def multi_select_email_alerts( self, trans, **kwd ):
params = util.Params( kwd )
@@ -1726,7 +1768,7 @@
repository,
selected_value=changeset_revision,
add_id_to_name=False,
- downloadable_only=False )
+ downloadable=False )
return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako',
repository=repository,
repository_metadata_id=repository_metadata_id,
@@ -2170,6 +2212,17 @@
message=message,
status=status )
@web.expose
+ def view_or_manage_repository( self, trans, **kwd ):
+ repository = get_repository( trans, kwd[ 'id' ] )
+ if trans.user_is_admin() or repository.user == trans.user:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='manage_repository',
+ **kwd ) )
+ else:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_repository',
+ **kwd ) )
+ @web.expose
def view_readme( self, trans, id, changeset_revision, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -2225,6 +2278,7 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
+ cntrller = params.get( 'cntrller', 'repository' )
repository = get_repository( trans, id )
repo = hg.repository( get_configured_ui(), repository.repo_path )
avg_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, repository, webapp_model=trans.model )
@@ -2258,7 +2312,7 @@
repository,
selected_value=changeset_revision,
add_id_to_name=False,
- downloadable_only=False )
+ downloadable=False )
revision_label = get_revision_label( trans, repository, changeset_revision )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
@@ -2274,7 +2328,10 @@
else:
message += malicious_error
status = 'error'
+ # Determine if the current changeset revision has been reviewed by the current user.
+ reviewed_by_user = changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
return trans.fill_template( '/webapps/community/repository/view_repository.mako',
+ cntrller=cntrller,
repo=repo,
repository=repository,
repository_metadata_id=repository_metadata_id,
@@ -2284,6 +2341,7 @@
num_ratings=num_ratings,
alerts_check_box=alerts_check_box,
changeset_revision=changeset_revision,
+ reviewed_by_user=reviewed_by_user,
changeset_revision_select_field=changeset_revision_select_field,
revision_label=revision_label,
is_malicious=is_malicious,
@@ -2342,8 +2400,9 @@
repository,
selected_value=changeset_revision,
add_id_to_name=False,
- downloadable_only=False )
+ downloadable=False )
trans.app.config.tool_data_path = original_tool_data_path
+ reviewed_by_user = changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
return trans.fill_template( "/webapps/community/repository/view_tool_metadata.mako",
repository=repository,
metadata=metadata,
@@ -2354,29 +2413,44 @@
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
is_malicious=is_malicious,
+ reviewed_by_user=reviewed_by_user,
message=message,
status=status )
# ----- Utility methods -----
-def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True, downloadable_only=False ):
- """Build a SelectField whose options are the changeset_rev strings of all downloadable revisions of the received repository."""
- repo = hg.repository( get_configured_ui(), repository.repo_path )
+
+def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True,
+ downloadable=False, reviewed=False, not_reviewed=False ):
+ """Build a SelectField whose options are the changeset_rev strings of certain revisions of the received repository."""
options = []
changeset_tups = []
refresh_on_change_values = []
- if downloadable_only:
+ if downloadable:
+ # Restrict the options to downloadable revisions.
repository_metadata_revisions = repository.downloadable_revisions
+ elif reviewed:
+ # Restrict the options to revisions that have been reviewed.
+ repository_metadata_revisions = []
+ metadata_changeset_revision_hashes = []
+ for metadata_revision in repository.metadata_revisions:
+ metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision )
+ for review in repository.reviews:
+ if review.changeset_revision in metadata_changeset_revision_hashes:
+ repository_metadata_revisions.append( review.repository_metadata )
+ elif not_reviewed:
+ # Restrict the options to revisions that have not yet been reviewed.
+ repository_metadata_revisions = []
+ reviewed_metadata_changeset_revision_hashes = []
+ for review in repository.reviews:
+ reviewed_metadata_changeset_revision_hashes.append( review.changeset_revision )
+ for metadata_revision in repository.metadata_revisions:
+ if metadata_revision.changeset_revision not in reviewed_metadata_changeset_revision_hashes:
+ repository_metadata_revisions.append( metadata_revision )
else:
+ # Restrict the options to all revisions that have associated metadata.
repository_metadata_revisions = repository.metadata_revisions
for repository_metadata in repository_metadata_revisions:
- changeset_revision = repository_metadata.changeset_revision
- ctx = get_changectx_for_changeset( repo, changeset_revision )
- if ctx:
- rev = '%04d' % ctx.rev()
- label = "%s:%s" % ( str( ctx.rev() ), changeset_revision )
- else:
- rev = '-1'
- label = "-1:%s" % changeset_revision
+ rev, label, changeset_revision = get_rev_label_changeset_revision_from_repository_metadata( repository_metadata, repository=repository )
changeset_tups.append( ( rev, label, changeset_revision ) )
refresh_on_change_values.append( changeset_revision )
# Sort options by the revision label. Even though the downloadable_revisions query sorts by update_time,
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/controllers/repository_review.py
--- /dev/null
+++ b/lib/galaxy/webapps/community/controllers/repository_review.py
@@ -0,0 +1,707 @@
+import os, logging
+from galaxy import util
+from galaxy.web.base.controller import *
+from galaxy.web.form_builder import SelectField, CheckboxField
+from galaxy.webapps.community import model
+from galaxy.web.framework.helpers import time_ago, iff, grids
+from galaxy.model.orm import *
+from sqlalchemy.sql.expression import func
+from common import *
+from repository import RepositoryListGrid
+from galaxy.util.shed_util import get_configured_ui
+from galaxy.util.odict import odict
+
+from galaxy import eggs
+eggs.require('mercurial')
+from mercurial import hg, ui, patch, commands
+
+log = logging.getLogger( __name__ )
+
+class ComponentGrid( grids.Grid ):
+ class NameColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, component ):
+ return component.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, component ):
+ return component.description
+ title = "Repository review components"
+ model_class = model.Component
+ template='/webapps/community/repository_review/grid.mako'
+ default_sort_key = "name"
+ columns = [
+ NameColumn( "Name",
+ key="Component.name",
+ link=( lambda item: dict( operation="edit", id=item.id ) ),
+ attach_popup=False ),
+ DescriptionColumn( "Description",
+ key="Component.description",
+ attach_popup=False )
+ ]
+ default_filter = {}
+ global_actions = [
+ grids.GridAction( "Add new component",
+ dict( controller='repository_review', action='manage_components', operation='create' ) )
+ ]
+ operations = []
+ standard_filters = []
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = True
+
+class RepositoriesWithReviewsGrid( RepositoryListGrid ):
+ class ReviewersColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, repository ):
+ if repository.reviewers:
+ rval = ''
+ for user in repository.reviewers:
+ rval += '%s<br/>' % user.username
+ return rval
+ return ''
+ title = "All reviewed Repositories"
+ model_class = model.Repository
+ template='/webapps/community/repository_review/grid.mako'
+ default_sort_key = "Repository.name"
+ columns = [
+ RepositoryListGrid.NameColumn( "Repository name",
+ key="name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=True ),
+ RepositoryListGrid.DescriptionColumn( "Synopsis",
+ key="description",
+ attach_popup=False ),
+ RepositoryListGrid.WithReviewsRevisionColumn( "Reviewed revisions" ),
+ RepositoryListGrid.WithoutReviewsRevisionColumn( "Revisions for review" ),
+ RepositoryListGrid.UserColumn( "Owner",
+ attach_popup=False ),
+ ReviewersColumn( "Reviewers",
+ attach_popup=False )
+ ]
+ operations = [
+ grids.GridOperation( "Inspect repository revisions",
+ allow_multiple=False,
+ condition=( lambda item: not item.deleted ),
+ async_compatible=False )
+ ]
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.Repository ) \
+ .join( ( model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \
+ .join( ( model.User.table, model.User.table.c.id == model.Repository.table.c.user_id ) ) \
+ .outerjoin( ( model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id ) ) \
+ .outerjoin( ( model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id ) )
+
+class RepositoriesWithoutReviewsGrid( RepositoriesWithReviewsGrid ):
+ title = "Repositories with no reviews"
+ columns = [
+ RepositoriesWithReviewsGrid.NameColumn( "Repository name",
+ key="name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=True ),
+ RepositoriesWithReviewsGrid.DescriptionColumn( "Synopsis",
+ key="description",
+ attach_popup=False ),
+ RepositoriesWithReviewsGrid.WithoutReviewsRevisionColumn( "Revisions for review" ),
+ RepositoriesWithReviewsGrid.UserColumn( "Owner",
+ attach_popup=False )
+ ]
+ operations = [ grids.GridOperation( "Inspect repository revisions",
+ allow_multiple=False,
+ condition=( lambda item: not item.deleted ),
+ async_compatible=False ) ]
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.Repository ) \
+ .filter( model.Repository.reviews == None ) \
+ .join( model.User.table )
+
+class RepositoriesReviewedByMeGrid( RepositoriesWithReviewsGrid ):
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.Repository ) \
+ .join( ( model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \
+ .filter( model.RepositoryReview.table.c.user_id == trans.user.id ) \
+ .join( ( model.User.table, model.User.table.c.id == model.RepositoryReview.table.c.user_id ) ) \
+ .outerjoin( ( model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id ) ) \
+ .outerjoin( ( model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id ) )
+
+class RepositoryReviewsByUserGrid( grids.Grid ):
+ class RepositoryNameColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, review ):
+ return review.repository.name
+ class RepositoryDescriptionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, review ):
+ return review.repository.description
+ class RevisionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, review ):
+ encoded_review_id = trans.security.encode_id( review.id )
+ rval = '<a class="action-button" href="'
+ if review.user == trans.user:
+ rval += 'edit_review'
+ else:
+ rval +='browse_review'
+ rval += '?id=%s">%s</a>' % ( encoded_review_id, get_revision_label( trans, review.repository, review.changeset_revision ) )
+ return rval
+ class RatingColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, review ):
+ if review.rating:
+ rval = '<input '
+ rval += 'name="star1-%s" ' % trans.security.encode_id( review.id )
+ rval += 'type="radio" '
+ rval += 'class="community_rating_star star" '
+ rval += 'disabled="disabled" '
+ rval += 'value="%s"' % str( review.rating )
+ rval += '/>'
+ return rval
+ return ''
+ title = "Reviews by user"
+ model_class = model.RepositoryReview
+ template='/webapps/community/repository_review/grid.mako'
+ default_sort_key = 'repository_id'
+ columns = [
+ RepositoryNameColumn( "Repository Name",
+ model_class=model.Repository,
+ key="Repository.name",
+ attach_popup=False ),
+ RepositoryDescriptionColumn( "Description",
+ model_class=model.Repository,
+ key="Repository.description",
+ attach_popup=False ),
+ RevisionColumn( "Revision",
+ attach_popup=False ),
+ RatingColumn( "Rating",
+ attach_popup=False )
+ ]
+ # Override these
+ default_filter = {}
+ global_actions = []
+ operations = []
+ standard_filters = []
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = True
+ def build_initial_query( self, trans, **kwd ):
+ user_id = trans.security.decode_id( kwd[ 'id' ] )
+ return trans.sa_session.query( self.model_class ) \
+ .filter( and_( model.RepositoryReview.table.c.deleted == False, \
+ model.RepositoryReview.table.c.user_id == user_id ) )
+
+class ReviewedRepositoriesIOwnGrid( RepositoriesWithReviewsGrid ):
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.Repository ) \
+ .join( ( model.RepositoryReview.table, model.RepositoryReview.table.c.repository_id == model.Repository.table.c.id ) ) \
+ .filter( model.Repository.table.c.user_id == trans.user.id ) \
+ .join( ( model.User.table, model.User.table.c.id == model.RepositoryReview.table.c.user_id ) ) \
+ .outerjoin( ( model.ComponentReview.table, model.ComponentReview.table.c.repository_review_id == model.RepositoryReview.table.c.id ) ) \
+ .outerjoin( ( model.Component.table, model.Component.table.c.id == model.ComponentReview.table.c.component_id ) )
+
+class RepositoryReviewController( BaseUIController, ItemRatings ):
+
+ component_grid = ComponentGrid()
+ repositories_reviewed_by_me_grid = RepositoriesReviewedByMeGrid()
+ repositories_with_reviews_grid = RepositoriesWithReviewsGrid()
+ repositories_without_reviews_grid = RepositoriesWithoutReviewsGrid()
+ repository_reviews_by_user_grid = RepositoryReviewsByUserGrid()
+ reviewed_repositories_i_own_grid = ReviewedRepositoriesIOwnGrid()
+
+ @web.expose
+ @web.require_login( "approve repository review" )
+ def approve_repository_review( self, trans, **kwd ):
+ # The value of the received id is the encoded review id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ encoded_review_id = kwd[ 'id' ]
+ review = get_review( trans, encoded_review_id )
+ if kwd.get( 'approve_repository_review_button', False ):
+ approved_select_field_name = '%s%sapproved' % ( encoded_review_id, STRSEP )
+ approved_select_field_value = str( kwd[ approved_select_field_name ] )
+ review.approved = approved_select_field_value
+ trans.sa_session.add( review )
+ trans.sa_session.flush()
+ message = 'Approved value <b>%s</b> saved for this revision.' % approved_select_field_value
+ repository_id = trans.security.encode_id( review.repository_id )
+ changeset_revision = review.changeset_revision
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_repository_reviews_of_revision',
+ id=repository_id,
+ changeset_revision=changeset_revision,
+ message=message,
+ status=status ) )
+ @web.expose
+ @web.require_login( "browse components" )
+ def browse_components( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "create":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='create_component',
+ **kwd ) )
+ return self.component_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "browse review" )
+ def browse_review( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ review = get_review( trans, kwd[ 'id' ] )
+ repository = review.repository
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
+ rev, changeset_revision_label = get_rev_label_from_changeset_revision( repo, review.changeset_revision )
+ return trans.fill_template( '/webapps/community/repository_review/browse_review.mako',
+ repository=repository,
+ changeset_revision_label=changeset_revision_label,
+ review=review,
+ message=message,
+ status=status )
+ def copy_review( self, trans, review_to_copy, review ):
+ for component_review in review_to_copy.component_reviews:
+ copied_component_review = trans.model.ComponentReview( repository_review_id=review.id,
+ component_id=component_review.component.id,
+ comment=component_review.comment,
+ private=component_review.private,
+ approved=component_review.approved,
+ rating=component_review.rating )
+ trans.sa_session.add( copied_component_review )
+ trans.sa_session.flush()
+ review.approved = review_to_copy.approved
+ review.rating = review_to_copy.rating
+ trans.sa_session.add( review )
+ trans.sa_session.flush()
+ @web.expose
+ @web.require_login( "create component" )
+ def create_component( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ name = util.restore_text( params.get( 'name', '' ) )
+ description = util.restore_text( params.get( 'description', '' ) )
+ if params.get( 'create_component_button', False ):
+ if not name or not description:
+ message = 'Enter a valid name and a description'
+ status = 'error'
+ elif get_component_by_name( trans, name ):
+ message = 'A component with that name already exists'
+ status = 'error'
+ else:
+ component = trans.app.model.Component( name=name, description=description )
+ trans.sa_session.add( component )
+ trans.sa_session.flush()
+ message = "Component '%s' has been created" % component.name
+ status = 'done'
+ trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_components',
+ message=message,
+ status=status ) )
+ return trans.fill_template( '/webapps/community/repository_review/create_component.mako',
+ name=name,
+ description=description,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_login( "create review" )
+ def create_review( self, trans, **kwd ):
+ # The value of the received id is the encoded repository id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository_id = kwd.get( 'id', None )
+ changeset_revision = kwd.get( 'changeset_revision', None )
+ previous_review_id = kwd.get( 'previous_review_id', None )
+ create_without_copying = 'create_without_copying' in kwd
+ if repository_id:
+ if changeset_revision:
+ # Make sure there is not already a review of the revision by the user.
+ if get_review_by_repository_id_changeset_revision_user_id( trans,
+ repository_id,
+ changeset_revision,
+ trans.security.encode_id( trans.user.id ) ):
+ message = "You have already created a review for revision <b>%s</b> of repository <b>%s</b>." % ( changeset_revision, repository.name )
+ status = "error"
+ else:
+ repository = get_repository( trans, repository_id )
+ # See if there are any reviews for previous changeset revisions that the user can copy.
+ if not create_without_copying and not previous_review_id and has_previous_repository_reviews( trans, repository, changeset_revision ):
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='select_previous_review',
+ **kwd ) )
+ # A review can be initially performed only on an installable revision of a repository, so make sure we have metadata associated
+ # with the received changeset_revision.
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ review = trans.app.model.RepositoryReview( repository_id=repository_metadata.repository_id,
+ changeset_revision=changeset_revision,
+ user_id=trans.user.id,
+ rating=None,
+ deleted=False )
+ trans.sa_session.add( review )
+ trans.sa_session.flush()
+ if previous_review_id:
+ review_to_copy = get_review( trans, previous_review_id )
+ self.copy_review( trans, review_to_copy, review )
+ review_id = trans.security.encode_id( review.id )
+ message = "Begin your review of revision <b>%s</b> of repository <b>%s</b>." \
+ % ( changeset_revision, repository.name )
+ status = 'done'
+ trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='edit_review',
+ id=review_id,
+ message=message,
+ status=status ) )
+ else:
+ message = "A new review cannot be created for revision <b>%s</b> of repository <b>%s</b>. Select a valid revision and try again." \
+ % ( changeset_revision, repository.name )
+ kwd[ 'message' ] = message
+ kwd[ 'status' ] = 'error'
+ else:
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_repository_reviews',
+ **kwd ) )
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='view_or_manage_repository',
+ **kwd ) )
+ @web.expose
+ @web.require_login( "edit component" )
+ def edit_component( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ id = params.get( 'id', None )
+ if not id:
+ message = "No component ids received for editing"
+ trans.response.send_redirect( web.url_for( controller='admin',
+ action='manage_categories',
+ message=message,
+ status='error' ) )
+ component = get_component( trans, id )
+ if params.get( 'edit_component_button', False ):
+ new_description = util.restore_text( params.get( 'description', '' ) ).strip()
+ if component.description != new_description:
+ component.description = new_description
+ trans.sa_session.add( component )
+ trans.sa_session.flush()
+ message = "The information has been saved for the component named <b>%s</b>" % ( component.name )
+ status = 'done'
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_components',
+ message=message,
+ status=status ) )
+ return trans.fill_template( '/webapps/community/repository_review/edit_component.mako',
+ component=component,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_login( "edit review" )
+ def edit_review( self, trans, **kwd ):
+ # The value of the received id is the encoded review id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ review_id = kwd.get( 'id', None )
+ review = get_review( trans, review_id )
+ components_dict = odict()
+ for component in get_components( trans ):
+ components_dict[ component.name ] = dict( component=component, component_review=None )
+ repository = review.repository
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
+ for component_review in review.component_reviews:
+ if component_review and component_review.component:
+ component_name = component_review.component.name
+ if component_name in components_dict:
+ component_review_dict = components_dict[ component_name ]
+ component_review_dict[ 'component_review' ] = component_review
+ components_dict[ component_name ] = component_review_dict
+ # Handle a Save button click.
+ save_button_clicked = False
+ save_buttons = [ '%s%sreview_button' % ( component_name, STRSEP ) for component_name in components_dict.keys() ]
+ save_buttons.append( 'revision_approved_button' )
+ for save_button in save_buttons:
+ if save_button in kwd:
+ save_button_clicked = True
+ break
+ if save_button_clicked:
+ # Handle the revision_approved_select_field value.
+ revision_approved = kwd.get( 'revision_approved', None )
+ revision_approved_setting_changed = False
+ if revision_approved:
+ revision_approved = str( revision_approved )
+ if review.approved != revision_approved:
+ revision_approved_setting_changed = True
+ review.approved = revision_approved
+ trans.sa_session.add( review )
+ trans.sa_session.flush()
+ saved_component_names = []
+ for component_name in components_dict.keys():
+ flushed = False
+ # Retrieve the review information from the form.
+ # The star rating form field is a radio button list, so it will not be received if it was not clicked in the form.
+ # Due to this behavior, default the value to 0.
+ rating = 0
+ for k, v in kwd.items():
+ if k.startswith( '%s%s' % ( component_name, STRSEP ) ):
+ component_review_attr = k.replace( '%s%s' % ( component_name, STRSEP ), '' )
+ if component_review_attr == 'component_id':
+ component_id = str( v )
+ elif component_review_attr == 'comment':
+ comment = str( v )
+ elif component_review_attr == 'private':
+ private = CheckboxField.is_checked( str( v ) )
+ elif component_review_attr == 'approved':
+ approved = str( v )
+ elif component_review_attr == 'rating':
+ rating = int( str( v ) )
+ component = get_component( trans, component_id )
+ component_review = get_component_review_by_repository_review_id_component_id( trans, review_id, component_id )
+ if component_review:
+ # See if the existing component review should be updated.
+ if component_review.comment != comment or \
+ component_review.private != private or \
+ component_review.approved != approved or \
+ component_review.rating != rating:
+ component_review.comment = comment
+ component_review.private = private
+ component_review.approved = approved
+ component_review.rating = rating
+ trans.sa_session.add( component_review )
+ trans.sa_session.flush()
+ flushed = True
+ saved_component_names.append( component_name )
+ else:
+ # See if a new component_review should be created.
+ if comment or private or approved != trans.model.ComponentReview.approved_states.NO or rating:
+ component_review = trans.model.ComponentReview( repository_review_id=review.id,
+ component_id=component.id,
+ comment=comment,
+ approved=approved,
+ rating=rating )
+ trans.sa_session.add( component_review )
+ trans.sa_session.flush()
+ flushed = True
+ saved_component_names.append( component_name )
+ if flushed:
+ # Update the repository rating value to be the average of all component review ratings.
+ average_rating = trans.sa_session.query( func.avg( trans.model.ComponentReview.table.c.rating ) ) \
+ .filter( trans.model.ComponentReview.table.c.repository_review_id == review.id ) \
+ .scalar()
+ review.rating = int( average_rating )
+ trans.sa_session.add( review )
+ trans.sa_session.flush()
+ # Update the information in components_dict.
+ if component_name in components_dict:
+ component_review_dict = components_dict[ component_name ]
+ component_review_dict[ 'component_review' ] = component_review
+ components_dict[ component_name ] = component_review_dict
+ if revision_approved_setting_changed:
+ message += 'Approved value <b>%s</b> saved for this revision.<br/>' % review.approved
+ if saved_component_names:
+ message += 'Reviews were saved for components: %s' % ', '.join( saved_component_names )
+ if not revision_approved_setting_changed and not saved_component_names:
+ message += 'No changes were made to this review, so nothing was saved.'
+ if review and review.approved:
+ selected_value = review.approved
+ else:
+ selected_value = trans.model.ComponentReview.approved_states.NO
+ revision_approved_select_field = build_approved_select_field( trans,
+ name='revision_approved',
+ selected_value=selected_value,
+ for_component=False )
+ rev, changeset_revision_label = get_rev_label_from_changeset_revision( repo, review.changeset_revision )
+ return trans.fill_template( '/webapps/community/repository_review/edit_review.mako',
+ repository=repository,
+ review=review,
+ changeset_revision_label=changeset_revision_label,
+ revision_approved_select_field=revision_approved_select_field,
+ components_dict=components_dict,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_login( "manage components" )
+ def manage_components( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if operation == "create":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='create_component',
+ **kwd ) )
+ elif operation == "edit":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='edit_component',
+ **kwd ) )
+ if 'message' not in kwd:
+ message = "This is a list of repository components (features) that can be reviewed. You can add new components or change "
+ message += "the description of an existing component if appropriate. Click on the name link to change the description."
+ status = "warning"
+ kwd[ 'message' ] = message
+ kwd[ 'status' ] = status
+ return self.component_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "manage repositories reviewed by me" )
+ def manage_repositories_reviewed_by_me( self, trans, **kwd ):
+ # The value of the received id is the encoded repository id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ if 'operation' in kwd:
+ kwd[ 'mine' ] = True
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_repositories_with_reviews',
+ **kwd ) )
+ self.repositories_reviewed_by_me_grid.title = 'Repositories reviewed by me'
+ return self.repositories_reviewed_by_me_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "manage repositories with reviews" )
+ def manage_repositories_with_reviews( self, trans, **kwd ):
+ # The value of the received id is the encoded repository id.
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if operation == "inspect repository revisions":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='manage_repository_reviews',
+ **kwd ) )
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='view_or_manage_repository',
+ **kwd ) )
+ return self.repositories_with_reviews_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "manage repositories without reviews" )
+ def manage_repositories_without_reviews( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if operation == "inspect repository revisions":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='create_review',
+ **kwd ) )
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository_review',
+ action='view_or_manage_repository',
+ **kwd ) )
+ return self.repositories_without_reviews_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "manage repository reviews" )
+ def manage_repository_reviews( self, trans, mine=False, **kwd ):
+ # The value of the received id is the encoded repository id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository_id = kwd.get( 'id', None )
+ if repository_id:
+ repository = get_repository( trans, repository_id )
+ repo_dir = repository.repo_path
+ repo = hg.repository( get_configured_ui(), repo_dir )
+ metadata_revision_hashes = [ metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions ]
+ reviewed_revision_hashes = [ reviewed_revisions.changeset_revision for reviewed_revisions in repository.reviewed_revisions ]
+ reviews_dict = odict()
+ for changeset in get_reversed_changelog_changesets( repo ):
+ ctx = repo.changectx( changeset )
+ changeset_revision = str( ctx )
+ if changeset_revision in metadata_revision_hashes or changeset_revision in reviewed_revision_hashes:
+ rev, changeset_revision_label = get_rev_label_from_changeset_revision( repo, changeset_revision )
+ if changeset_revision in reviewed_revision_hashes:
+ # Find the review for this changeset_revision
+ repository_reviews = get_reviews_by_repository_id_changeset_revision( trans, repository_id, changeset_revision )
+ # Determine if the current user can add a review to this revision.
+ can_add_review = trans.user not in [ repository_review.user for repository_review in repository_reviews ]
+ repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ repository_metadata_reviews = util.listify( repository_metadata.reviews )
+ else:
+ repository_reviews = []
+ repository_metadata_reviews = []
+ can_add_review = True
+ installable = changeset_revision in metadata_revision_hashes
+ revision_dict = dict( changeset_revision_label=changeset_revision_label,
+ repository_reviews=repository_reviews,
+ repository_metadata_reviews=repository_metadata_reviews,
+ installable=installable,
+ can_add_review=can_add_review )
+ reviews_dict[ changeset_revision ] = revision_dict
+ return trans.fill_template( '/webapps/community/repository_review/reviews_of_repository.mako',
+ repository=repository,
+ reviews_dict=reviews_dict,
+ mine=mine,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_login( "manage repository reviews of revision" )
+ def manage_repository_reviews_of_revision( self, trans, **kwd ):
+ # The value of the received id is the encoded repository id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository_id = kwd.get( 'id', None )
+ changeset_revision = kwd.get( 'changeset_revision', None )
+ repository = get_repository( trans, repository_id )
+ repo_dir = repository.repo_path
+ repo = hg.repository( get_configured_ui(), repo_dir )
+ installable = changeset_revision in [ metadata_revision.changeset_revision for metadata_revision in repository.metadata_revisions ]
+ rev, changeset_revision_label = get_rev_label_from_changeset_revision( repo, changeset_revision )
+ reviews = get_reviews_by_repository_id_changeset_revision( trans, repository_id, changeset_revision )
+ return trans.fill_template( '/webapps/community/repository_review/reviews_of_changeset_revision.mako',
+ repository=repository,
+ changeset_revision=changeset_revision,
+ changeset_revision_label=changeset_revision_label,
+ reviews=reviews,
+ installable=installable,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_login( "repository reviews by user" )
+ def repository_reviews_by_user( self, trans, **kwd ):
+ # The user may not be the current user. The value of the received id is the encoded user id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ user = get_user( trans, kwd[ 'id' ] )
+ self.repository_reviews_by_user_grid.title = "All repository revision reviews for user '%s'" % user.username
+ return self.repository_reviews_by_user_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "reviewed repositories i own" )
+ def reviewed_repositories_i_own( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ return self.reviewed_repositories_i_own_grid( trans, **kwd )
+ @web.expose
+ @web.require_login( "select previous review" )
+ def select_previous_review( self, trans, **kwd ):
+ # The value of the received id is the encoded repository id.
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository = get_repository( trans, kwd[ 'id' ] )
+ changeset_revision = kwd.get( 'changeset_revision', None )
+ repo = hg.repository( get_configured_ui(), repository.repo_path )
+ previous_reviews_dict = get_previous_repository_reviews( trans, repository, changeset_revision )
+ rev, changeset_revision_label = get_rev_label_from_changeset_revision( repo, changeset_revision )
+ return trans.fill_template( '/webapps/community/repository_review/select_previous_review.mako',
+ repository=repository,
+ changeset_revision=changeset_revision,
+ changeset_revision_label=changeset_revision_label,
+ previous_reviews_dict=previous_reviews_dict,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_login( "view or manage repository" )
+ def view_or_manage_repository( self, trans, **kwd ):
+ repository = get_repository( trans, kwd[ 'id' ] )
+ if trans.user_is_admin() or repository.user == trans.user:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='manage_repository',
+ cntrller='repository_review',
+ **kwd ) )
+ else:
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_repository',
+ cntrller='repository_review',
+ **kwd ) )
+
+# ----- Utility methods -----
+
+def build_approved_select_field( trans, name, selected_value=None, for_component=True ):
+ options = [ ( 'No', trans.model.ComponentReview.approved_states.NO ),
+ ( 'Yes', trans.model.ComponentReview.approved_states.YES ) ]
+ if for_component:
+ options.append( ( 'Not applicable', trans.model.ComponentReview.approved_states.NA ) )
+ select_field = SelectField( name=name )
+ for option_tup in options:
+ selected = selected_value and option_tup[1] == selected_value
+ select_field.add_option( option_tup[0], option_tup[1], selected=selected )
+ return select_field
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/controllers/upload.py
--- a/lib/galaxy/webapps/community/controllers/upload.py
+++ b/lib/galaxy/webapps/community/controllers/upload.py
@@ -85,7 +85,6 @@
isgzip = False
isbz2 = False
if uploaded_file:
-
if uncompress_file:
isgzip = is_gzip( uploaded_file_name )
if not isgzip:
@@ -208,12 +207,10 @@
repo = hg.repository( get_configured_ui(), repo_dir )
undesirable_dirs_removed = 0
undesirable_files_removed = 0
-
if upload_point is not None:
full_path = os.path.abspath( os.path.join( repo_dir, upload_point ) )
else:
full_path = os.path.abspath( repo_dir )
-
filenames_in_archive = []
for root, dirs, files in os.walk( uploaded_directory ):
for uploaded_file in files:
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/model/__init__.py
--- a/lib/galaxy/webapps/community/model/__init__.py
+++ b/lib/galaxy/webapps/community/model/__init__.py
@@ -25,6 +25,13 @@
self.purged = False
self.username = None
self.new_repo_alert = False
+ def all_roles( self ):
+ roles = [ ura.role for ura in self.roles ]
+ for group in [ uga.group for uga in self.groups ]:
+ for role in [ gra.role for gra in group.roles ]:
+ if role not in roles:
+ roles.append( role )
+ return roles
def set_password_cleartext( self, cleartext ):
"""Set 'self.password' to the digest of 'cleartext'."""
self.password = new_secure_hash( text_type=cleartext )
@@ -173,7 +180,32 @@
self.tool_versions = tool_versions or dict()
self.malicious = malicious
self.downloadable = downloadable
-
+
+class RepositoryReview( object ):
+ approved_states = Bunch( NO='no', YES='yes' )
+ def __init__( self, repository_id=None, changeset_revision=None, user_id=None, rating=None, deleted=False ):
+ self.repository_id = repository_id
+ self.changeset_revision = changeset_revision
+ self.user_id = user_id
+ self.rating = rating
+ self.deleted = deleted
+
+class ComponentReview( object ):
+ approved_states = Bunch( NO='no', YES='yes', NA='not_applicable' )
+ def __init__( self, repository_review_id=None, component_id=None, comment=None, private=False, approved=False, rating=None, deleted=False ):
+ self.repository_review_id = repository_review_id
+ self.component_id = component_id
+ self.comment = comment
+ self.private = private
+ self.approved = approved
+ self.rating = rating
+ self.deleted = deleted
+
+class Component( object ):
+ def __init__( self, name=None, description=None ):
+ self.name = name
+ self.description = description
+
class ItemRatingAssociation( object ):
def __init__( self, id=None, user=None, item=None, rating=0, comment='' ):
self.id = id
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/model/mapping.py
--- a/lib/galaxy/webapps/community/model/mapping.py
+++ b/lib/galaxy/webapps/community/model/mapping.py
@@ -124,6 +124,34 @@
Column( "malicious", Boolean, default=False ),
Column( "downloadable", Boolean, default=True ) )
+RepositoryReview.table = Table( "repository_review", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "repository_id", Integer, ForeignKey( "repository.id" ), index=True ),
+ Column( "changeset_revision", TrimmedString( 255 ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
+ Column( "approved", TrimmedString( 255 ) ),
+ Column( "rating", Integer, index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
+ComponentReview.table = Table( "component_review", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "repository_review_id", Integer, ForeignKey( "repository_review.id" ), index=True ),
+ Column( "component_id", Integer, ForeignKey( "component.id" ), index=True ),
+ Column( "comment", TEXT ),
+ Column( "private", Boolean, default=False ),
+ Column( "approved", TrimmedString( 255 ) ),
+ Column( "rating", Integer ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
+Component.table = Table( "component", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "name", TrimmedString( 255 ) ),
+ Column( "description", TEXT ) )
+
RepositoryRatingAssociation.table = Table( "repository_rating_association", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
@@ -187,7 +215,7 @@
properties=dict( user=relation( User.mapper ) ) )
assign_mapper( context, Tag, Tag.table,
- properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[Tag.table.c.id] ) ) ) )
+ properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[ Tag.table.c.id ] ) ) ) )
assign_mapper( context, Category, Category.table,
properties=dict( repositories=relation( RepositoryCategoryAssociation ) ) )
@@ -201,10 +229,47 @@
primaryjoin=( ( Repository.table.c.id == RepositoryMetadata.table.c.repository_id ) & ( RepositoryMetadata.table.c.downloadable == True ) ),
order_by=desc( RepositoryMetadata.table.c.update_time ) ),
metadata_revisions=relation( RepositoryMetadata,
- order_by=desc( RepositoryMetadata.table.c.update_time ) ) ) )
+ order_by=desc( RepositoryMetadata.table.c.update_time ) ),
+ reviews=relation( RepositoryReview,
+ primaryjoin=( ( Repository.table.c.id == RepositoryReview.table.c.repository_id ) ) ),
+ reviewers=relation( User,
+ secondary=RepositoryReview.table,
+ primaryjoin=( Repository.table.c.id == RepositoryReview.table.c.repository_id ),
+ secondaryjoin=( RepositoryReview.table.c.user_id == User.table.c.id ) ),
+ reviewed_revisions=relation( RepositoryMetadata,
+ secondary=RepositoryReview.table,
+ foreign_keys=[ RepositoryMetadata.table.c.repository_id, RepositoryMetadata.table.c.changeset_revision ],
+ primaryjoin=( Repository.table.c.id == RepositoryMetadata.table.c.repository_id ),
+ secondaryjoin=( ( RepositoryMetadata.table.c.repository_id == RepositoryReview.table.c.repository_id ) & ( RepositoryMetadata.table.c.changeset_revision == RepositoryReview.table.c.changeset_revision ) ) ) ) )
assign_mapper( context, RepositoryMetadata, RepositoryMetadata.table,
- properties=dict( repository=relation( Repository ) ) )
+ properties=dict( repository=relation( Repository ),
+ reviews=relation( RepositoryReview,
+ foreign_keys=[ RepositoryMetadata.table.c.repository_id, RepositoryMetadata.table.c.changeset_revision ],
+ primaryjoin=( ( RepositoryMetadata.table.c.repository_id == RepositoryReview.table.c.repository_id ) & ( RepositoryMetadata.table.c.changeset_revision == RepositoryReview.table.c.changeset_revision ) ) ) ) )
+
+assign_mapper( context, RepositoryReview, RepositoryReview.table,
+ properties=dict( repository=relation( Repository,
+ primaryjoin=( RepositoryReview.table.c.repository_id == Repository.table.c.id ) ),
+ # Take case when using the mapper below! It should be used only when a new review is being created for a repository change set revision.
+ # Keep in mind that repository_metadata records can be removed from the database for certain change set revisions when metadata is being
+ # reset on a repository!
+ repository_metadata=relation( RepositoryMetadata,
+ foreign_keys=[ RepositoryReview.table.c.repository_id, RepositoryReview.table.c.changeset_revision ],
+ primaryjoin=( ( RepositoryReview.table.c.repository_id == RepositoryMetadata.table.c.repository_id ) & ( RepositoryReview.table.c.changeset_revision == RepositoryMetadata.table.c.changeset_revision ) ),
+ backref='review' ),
+ user=relation( User, backref="repository_reviews" ),
+ component_reviews=relation( ComponentReview,
+ primaryjoin=( ( RepositoryReview.table.c.id == ComponentReview.table.c.repository_review_id ) & ( ComponentReview.table.c.deleted == False ) ) ),
+ private_component_reviews=relation( ComponentReview,
+ primaryjoin=( ( RepositoryReview.table.c.id == ComponentReview.table.c.repository_review_id ) & ( ComponentReview.table.c.deleted == False ) & ( ComponentReview.table.c.private == True ) ) ) ) )
+
+assign_mapper( context, ComponentReview, ComponentReview.table,
+ properties=dict( repository_review=relation( RepositoryReview ),
+ component=relation( Component,
+ primaryjoin=( ComponentReview.table.c.component_id == Component.table.c.id ) ) ) )
+
+assign_mapper( context, Component, Component.table )
assign_mapper( context, RepositoryRatingAssociation, RepositoryRatingAssociation.table,
properties=dict( repository=relation( Repository ), user=relation( User ) ) )
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/model/migrate/versions/0013_add_review_tables.py
--- /dev/null
+++ b/lib/galaxy/webapps/community/model/migrate/versions/0013_add_review_tables.py
@@ -0,0 +1,212 @@
+"""
+Migration script to add the repository_review, component_review and component tables and the Repository Reviewer group and role.
+"""
+import datetime, logging, sys
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+log = logging.getLogger( __name__ )
+log.setLevel(logging.DEBUG)
+handler = logging.StreamHandler( sys.stdout )
+format = "%(name)s %(levelname)s %(asctime)s %(message)s"
+formatter = logging.Formatter( format )
+handler.setFormatter( formatter )
+log.addHandler( handler )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+IUC = 'Intergalactic Utilities Commission'
+NOW = datetime.datetime.utcnow
+REVIEWER = 'Repository Reviewer'
+ROLE_TYPE = 'system'
+
+def nextval( table, col='id' ):
+ if migrate_engine.name == 'postgres':
+ return "nextval('%s_%s_seq')" % ( table, col )
+ elif migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ return "null"
+ else:
+ raise Exception( 'Unable to convert data for unknown database type: %s' % migrate_engine.name )
+
+def localtimestamp():
+ if migrate_engine.name == 'postgres' or migrate_engine.name == 'mysql':
+ return "LOCALTIMESTAMP"
+ elif migrate_engine.name == 'sqlite':
+ return "current_date || ' ' || current_time"
+ else:
+ raise Exception( 'Unable to convert data for unknown database type: %s' % db )
+
+def boolean_false():
+ if migrate_engine.name == 'postgres' or migrate_engine.name == 'mysql':
+ return False
+ elif migrate_engine.name == 'sqlite':
+ return 0
+ else:
+ raise Exception( 'Unable to convert data for unknown database type: %s' % db )
+
+RepositoryReview_table = Table( "repository_review", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=NOW ),
+ Column( "update_time", DateTime, default=NOW, onupdate=NOW ),
+ Column( "repository_id", Integer, ForeignKey( "repository.id" ), index=True ),
+ Column( "changeset_revision", TrimmedString( 255 ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True, nullable=False ),
+ Column( "approved", TrimmedString( 255 ) ),
+ Column( "rating", Integer, index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
+ComponentReview_table = Table( "component_review", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=NOW ),
+ Column( "update_time", DateTime, default=NOW, onupdate=NOW ),
+ Column( "repository_review_id", Integer, ForeignKey( "repository_review.id" ), index=True ),
+ Column( "component_id", Integer, ForeignKey( "component.id" ), index=True ),
+ Column( "comment", TEXT ),
+ Column( "private", Boolean, default=False ),
+ Column( "approved", TrimmedString( 255 ) ),
+ Column( "rating", Integer ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
+Component_table = Table( "component", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "name", TrimmedString( 255 ) ),
+ Column( "description", TEXT ) )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+ # Create new review tables.
+ try:
+ Component_table.create()
+ except Exception, e:
+ print str(e)
+ log.debug( "Creating component table failed: %s" % str( e ) )
+ try:
+ RepositoryReview_table.create()
+ except Exception, e:
+ print str(e)
+ log.debug( "Creating repository_review table failed: %s" % str( e ) )
+ try:
+ ComponentReview_table.create()
+ except Exception, e:
+ print str(e)
+ log.debug( "Creating component_review table failed: %s" % str( e ) )
+ # Insert default Component values.
+ names = [ 'Data types', 'Functional tests', 'README', 'Tool dependencies', 'Tools', 'Workflows' ]
+ descriptions = [ 'Proprietary datatypes defined in a file named datatypes_conf.xml included in the repository',
+ 'Functional tests defined in each tool config included in the repository along with test data files',
+ 'An appropriately named file included in the repository that contains installation information or 3rd-party tool dependency licensing information',
+ 'Tool dependencies defined in a file named tool_dependencies.xml included in the repository for contained tools',
+ 'Galaxy tools included in the repository',
+ 'Exported Galaxy workflows included in the repository' ]
+ for tup in zip( names, descriptions ):
+ name, description = tup
+ cmd = "INSERT INTO component VALUES ("
+ cmd += "%s, " % nextval( 'component' )
+ cmd += "'%s', " % name
+ cmd += "'%s' " % description
+ cmd += ");"
+ db_session.execute( cmd )
+ # Insert a REVIEWER role into the role table.
+ cmd = "INSERT INTO role VALUES ("
+ cmd += "%s, " % nextval( 'role' )
+ cmd += "%s, " % localtimestamp()
+ cmd += "%s, " % localtimestamp()
+ cmd += "'%s', " % REVIEWER
+ cmd += "'A user or group member with this role can review repositories.', "
+ cmd += "'%s', " % ROLE_TYPE
+ cmd += "%s" % boolean_false()
+ cmd += ");"
+ db_session.execute( cmd )
+ # Get the id of the REVIEWER role.
+ cmd = "SELECT id FROM role WHERE name = '%s' and type = '%s';" % ( REVIEWER, ROLE_TYPE )
+ row = db_session.execute( cmd ).fetchone()
+ if row:
+ role_id = row[ 0 ]
+ else:
+ role_id = None
+ # Insert an IUC group into the galaxy_group table.
+ cmd = "INSERT INTO galaxy_group VALUES ("
+ cmd += "%s, " % nextval( 'galaxy_group' )
+ cmd += "%s, " % localtimestamp()
+ cmd += "%s, " % localtimestamp()
+ cmd += "'%s', " % IUC
+ cmd += "%s" % boolean_false()
+ cmd += ");"
+ db_session.execute( cmd )
+ # Get the id of the IUC group.
+ cmd = "SELECT id FROM galaxy_group WHERE name = '%s';" % ( IUC )
+ row = db_session.execute( cmd ).fetchone()
+ if row:
+ group_id = row[ 0 ]
+ else:
+ group_id = None
+ if group_id and role_id:
+ # Insert a group_role_association for the IUC group and the REVIEWER role.
+ cmd = "INSERT INTO group_role_association VALUES ("
+ cmd += "%s, " % nextval( 'group_role_association' )
+ cmd += "%d, " % int( group_id )
+ cmd += "%d, " % int( role_id )
+ cmd += "%s, " % localtimestamp()
+ cmd += "%s " % localtimestamp()
+ cmd += ");"
+ db_session.execute( cmd )
+
+def downgrade():
+ metadata.reflect()
+ # Drop review tables.
+ try:
+ ComponentReview_table.drop()
+ except Exception, e:
+ print str(e)
+ log.debug( "Dropping component_review table failed: %s" % str( e ) )
+ try:
+ RepositoryReview_table.drop()
+ except Exception, e:
+ print str(e)
+ log.debug( "Dropping repository_review table failed: %s" % str( e ) )
+ try:
+ Component_table.drop()
+ except Exception, e:
+ print str(e)
+ log.debug( "Dropping component table failed: %s" % str( e ) )
+ # Get the id of the REVIEWER group.
+ cmd = "SELECT id FROM galaxy_group WHERE name = '%s';" % ( IUC )
+ row = db_session.execute( cmd ).fetchone()
+ if row:
+ group_id = row[ 0 ]
+ else:
+ group_id = None
+ # Get the id of the REVIEWER role.
+ cmd = "SELECT id FROM role WHERE name = '%s' and type = '%s';" % ( REVIEWER, ROLE_TYPE )
+ row = db_session.execute( cmd ).fetchone()
+ if row:
+ role_id = row[ 0 ]
+ else:
+ role_id = None
+ # See if we have at least 1 user
+ cmd = "SELECT * FROM galaxy_user;"
+ users = db_session.execute( cmd ).fetchall()
+ if role_id:
+ if users:
+ # Delete all UserRoleAssociations for the REVIEWER role.
+ cmd = "DELETE FROM user_role_association WHERE role_id = %d;" % int( role_id )
+ db_session.execute( cmd )
+ if group_id:
+ # Delete all UserGroupAssociations for members of the IUC group.
+ cmd = "DELETE FROM user_group_association WHERE group_id = %d;" % int( group_id )
+ db_session.execute( cmd )
+ # Delete all GroupRoleAssociations for the IUC group and the REVIEWER role.
+ cmd = "DELETE FROM group_role_association WHERE group_id = %d and role_id = %d;" % ( int( group_id ), int( role_id ) )
+ db_session.execute( cmd )
+ # Delete the IUC group from the galaxy_group table.
+ cmd = "DELETE FROM galaxy_group WHERE id = %d;" % int( group_id )
+ db_session.execute( cmd )
+ # Delete the REVIEWER role from the role table.
+ cmd = "DELETE FROM role WHERE id = %d;" % int( role_id )
+ db_session.execute( cmd )
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 lib/galaxy/webapps/community/security/__init__.py
--- a/lib/galaxy/webapps/community/security/__init__.py
+++ b/lib/galaxy/webapps/community/security/__init__.py
@@ -121,6 +121,11 @@
else:
return None
return role
+ def get_repository_reviewer_role( self ):
+ return self.sa_session.query( self.model.Role ) \
+ .filter( and_( self.model.Role.table.c.name == 'Repository Reviewer',
+ self.model.Role.table.c.type == self.model.Role.types.SYSTEM ) ) \
+ .first()
def set_entity_group_associations( self, groups=[], users=[], roles=[], delete_existing_assocs=True ):
for group in groups:
if delete_existing_assocs:
@@ -158,6 +163,13 @@
if user:
return user.username in listify( repository.allow_push )
return False
+ def user_can_review_repositories( self, user ):
+ if user:
+ roles = user.all_roles()
+ if roles:
+ repository_reviewer_role = self.get_repository_reviewer_role()
+ return repository_reviewer_role and repository_reviewer_role in roles
+ return False
def get_permitted_actions( filter=None ):
'''Utility method to return a subset of RBACAgent's permitted actions'''
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/admin/tool_shed_repository/view_tool_metadata.mako
--- a/templates/admin/tool_shed_repository/view_tool_metadata.mako
+++ b/templates/admin/tool_shed_repository/view_tool_metadata.mako
@@ -185,7 +185,6 @@
%>
%if tests:
<div class="form-row">
- <label>Functional tests:</label></td><table class="grid"><tr><td><b>name</b></td>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/admin/index.mako
--- a/templates/webapps/community/admin/index.mako
+++ b/templates/webapps/community/admin/index.mako
@@ -36,6 +36,7 @@
</%def><%def name="left_panel()">
+ <% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %><div class="unified-panel-header" unselectable="on"><div class='unified-panel-header-inner'>Administration</div></div>
@@ -64,6 +65,31 @@
</div></div></div>
+ %if can_review_repositories:
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">
+ Reviewing Repositories
+ </div>
+ <div class="toolSectionBody">
+ <div class="toolSectionBg">
+ %if trans.user.repository_reviews:
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_reviewed_by_me' )}">Repositories reviewed by me</a>
+ </div>
+ %endif
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_with_reviews' )}">All reviewed repositories</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_without_reviews' )}">Repositories with no reviews</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_components' )}">Manage review components</a>
+ </div>
+ </div>
+ </div>
+ %endif
+ <div class="toolSectionPad"></div><div class="toolSectionTitle">
Categories
</div>
@@ -91,12 +117,15 @@
</div></div></div>
+ <div class="toolSectionPad"></div><div class="toolSectionTitle">
Statistics
</div>
+ <div class="toolSectionBody"><div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='admin', action='regenerate_statistics' )}">View shed statistics</a></div>
+ </div></div></div></div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/category/edit_category.mako
--- a/templates/webapps/community/category/edit_category.mako
+++ b/templates/webapps/community/category/edit_category.mako
@@ -8,7 +8,7 @@
<div class="toolForm"><div class="toolFormTitle">Change category name and description</div><div class="toolFormBody">
- <form name="library" action="${h.url_for( controller='admin', action='edit_category' )}" method="post" >
+ <form name="edit_category" action="${h.url_for( controller='admin', action='edit_category' )}" method="post" ><div class="form-row"><label>Name:</label><div style="float: left; width: 250px; margin-right: 10px;">
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/index.mako
--- a/templates/webapps/community/index.mako
+++ b/templates/webapps/community/index.mako
@@ -37,6 +37,7 @@
</%def><%def name="left_panel()">
+ <% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %><div class="unified-panel-header" unselectable="on"><div class='unified-panel-header-inner'>${trans.app.shed_counter.valid_tools} valid tools on ${trans.app.shed_counter.generation_time}</div></div>
@@ -72,6 +73,11 @@
<div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='repositories_i_own' )}">Repositories I own</a></div>
+ %if has_reviewed_repositories:
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='reviewed_repositories_i_own' )}">Reviewed repositories I own</a>
+ </div>
+ %endif
<div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='writable_repositories' )}">My writable repositories</a></div>
@@ -85,6 +91,30 @@
<div class="toolTitle"><a target="galaxy_main" href="${h.url_for( controller='repository', action='create_repository' )}">Create new repository</a></div>
+ %if can_review_repositories:
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">
+ Reviewing Repositories
+ </div>
+ <div class="toolSectionBody">
+ <div class="toolSectionBg">
+ %if trans.user.repository_reviews:
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_reviewed_by_me' )}">Repositories reviewed by me</a>
+ </div>
+ %endif
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_with_reviews' )}">All reviewed repositories</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_repositories_without_reviews' )}">Repositories with no reviews</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository_review', action='manage_components' )}">Manage review components</a>
+ </div>
+ </div>
+ </div>
+ %endif
%else:
<div class="toolSectionPad"></div><div class="toolSectionTitle">
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository/manage_repository.mako
--- a/templates/webapps/community/repository/manage_repository.mako
+++ b/templates/webapps/community/repository/manage_repository.mako
@@ -22,6 +22,12 @@
can_set_malicious = metadata and can_set_metadata and is_admin and changeset_revision == repository.tip
can_reset_all_metadata = is_admin and len( repo ) > 0
has_readme = metadata and 'readme' in metadata
+ can_review_repository = trans.app.security_agent.user_can_review_repositories( trans.user )
+ reviewing_repository = cntrller and cntrller == 'repository_review'
+ if changeset_revision == repository.tip:
+ tip_str = 'repository tip'
+ else:
+ tip_str = ''
%><%!
@@ -41,38 +47,53 @@
<br/><br/><ul class="manage-table-actions">
- %if is_new and can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
+ %if reviewing_repository:
+ %if reviewed_by_user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage my review of this revision</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
%else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if has_readme:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_reset_all_metadata:
- <a class="action-button" href="${h.url_for( controller='repository', action='reset_all_metadata', id=trans.security.encode_id( repository.id ) )}">Reset all repository metadata</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
+ %if is_new and can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_review_repository:
+ %if reviewed_by_user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage my review of this revision</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
+ %endif
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
+ %endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
+ %endif
+ %if can_reset_all_metadata:
+ <a class="action-button" href="${h.url_for( controller='repository', action='reset_all_metadata', id=trans.security.encode_id( repository.id ) )}">Reset all repository metadata</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
+ %endif
+ </div>
+ %endif
%endif
</ul>
@@ -86,15 +107,13 @@
<div class="toolFormBody"><form name="change_revision" id="change_revision" action="${h.url_for( controller='repository', action='manage_repository', id=trans.security.encode_id( repository.id ) )}" method="post" ><div class="form-row">
- <%
- if changeset_revision == repository.tip:
- tip_str = 'repository tip'
- else:
- tip_str = ''
- %>
${changeset_revision_select_field.get_html()} <i>${tip_str}</i><div class="toolParamHelp" style="clear: both;">
- Select a revision to inspect and download versions of tools from this repository.
+ %if reviewing_repository or can_review_repository:
+ Select a revision to inspect for adding or managing a review or for download or installation.
+ %else:
+ Select a revision to inspect for download or installation.
+ %endif
</div></div></form>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository/view_repository.mako
--- a/templates/webapps/community/repository/view_repository.mako
+++ b/templates/webapps/community/repository/view_repository.mako
@@ -18,6 +18,8 @@
else:
browse_label = 'Browse repository tip files'
has_readme = metadata and 'readme' in metadata
+ reviewing_repository = cntrller and cntrller == 'repository_review'
+ can_review_repository = trans.app.security_agent.user_can_review_repositories( trans.user )
%><%!
@@ -38,35 +40,50 @@
<br/><br/><ul class="manage-table-actions">
%if trans.webapp.name == 'community':
- %if is_new and can_upload:
- <li><a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a></li>
+ %if reviewing_repository:
+ %if reviewed_by_user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage my review of this revision</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
%else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
- %endif
- %if has_readme:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
+ %if is_new and can_upload:
+ <li><a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a></li>
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_review_repository:
+ %if reviewed_by_user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage my review of this revision</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
+ %endif
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ) )}">Upload files to repository</a>
+ %endif
+ %if has_readme:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_readme', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View README</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
+ %endif
+ </div>
+ %endif
%endif
%else:
<li><a class="action-button" href="${h.url_for( controller='repository', action='install_repositories_by_revision', repository_ids=trans.security.encode_id( repository.id ), changeset_revisions=changeset_revision )}">Install to local Galaxy</a></li>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository/view_tool_metadata.mako
--- a/templates/webapps/community/repository/view_tool_metadata.mako
+++ b/templates/webapps/community/repository/view_tool_metadata.mako
@@ -21,6 +21,7 @@
else:
browse_label = 'Browse repository tip files'
has_readme = metadata and 'readme' in metadata
+ can_review_repository = trans.app.security_agent.user_can_review_repositories( trans.user )
%><%!
@@ -52,6 +53,13 @@
%else:
<li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li><div popupmenu="repository-${repository.id}-popup">
+ %if can_review_repository:
+ %if reviewed_by_user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage my review of this revision</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
+ %endif
%if can_manage:
<a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
%else:
@@ -274,7 +282,6 @@
%>
%if tests:
<div class="form-row">
- <label>Functional tests:</label></td><table class="grid"><tr><td><b>name</b></td>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/browse_review.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/browse_review.mako
@@ -0,0 +1,125 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="*" />
+
+<%
+ from galaxy.web.form_builder import CheckboxField
+ from galaxy.webapps.community.controllers.common import STRSEP
+ can_manage_repository = is_admin or repository.user == trans.user
+%>
+
+<%def name="stylesheets()">
+ ${h.css('base','panel_layout','jquery.rating')}
+</%def>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js( "libs/jquery/jquery.rating" )}
+</%def>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" id="review-${review.id}-popup" class="menubutton">Review Actions</a></li>
+ <div popupmenu="review-${review.id}-popup">
+ %if can_manage_repository:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">View repository</a>
+ %endif
+ </div>
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Review of repository '${repository.name}'</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ <label>Reviewer:</label>
+ ${review.user.username}
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Repository revision:</label>
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='view_or_manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">${changeset_revision_label}</a>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Repository owner:</label>
+ ${repository.user.username}
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Repository synopsis:</label>
+ ${repository.description}
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ %if review.component_reviews:
+ <table class="grid">
+ %for component_review in review.component_reviews:
+ <%
+ component = component_review.component
+
+ # Initialize Private check box.
+ private_check_box_name = '%s%sprivate' % ( component.name, STRSEP )
+ private_check_box = CheckboxField( name=private_check_box_name, checked=component_review.private )
+
+ # Initialize star rating.
+ rating_name = '%s%srating' % ( component.name, STRSEP )
+
+ review_comment = component_review.comment.replace( '\n', '<br/>' )
+ %>
+ <tr>
+ <td bgcolor="#D8D8D8"><b>${component.name}</b></td>
+ <td bgcolor="#D8D8D8">${component.description}</td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table class="grid">
+ <tr>
+ <td>
+ <label>Private:</label>
+ ${private_check_box.get_html( disabled=True )}
+ <div class="toolParamHelp" style="clear: both;">
+ A private review can be accessed only by the owner of the repository and the IUC.
+ </div>
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ %if component_review.comment:
+ <tr>
+ <td>
+ <div overflow-wrap:normal;overflow:hidden;word-break:keep-all;word-wrap:break-word;line-break:strict;>
+ ${review_comment}
+ </div>
+ </td>
+ </tr>
+ %endif
+ <tr>
+ <td>
+ <label>Approved:</label>
+ ${component_review.approved}
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label>Rating:</label>
+ ${render_star_rating( rating_name, component_review.rating, disabled=True )}
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ %endfor
+ </table>
+ %else:
+ This review has not yet been started.
+ %endif
+ </div>
+ </div>
+</div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/create_component.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/create_component.mako
@@ -0,0 +1,34 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $(function(){
+ $("input:text:first").focus();
+ })
+ </script>
+</%def>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Create Component</div>
+ <div class="toolFormBody">
+ <form name="create_component" id="create_component" action="${h.url_for( controller='repository_review', action='create_component' )}" method="post" >
+ <div class="form-row">
+ <label>Name:</label>
+ <input name="name" type="textfield" value="${name}" size=40"/>
+ </div>
+ <div class="form-row">
+ <label>Description:</label>
+ <input name="description" type="textfield" value="${description}" size=40"/>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="create_component_button" value="Save"/>
+ </div>
+ </form>
+ </div>
+</div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/edit_component.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/edit_component.mako
@@ -0,0 +1,37 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Change component description</div>
+ <div class="toolFormBody">
+ <form name="edit_component" action="${h.url_for( controller='repository_review', action='edit_component' )}" method="post" >
+ <div class="form-row">
+ <label>Name:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ ${component.name}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Description:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input name="description" type="textfield" value="${component.description}" size=40"/>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="hidden" name="id" value="${trans.security.encode_id( component.id )}"/>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="edit_component_button" value="Save"/>
+ </div>
+ </form>
+ </div>
+</div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/edit_review.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/edit_review.mako
@@ -0,0 +1,173 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="*" />
+
+<%
+ from galaxy.web.form_builder import CheckboxField
+ from galaxy.webapps.community.controllers.repository_review import build_approved_select_field
+ from galaxy.webapps.community.controllers.common import STRSEP
+ can_manage_repository = is_admin or repository.user == trans.user
+%>
+
+<%def name="stylesheets()">
+ ${h.css('base','panel_layout','jquery.rating')}
+</%def>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js( "libs/jquery/jquery.rating" )}
+</%def>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" id="review-${review.id}-popup" class="menubutton">Review Actions</a></li>
+ <div popupmenu="review-${review.id}-popup">
+ %if can_manage_repository:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">View repository</a>
+ %endif
+ </div>
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">My review of repository '${repository.name}'</div>
+ <div class="toolFormBody">
+ <form name="edit_review" action="${h.url_for( controller='repository_review', action='edit_review', id=trans.security.encode_id( review.id ) )}" method="post" >
+ <div class="form-row">
+ <label>Repository revision:</label>
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='view_or_manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=review.changeset_revision )}">${changeset_revision_label}</a>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Repository owner:</label>
+ ${repository.user.username}
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Repository synopsis:</label>
+ ${repository.description}
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Approve this repository revision?</label>
+ ${revision_approved_select_field.get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ Individual components below may be approved without approving the repository revision.
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="revision_approved_button" value="Save"/>
+ <div class="toolParamHelp" style="clear: both;">
+ All changes made on this page will be saved when any <b>Save</b> button is clicked.
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <table class="grid">
+ %for component_name, component_review_dict in components_dict.items():
+ <%
+ component = component_review_dict[ 'component' ]
+ encoded_component_id = trans.security.encode_id( component.id )
+
+ component_review = component_review_dict[ 'component_review' ]
+ if component_review:
+ comment = component_review.comment or ''
+ rating = component_review.rating
+ approved_select_field_selected_value = component_review.approved
+ private = component_review.private
+ else:
+ comment = ''
+ rating = 0
+ approved_select_field_selected_value = None
+ private = False
+
+ # Initialize Approved select field.
+ approved_select_field_name = '%s%sapproved' % ( component_name, STRSEP )
+ approved_select_field = build_approved_select_field( trans, name=approved_select_field_name, selected_value=approved_select_field_selected_value, for_component=True )
+
+ # Initialize Private check box.
+ private_check_box_name = '%s%sprivate' % ( component_name, STRSEP )
+ private_check_box = CheckboxField( name=private_check_box_name, checked=private )
+
+ # Initialize star rating.
+ rating_name = '%s%srating' % ( component_name, STRSEP )
+
+ # Initialize comment text area.
+ comment_name = '%s%scomment' % ( component_name, STRSEP )
+
+ # Initialize the component id form field name.
+ component_id_name = '%s%scomponent_id' % ( component_name, STRSEP )
+
+ # Initialize the Save button.
+ review_button_name = '%s%sreview_button' % ( component_name, STRSEP )
+ %>
+ <tr>
+ <td bgcolor="#D8D8D8"><b>${component.name}</b></td>
+ <td bgcolor="#D8D8D8">${component.description}</td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table class="grid">
+ <tr>
+ <td>
+ <label>Mark private:</label>
+ ${private_check_box.get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ A private review can be accessed only by the owner of the repository and the IUC.
+ </div>
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label>Comments:</label>
+ %if component_review:
+ <pre><textarea name="${comment_name}" rows="3" cols="80">${comment}</textarea></pre>
+ %else:
+ <textarea name="${comment_name}" rows="3" cols="80"></textarea>
+ %endif
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label>Approved:</label>
+ ${approved_select_field.get_html()}
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label>Rating:</label>
+ ${render_star_rating( rating_name, rating )}
+ <div style="clear: both"></div>
+ <div class="toolParamHelp" style="clear: both;">
+ Rate this component only - the average of all component ratings defines the value of the repository rating.
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <input type="hidden" name="${component_id_name}" value="${encoded_component_id}"/>
+ <input type="submit" name="${review_button_name}" value="Save"/>
+ <div style="clear: both"></div>
+ <div class="toolParamHelp" style="clear: both;">
+ All changes made on this page will be saved when any <b>Save</b> button is clicked.
+ </div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ %endfor
+ </table>
+ </div>
+ </form>
+ </div>
+</div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/grid.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/grid.mako
@@ -0,0 +1,1 @@
+<%inherit file="/grid_base.mako"/>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/reviews_of_changeset_revision.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/reviews_of_changeset_revision.mako
@@ -0,0 +1,145 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="*" />
+<%namespace file="/webapps/community/repository/common.mako" import="*" />
+
+<%
+ from galaxy.webapps.community.controllers.repository_review import build_approved_select_field
+ from galaxy.webapps.community.controllers.common import STRSEP
+ is_admin = trans.user_is_admin()
+ is_new = repository.is_new
+ can_browse_contents = not is_new
+ can_contact_owner = trans.user and trans.user != repository.user
+ can_manage = is_admin or repository.user == trans.user
+ can_push = trans.app.security_agent.can_push( trans.user, repository )
+ can_rate = not is_new and trans.user and repository.user != trans.user
+ can_view_change_log = not is_new
+ if can_push:
+ browse_label = 'Browse or delete repository tip files'
+ else:
+ browse_label = 'Browse repository tip files'
+ if installable:
+ installable_str = 'yes'
+ else:
+ installable_str = 'no'
+ can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user )
+%>
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/community/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="stylesheets()">
+ ${h.css('base','panel_layout','jquery.rating')}
+</%def>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js( "libs/jquery/jquery.rating" )}
+ ${common_javascripts(repository)}
+</%def>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
+ %endif
+ </div>
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Revision reviews of repository '${repository.name}'</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ <label>Revision:</label>
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='view_or_manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">${changeset_revision_label}</a>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Revision is installable:</label>
+ ${installable_str}
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ %if reviews:
+ <table class="grid">
+ <tr>
+ <th>Reviewer</th>
+ <th>Repository rating</th>
+ <th>Approved</th>
+ <th></th>
+ </tr>
+ %for review in reviews:
+ <%
+ encoded_review_id = trans.security.encode_id( review.id )
+ approved_select_field_name = '%s%sapproved' % ( encoded_review_id, STRSEP )
+ approved_select_field_selected_value = review.approved
+ approved_select_field = build_approved_select_field( trans, name=approved_select_field_name, selected_value=approved_select_field_selected_value, for_component=False )
+ if review.approved not in [ None, 'None', 'none' ]:
+ approved_str = review.approved
+ else:
+ approved_str = ''
+ repository_rating_name = '%srepository_rating' % encoded_review_id
+ %>
+ <tr>
+ <td>
+ <div style="float:left;" class="menubutton split popup" id="${encoded_review_id}-popup">
+ <a class="view-info" href="${h.url_for( controller='repository_review', action='repository_reviews_by_user', id=trans.security.encode_id( review.user.id ) )}">${review.user.username}</a>
+ </div>
+ <div popupmenu="${encoded_review_id}-popup">
+ %if review.user == trans.user:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='edit_review', id=encoded_review_id )}">Edit my review</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='browse_review', id=encoded_review_id )}">Browse this review</a>
+ %endif
+ </div>
+ </td>
+ <td>${render_star_rating( repository_rating_name, review.rating, disabled=True )}</td>
+ %if review.user == trans.user:
+ <form name="approve_repository_review" action="${h.url_for( controller='repository_review', action='approve_repository_review', id=encoded_review_id ) }" method="post" >
+ <td>${approved_select_field.get_html()}</td>
+ <td><input type="submit" name="approve_repository_review_button" value="Save"/></td>
+ </form>
+ %else:
+ <td>${approved_str}</td>
+ <td></td>
+ %endif
+ </tr>
+ %endfor
+ </table>
+ %else:
+ <label>This repository revision has not yet been reviewed:</label>
+ %if can_review_repositories:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ <div style="clear: both"></div>
+ %endif
+ %endif
+ </div>
+ <div style="clear: both"></div>
+ </div>
+</div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/reviews_of_repository.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/reviews_of_repository.mako
@@ -0,0 +1,123 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="*" />
+<%namespace file="/webapps/community/repository/common.mako" import="*" />
+
+<%
+ is_admin = trans.user_is_admin()
+ is_new = repository.is_new
+ can_browse_contents = not is_new
+ can_contact_owner = trans.user and trans.user != repository.user
+ can_manage = is_admin or repository.user == trans.user
+ can_push = trans.app.security_agent.can_push( trans.user, repository )
+ can_rate = not is_new and trans.user and repository.user != trans.user
+ can_view_change_log = not is_new
+ if can_push:
+ browse_label = 'Browse or delete repository tip files'
+ else:
+ browse_label = 'Browse repository tip files'
+ if mine:
+ title = "My reviews of repository '%s'" % repository.name
+ review_revision_label = "Manage my review of this revision"
+ else:
+ title = "All reviews of repository '%s'" % repository.name
+ review_revision_label = "Inspect reviews of this revision"
+%>
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/community/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js( "libs/jquery/jquery.rating" )}
+ ${common_javascripts(repository)}
+</%def>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">View repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
+ %endif
+ </div>
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">${title}</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ <table class="grid">
+ <tr>
+ <th>Revision</th>
+ <th>Reviewers</th>
+ <th>Installable</th>
+ </tr>
+ %for changeset_revision, revision_dict in reviews_dict.items():
+ <%
+ changeset_revision_label = revision_dict[ 'changeset_revision_label' ]
+ repository_reviews = revision_dict[ 'repository_reviews' ]
+ repository_metadata_reviews = revision_dict[ 'repository_metadata_reviews' ]
+ reviewers_str = ''
+ if repository_reviews:
+ for repository_review in repository_reviews:
+ reviewers_str += '<a class="view-info" href="'
+ if repository_review.user == trans.user:
+ reviewers_str += 'edit_review'
+ else:
+ reviewers_str += 'browse_review'
+ reviewers_str += '?id=%s">%s</a>' % ( trans.security.encode_id( repository_review.id ), repository_review.user.username )
+ reviewers_str += ' | '
+ reviewers_str = reviewers_str.rstrip( '| ' )
+ if revision_dict[ 'installable' ]:
+ installable_str = 'yes'
+ else:
+ installable_str = ''
+ can_add_review = revision_dict[ 'can_add_review' ]
+ %>
+ <tr>
+ <td>
+ <div style="float:left;" class="menubutton split popup" id="${changeset_revision}-popup">
+ <a class="view-info" href="${h.url_for( controller='repository_review', action='view_or_manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">${changeset_revision_label}</a>
+ </div>
+ <div popupmenu="${changeset_revision}-popup">
+ %if repository_reviews:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='manage_repository_reviews_of_revision', id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Browse reviews of this revision</a>
+ %elif can_add_review:
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Add a review to this revision</a>
+ %endif
+ </div>
+ </td>
+ <td>${reviewers_str}</td>
+ <td>${installable_str}</td>
+ </tr>
+ %endfor
+ </table>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+</div>
diff -r 12fcd068b12eb844d7eded11bd70826c4275021c -r 0698fc666bd04a28b88f1472ac8eeb8dfb3a6423 templates/webapps/community/repository_review/select_previous_review.mako
--- /dev/null
+++ b/templates/webapps/community/repository_review/select_previous_review.mako
@@ -0,0 +1,127 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="*" />
+<%namespace file="/webapps/community/repository/common.mako" import="*" />
+
+<%
+ is_admin = trans.user_is_admin()
+ is_new = repository.is_new
+ can_browse_contents = not is_new
+ can_contact_owner = trans.user and trans.user != repository.user
+ can_manage = is_admin or repository.user == trans.user
+ can_push = trans.app.security_agent.can_push( trans.user, repository )
+ can_rate = not is_new and trans.user and repository.user != trans.user
+ can_view_change_log = not is_new
+ if can_push:
+ browse_label = 'Browse or delete repository tip files'
+ else:
+ browse_label = 'Browse repository tip files'
+ can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user )
+%>
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/community/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="stylesheets()">
+ ${h.css('base','panel_layout','jquery.rating')}
+</%def>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${h.js( "libs/jquery/jquery.rating" )}
+ ${common_javascripts(repository)}
+</%def>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">View repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ) )}">Contact repository owner</a>
+ %endif
+ </div>
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="warningmessage">
+ You have elected to create a new review for revision <b>${changeset_revision_label}</b>of this repository. Since previous revisions have been reviewed,
+ you can select a previous review to copy to your new review, or click the <b>Create a review without copying</b> button.
+</div>
+
+<div class="toolForm">
+ <div class="toolFormTitle">Select previous revision review of repository '${repository.name}'</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ <label>Revision for new review:</label>
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='view_or_manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">${changeset_revision_label}</a>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <table class="grid">
+ <tr>
+ </tr>
+ <td bgcolor="#D8D8D8" colspan="4"><b>Previous revision reviews of repository '${repository.name}' that can be copied to your new review</b></td>
+ <tr>
+ <th>Reviewer</th>
+ <th>Revision reviewed</th>
+ <th>Repository rating</th>
+ <th>Approved</th>
+ </tr>
+ %for previous_changeset_revision, previous_changeset_revision_dict in previous_reviews_dict.items():
+ <%
+ previous_changeset_revision_label = previous_changeset_revision_dict[ 'changeset_revision_label' ]
+ previous_reviews = previous_changeset_revision_dict[ 'reviews' ]
+ %>
+ %for review in previous_reviews:
+ <%
+ encoded_review_id = trans.security.encode_id( review.id )
+ if review.approved not in [ None, 'None', 'none' ]:
+ approved_str = review.approved
+ else:
+ approved_str = ''
+ repository_rating_name = '%srepository_rating' % encoded_review_id
+ %>
+ <tr>
+ <td>
+ <div style="float:left;" class="menubutton split popup" id="${encoded_review_id}-popup">
+ <a class="view-info" href="${h.url_for( controller='repository_review', action='browse_review', id=encoded_review_id )}">${review.user.username}</a>
+ </div>
+ <div popupmenu="${encoded_review_id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, previous_review_id=encoded_review_id )}">Copy this review</a>
+ </div>
+ </td>
+ <td>${previous_changeset_revision_label}</td>
+ <td>${render_star_rating( repository_rating_name, review.rating, disabled=True )}</td>
+ <td>${approved_str}</td>
+ </tr>
+ %endfor
+ %endfor
+ </table>
+ </div>
+ <div style="clear: both"></div>
+ <a class="action-button" href="${h.url_for( controller='repository_review', action='create_review', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, create_without_copying=True )}">Create a review without copying</a>
+ </div>
+</div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/d4aab233e2fd/
changeset: d4aab233e2fd
user: dan
date: 2012-10-18 17:22:12
summary: Unhide failed output datasets.
affected #: 1 file
diff -r ef498097758501bb1d174eaebeca1f11f9251360 -r d4aab233e2fd2195236a38fa6905c77e6bf61187 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -239,6 +239,7 @@
dataset.info = message
dataset.set_size()
dataset.dataset.set_total_size()
+ dataset.mark_unhidden()
if dataset.ext == 'auto':
dataset.extension = 'data'
# Update (non-library) job output datasets through the object store
@@ -379,6 +380,7 @@
# job's state:
if job.states.ERROR == job.state:
dataset.blurb = "error"
+ dataset.mark_unhidden()
elif dataset.has_data():
# If the tool was expected to set the extension, attempt to retrieve it
if dataset.ext == 'auto':
https://bitbucket.org/galaxy/galaxy-central/changeset/12fcd068b12e/
changeset: 12fcd068b12e
user: dan
date: 2012-10-18 17:22:12
summary: Do not hide failed datasets with HideDatasetAction post job action.
affected #: 1 file
diff -r d4aab233e2fd2195236a38fa6905c77e6bf61187 -r 12fcd068b12eb844d7eded11bd70826c4275021c lib/galaxy/jobs/actions/post.py
--- a/lib/galaxy/jobs/actions/post.py
+++ b/lib/galaxy/jobs/actions/post.py
@@ -230,7 +230,7 @@
@classmethod
def execute(cls, app, sa_session, action, job, replacement_dict):
for dataset_assoc in job.output_datasets:
- if action.output_name == '' or dataset_assoc.name == action.output_name:
+ if dataset_assoc.dataset.state != dataset_assoc.dataset.states.ERROR and ( action.output_name == '' or dataset_assoc.name == action.output_name ):
dataset_assoc.dataset.visible=False
@classmethod
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: smcmanus: Fixed minor issue with folder API's routing.
by Bitbucket 17 Oct '12
by Bitbucket 17 Oct '12
17 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/ef4980977585/
changeset: ef4980977585
user: smcmanus
date: 2012-10-18 04:55:00
summary: Fixed minor issue with folder API's routing.
affected #: 3 files
diff -r 4c5297ac9919dd00bb08399131f7adb5892a8891 -r ef498097758501bb1d174eaebeca1f11f9251360 lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -70,9 +70,7 @@
rval.append( dict( id = encoded_id,
type = content.api_type,
name = content.name,
- # TODO: calculate the folder's library id
- # (if necessary) and add library_id=X below:
- url = url_for( controller='folder_content', id=encoded_id ) ) )
+ url = url_for( 'folder_contents', folder_id=encoded_id ) ) )
return rval
@web.expose_api
diff -r 4c5297ac9919dd00bb08399131f7adb5892a8891 -r ef498097758501bb1d174eaebeca1f11f9251360 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -62,13 +62,12 @@
webapp.add_api_controllers( 'galaxy.webapps.galaxy.api', app )
# The /folders section is experimental at this point:
log.debug( "app.config.api_folders: %s" % app.config.api_folders )
- if app.config.api_folders:
- webapp.api_mapper.resource( 'folder', 'folders', path_prefix='/api' )
- webapp.api_mapper.resource( 'content', 'contents',
- controller='folder_contents',
- name_prefix='folder_',
- path_prefix='/api/folders/:folder_id',
- parent_resources=dict( member_name='folder', collection_name='folders' ) )
+ webapp.api_mapper.resource( 'folder', 'folders', path_prefix='/api' )
+ webapp.api_mapper.resource( 'content', 'contents',
+ controller='folder_contents',
+ name_prefix='folder_',
+ path_prefix='/api/folders/:folder_id',
+ parent_resources=dict( member_name='folder', collection_name='folders' ) )
webapp.api_mapper.resource( 'content',
'contents',
controller='library_contents',
diff -r 4c5297ac9919dd00bb08399131f7adb5892a8891 -r ef498097758501bb1d174eaebeca1f11f9251360 lib/galaxy/webapps/galaxy/controllers/library_common.py
--- a/lib/galaxy/webapps/galaxy/controllers/library_common.py
+++ b/lib/galaxy/webapps/galaxy/controllers/library_common.py
@@ -130,7 +130,6 @@
status = "info"
comptypes = get_comptypes( trans )
try:
- # SM: TODO: Add configuration variable asap.
if self.app.config.new_lib_browse:
pass
else:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/4c5297ac9919/
changeset: 4c5297ac9919
user: smcmanus
date: 2012-10-18 00:01:45
summary: Minor cleanup
affected #: 1 file
diff -r 91512b8e1a6ce1c91bd05482afe9a6a774a2ab93 -r 4c5297ac9919dd00bb08399131f7adb5892a8891 lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -22,7 +22,6 @@
we want here. We could add a parameter to use the recursive
style, but this is meant to act similar to an "ls" directory listing.
"""
- log.debug( "FolderContentsController.index: enter" )
rval = []
current_user_roles = trans.get_current_user_roles()
@@ -30,19 +29,15 @@
admin = trans.user_is_admin()
rval = []
for subfolder in folder.active_folders:
- log.debug( "Subfolder type: %s" % type(subfolder) )
if not admin:
- log.debug( "calling check_folder_contents" )
can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, subfolder )
if (admin or can_access) and not subfolder.deleted:
subfolder.api_type = 'folder'
rval.append( subfolder )
for ld in folder.datasets:
- log.debug( "Folder type: %s" % type(folder) )
if not admin:
can_access = trans.app.security_agent.can_access_dataset( current_user_roles, ld.library_dataset_dataset_association.dataset )
if (admin or can_access) and not ld.deleted:
- log.debug( "Folder attributes: %s" % dir(folder) )
ld.api_type = 'file'
rval.append( ld )
return rval
@@ -56,7 +51,6 @@
try:
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( decoded_folder_id )
parent_library = folder.parent_library
- log.debug( "parent library type: %s" % type(parent_library) )
except:
folder = None
log.error( "FolderContentsController.index: Unable to retrieve folder %s"
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: smcmanus: Removed experimental code for improving library browsing performance
by Bitbucket 17 Oct '12
by Bitbucket 17 Oct '12
17 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/91512b8e1a6c/
changeset: 91512b8e1a6c
user: smcmanus
date: 2012-10-17 23:40:25
summary: Removed experimental code for improving library browsing performance
affected #: 5 files
diff -r ba9a8b52e8539693606b07811a6b2bf48b071ae2 -r 91512b8e1a6ce1c91bd05482afe9a6a774a2ab93 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -235,8 +235,10 @@
self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
# Experimental: This will not be enabled by default and will hide
# nonproduction code.
- # The api_folders refers to whether the API exposes
+ # The api_folders refers to whether the API exposes the /folders section.
self.api_folders = string_as_bool( kwargs.get( 'api_folders', False ) )
+ # This is for testing new library browsing capabilities.
+ self.new_lib_browse = string_as_bool( kwargs.get( 'new_lib_browse', False ) )
def __read_tool_job_config( self, global_conf_parser, section, key ):
try:
diff -r ba9a8b52e8539693606b07811a6b2bf48b071ae2 -r 91512b8e1a6ce1c91bd05482afe9a6a774a2ab93 lib/galaxy/security/__init__.py
--- a/lib/galaxy/security/__init__.py
+++ b/lib/galaxy/security/__init__.py
@@ -256,7 +256,7 @@
def get_actions_for_items( self, trans, action, permission_items ):
# TODO: Rename this; it's a replacement for get_item_actions, but it
- # doesn't represent what it's really confusing.
+ # doesn't represent what it's really doing, which is confusing.
# TODO: Make this work for other classes besides lib_datasets.
# That should be as easy as checking the type and writing a query for each;
# we're avoiding using the SQLAlchemy backrefs because they can cause lots
@@ -1179,19 +1179,12 @@
return True, ''
action = self.permitted_actions.DATASET_ACCESS
- # SM: TODO: This is for timing debug. Delete it later.
- from datetime import datetime, timedelta
- query_start = datetime.now()
lddas = self.sa_session.query( self.model.LibraryDatasetDatasetAssociation ) \
.join( "library_dataset" ) \
.filter( self.model.LibraryDataset.folder == folder ) \
.join( "dataset" ) \
.options( eagerload_all( "dataset.actions" ) ) \
.all()
- query_end = datetime.now()
- query_delta = query_end - query_start
- #log.debug( "Check folder contents: join query time: %d.%.6d sec" %
- # ( query_delta.seconds, query_delta.microseconds ) )
for ldda in lddas:
ldda_access_permissions = self.get_item_actions( action, ldda.dataset )
diff -r ba9a8b52e8539693606b07811a6b2bf48b071ae2 -r 91512b8e1a6ce1c91bd05482afe9a6a774a2ab93 lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -25,6 +25,7 @@
log.debug( "FolderContentsController.index: enter" )
rval = []
current_user_roles = trans.get_current_user_roles()
+
def traverse( folder ):
admin = trans.user_is_admin()
rval = []
@@ -54,6 +55,8 @@
try:
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( decoded_folder_id )
+ parent_library = folder.parent_library
+ log.debug( "parent library type: %s" % type(parent_library) )
except:
folder = None
log.error( "FolderContentsController.index: Unable to retrieve folder %s"
diff -r ba9a8b52e8539693606b07811a6b2bf48b071ae2 -r 91512b8e1a6ce1c91bd05482afe9a6a774a2ab93 lib/galaxy/webapps/galaxy/controllers/library_common.py
--- a/lib/galaxy/webapps/galaxy/controllers/library_common.py
+++ b/lib/galaxy/webapps/galaxy/controllers/library_common.py
@@ -131,17 +131,20 @@
comptypes = get_comptypes( trans )
try:
# SM: TODO: Add configuration variable asap.
- return trans.fill_template( 'library/common/browse_library.mako',
- cntrller=cntrller,
- use_panels=use_panels,
- library=library,
- created_ldda_ids=created_ldda_ids,
- hidden_folder_ids=hidden_folder_ids,
- show_deleted=show_deleted,
- comptypes=comptypes,
- current_user_roles=current_user_roles,
- message=message,
- status=status )
+ if self.app.config.new_lib_browse:
+ pass
+ else:
+ return trans.fill_template( 'library/common/browse_library.mako',
+ cntrller=cntrller,
+ use_panels=use_panels,
+ library=library,
+ created_ldda_ids=created_ldda_ids,
+ hidden_folder_ids=hidden_folder_ids,
+ show_deleted=show_deleted,
+ comptypes=comptypes,
+ current_user_roles=current_user_roles,
+ message=message,
+ status=status )
except Exception, e:
message = 'Error attempting to display contents of library (%s): %s.' % ( str( library.name ), str( e ) )
status = 'error'
diff -r ba9a8b52e8539693606b07811a6b2bf48b071ae2 -r 91512b8e1a6ce1c91bd05482afe9a6a774a2ab93 templates/library/common/browse_library_opt.mako
--- a/templates/library/common/browse_library_opt.mako
+++ /dev/null
@@ -1,622 +0,0 @@
-<%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/library_item_info.mako" import="render_library_item_info" />
-<%namespace file="/library/common/common.mako" import="render_actions_on_multiple_items" />
-<%namespace file="/library/common/common.mako" import="render_compression_types_help" />
-<%namespace file="/library/common/common.mako" import="common_javascripts" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/galaxy/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%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_accessible_datasets = False
-%>
-</%def>
-
-##
-## Override methods from base.mako and base_panels.mako
-##
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%;">
- <div class="page-container" style="padding: 10px;">
- ${render_content()}
- </div>
- </div>
-</%def>
-
-## Render the grid's basic elements. Each of these elements can be subclassed.
-<%def name="body()">
- ${render_content()}
-</%def>
-
-<%def name="title()">Browse data library</%def>
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "library" )}
-</%def>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js("libs/json2")}
- ${h.js("libs/jquery/jstorage")}
- ${common_javascripts()}
- ${self.grid_javascripts()}
-</%def>
-
-<%def name="grid_javascripts()">
- <script type="text/javascript">
- var init_libraries = function() {
- var storage_id = "library-expand-state-${trans.security.encode_id(library.id)}";
-
- var restore_folder_state = function() {
- var state = $.jStorage.get(storage_id);
- if (state) {
- for (var id in state) {
- if (state[id] === true) {
- var row = $("#" + id),
- index = row.parent().children().index(row);
- row.addClass("expanded").show();
- row.siblings().filter("tr[parent='" + index + "']").show();
- }
- }
- }
- };
-
- var save_folder_state = function() {
- var state = {};
- $("tr.folderRow").each( function() {
- var folder = $(this);
- state[folder.attr("id")] = folder.hasClass("expanded");
- });
- $.jStorage.set(storage_id, state);
- };
-
- $("#library-grid").each(function() {
- var child_of_parent_cache = {};
- // Recursively fill in children and descendents of each row
- var process_row = function(q, parents) {
- // Find my index
- var parent = q.parent(),
- this_level = child_of_parent_cache[parent] || (child_of_parent_cache[parent] = parent.children());
-
- var index = this_level.index(q);
- // Find my immediate children
- var children = $(par_child_dict[index]);
- // Recursively handle them
- var descendents = children;
- children.each( function() {
- child_descendents = process_row( $(this), parents.add(q) );
- descendents = descendents.add(child_descendents);
- });
- // Set up expand / hide link
- var expand_fn = function() {
- if ( q.hasClass("expanded") ) {
- descendents.hide();
- descendents.removeClass("expanded");
- q.removeClass("expanded");
- } else {
- children.show();
- q.addClass("expanded");
- }
- save_folder_state();
- };
- $("." + q.attr("id") + "-click").click(expand_fn);
- // Check/uncheck boxes in subfolders.
- q.children("td").children("input[type=checkbox]").click( function() {
- if ( $(this).is(":checked") ) {
- descendents.find("input[type=checkbox]").attr("checked", true);
- } else {
- descendents.find("input[type=checkbox]").attr("checked", false);
- // If you uncheck a lower level checkbox, uncheck the boxes above it
- // (since deselecting a child means the parent is not fully selected any more).
- parents.children("td").children("input[type=checkbox]").attr("checked", false);
- }
- });
- // return descendents for use by parent
- return descendents;
- }
-
- // Initialize dict[parent_id] = rows_which_have_that_parent_id_as_parent_attr
- var par_child_dict = {},
- no_parent = [];
-
- $(this).find("tbody tr").each( function() {
- if ( $(this).attr("parent")) {
- var parent = $(this).attr("parent");
- if (par_child_dict[parent] !== undefined) {
- par_child_dict[parent].push(this);
- } else {
- par_child_dict[parent] = [this];
- }
- } else {
- no_parent.push(this);
- }
- });
-
- $(no_parent).each( function() {
- descendents = process_row( $(this), $([]) );
- descendents.hide();
- });
- });
-
- restore_folder_state();
- };
- $(function() {
- init_libraries();
- });
-
- // Looks for changes in dataset state using an async request. Keeps
- // calling itself (via setTimeout) until all datasets are in a terminal
- // state.
- var updater = function ( tracked_datasets ) {
- // Check if there are any items left to track
- var empty = true;
- for ( i in tracked_datasets ) {
- empty = false;
- break;
- }
- if ( ! empty ) {
- setTimeout( function() { updater_callback( tracked_datasets ) }, 3000 );
- }
- };
- var updater_callback = function ( tracked_datasets ) {
- // Build request data
- var ids = []
- var states = []
- $.each( tracked_datasets, function ( id, state ) {
- ids.push( id );
- states.push( state );
- });
- // Make ajax call
- $.ajax( {
- type: "POST",
- url: "${h.url_for( controller='library_common', action='library_item_updates' )}",
- dataType: "json",
- data: { ids: ids.join( "," ), states: states.join( "," ) },
- success : function ( data ) {
- $.each( data, function( id, val ) {
- // Replace HTML
- var cell = $("#libraryItem-" + id).find("#libraryItemInfo");
- cell.html( val.html );
- // If new state was terminal, stop tracking
- if (( val.state == "ok") || ( val.state == "error") || ( val.state == "empty") || ( val.state == "deleted" ) || ( val.state == "discarded" )) {
- delete tracked_datasets[ parseInt(id) ];
- } else {
- tracked_datasets[ parseInt(id) ] = val.state;
- }
- });
- updater( tracked_datasets );
- },
- error: function() {
- // Just retry, like the old method, should try to be smarter
- updater( tracked_datasets );
- }
- });
- };
- </script>
-</%def>
-
-<%def name="render_dataset( cntrller, ldda, library_dataset, can_modify, can_manage, selected, library, folder, pad, parent, row_counter, tracked_datasets, show_deleted=False, simple=False )">
- <%
- ## The received ldda must always be a LibraryDatasetDatasetAssociation object. The object id passed to methods
- ## from the drop down menu should be the ldda id to prevent id collision ( which could happen when displaying
- ## children, which are always lddas ). We also need to make sure we're displaying the latest version of this
- ## library_dataset, so we display the attributes from the ldda.
-
- from galaxy.webapps.galaxy.controllers.library_common import branch_deleted
-
- is_admin = trans.user_is_admin() and cntrller == 'library_admin'
- current_version = ( ldda == library_dataset.library_dataset_dataset_association )
- if current_version and ldda.state not in ( 'ok', 'error', 'empty', 'deleted', 'discarded' ):
- tracked_datasets[ldda.id] = ldda.state
- # SM: This causes a query to be emitted, but it quickly goes down a
- # rabbit hole of many possible inheritable cases. It may not be
- # possible to easily eliminate the extra query from this call.
- info_association, inherited = ldda.get_info_association( restrict=True )
- form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE
- %>
- %if current_version and ( not ldda.library_dataset.deleted or show_deleted ):
- <tr class="datasetRow"
- %if parent is not None:
- parent="${parent}"
- %endif
- id="libraryItem-${ldda.id}">
- <td style="padding-left: ${pad+20}px;">
- <input style="float: left;" type="checkbox" name="ldda_ids" id="${trans.security.encode_id( ldda.id )}" value="${trans.security.encode_id( ldda.id )}"
- %if selected:
- checked="checked"
- %endif
- />
- %if simple:
- <label for="${trans.security.encode_id( ldda.id )}">${ util.unicodify( ldda.name )}</label>
- %else:
- <div style="float: left; margin-left: 1px;" class="menubutton split popup" id="dataset-${ldda.id}-popup">
- <a class="view-info" href="${h.url_for( controller='library_common', action='ldda_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">
- %if ldda.library_dataset.deleted:
- <div class="libraryItem-error">${util.unicodify( ldda.name )}</div>
- %else:
- ${util.unicodify( ldda.name )}
- %endif
- </a>
- </div>
- %if not library.deleted:
- <div popupmenu="dataset-${ldda.id}-popup">
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify:
- <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_edit_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='move_library_item', cntrller=cntrller, item_type='ldda', item_id=trans.security.encode_id( ldda.id ), source_library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Move this dataset</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">View information</a>
- %endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify and not info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='ldda', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a>
- %endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='ldda', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='ldda', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a>
- %endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_manage:
- %if not trans.app.security_agent.dataset_is_public( ldda.dataset ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='ldda', id=trans.security.encode_id( ldda.dataset.id ), use_panels=use_panels, show_deleted=show_deleted )}">Make public</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_permissions', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), id=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
- %endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and can_modify:
- <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), replace_id=trans.security.encode_id( library_dataset.id ), show_deleted=show_deleted )}">Upload a new version of this dataset</a>
- %endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ldda.has_data:
- <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), ldda_ids=trans.security.encode_id( ldda.id ), use_panels=use_panels, show_deleted=show_deleted )}">Import this dataset into selected histories</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='download_dataset_from_folder', cntrller=cntrller, id=trans.security.encode_id( ldda.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels )}">Download this dataset</a>
- %endif
- %if can_modify:
- %if not library.deleted and not branch_deleted( folder ) and not ldda.library_dataset.deleted:
- <a class="action-button" confirm="Click OK to delete dataset '${util.unicodify( ldda.name )}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Delete this dataset</a>
- %elif not library.deleted and not branch_deleted( folder ) and not ldda.library_dataset.purged and ldda.library_dataset.deleted:
- <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library_dataset.id ), item_type='library_dataset', show_deleted=show_deleted )}">Undelete this dataset</a>
- %endif
- %endif
- </div>
- %endif
- %endif
- </td>
- % if not simple:
- <td id="libraryItemInfo">${render_library_item_info( ldda )}</td>
- <td>${ldda.extension}</td>
- % endif
- <td>${ldda.create_time.strftime( "%Y-%m-%d" )}</td>
- <td>${ldda.get_size( nice_size=True )}</td>
- </tr>
- <%
- my_row = row_counter.count
- row_counter.increment()
- %>
- %endif
-</%def>
-
-<%def name="format_delta( tdelta )">
- <%
- from datetime import datetime
- return "%d.%.6d" % ( tdelta.seconds, tdelta.microseconds )
- %>
-</%def>
-
-<%def name="render_folder( cntrller, folder, folder_pad, created_ldda_ids, library, hidden_folder_ids, tracked_datasets, show_deleted=False, parent=None, row_counter=None, root_folder=False, simple=False )">
- <%
- from galaxy.webapps.galaxy.controllers.library_common import active_folders, active_folders_and_library_datasets, activatable_folders_and_library_datasets, map_library_datasets_to_lddas, branch_deleted, datasets_for_lddas
-
- # SM: DELETEME
- from datetime import datetime, timedelta
- import logging
- log = logging.getLogger( __name__ )
-
- is_admin = trans.user_is_admin() and cntrller == 'library_admin'
- has_accessible_library_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, folder, trans.user, current_user_roles, search_downward=False )
-
- if root_folder:
- pad = folder_pad
- expander = h.url_for("/static/images/silk/resultset_bottom.png")
- folder_img = h.url_for("/static/images/silk/folder_page.png")
- else:
- pad = folder_pad + 20
- expander = h.url_for("/static/images/silk/resultset_next.png")
- folder_img = h.url_for("/static/images/silk/folder.png")
- # SM: If this is a comma-delimited list of LDDAs, then split them up
- # into a list. For anything else, turn created_ldda_ids into a single
- # item list.
- if created_ldda_ids:
- created_ldda_ids = util.listify( created_ldda_ids )
- if str( folder.id ) in hidden_folder_ids:
- return ""
- my_row = None
- if is_admin:
- can_add = can_modify = can_manage = True
- elif cntrller in [ 'library' ]:
- can_access, folder_ids = trans.app.security_agent.check_folder_contents( trans.user, current_user_roles, folder )
- if not can_access:
- can_show, folder_ids = \
- trans.app.security_agent.show_library_item( trans.user,
- current_user_roles,
- folder,
- [ trans.app.security_agent.permitted_actions.LIBRARY_ADD,
- trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
- trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ] )
- if not can_show:
- return ""
- can_add = trans.app.security_agent.can_add_library_item( current_user_roles, folder )
- can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, folder )
- can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, folder )
- else:
- can_add = can_modify = can_manage = False
-
- form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE
- info_association, inherited = folder.get_info_association( restrict=True )
- %>
- %if not root_folder and ( not folder.deleted or show_deleted ):
- <% encoded_id = trans.security.encode_id( folder.id ) %>
- <tr id="folder-${encoded_id}" class="folderRow libraryOrFolderRow"
- %if parent is not None:
- parent="${parent}"
- style="display: none;"
- %endif
- >
- <td style="padding-left: ${folder_pad}px;">
- <input type="checkbox" class="folderCheckbox"/>
- <span class="expandLink folder-${encoded_id}-click">
- <div style="float: left; margin-left: 2px;" class="menubutton split popup" id="folder_img-${folder.id}-popup">
- <a class="folder-${encoded_id}-click" href="javascript:void(0);">
- <span class="rowIcon"></span>
- %if folder.deleted:
- <div class="libraryItem-error">${folder.name}</div>
- %else:
- ${folder.name}
- %endif
- </a>
- </div>
- </span>
- %if not library.deleted:
- <div popupmenu="folder_img-${folder.id}-popup">
- %if not branch_deleted( folder ) and can_add:
- <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add datasets</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add sub-folder</a>
- %endif
- %if not branch_deleted( folder ):
- %if has_accessible_library_datasets:
- <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a>
- %endif
- %if can_modify:
- <a class="action-button" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='move_library_item', cntrller=cntrller, item_type='folder', item_id=trans.security.encode_id( folder.id ), source_library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Move this folder</a>
- %else:
- <a class="action-button" class="view-info" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">View information</a>
- %endif
- %endif
- %if not branch_deleted( folder ) and can_modify and not info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a>
- %endif
- %if not branch_deleted( folder ) and can_modify and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a>
- %endif
- %if not branch_deleted( folder ) and can_manage:
- %if not trans.app.security_agent.folder_is_public( folder ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='folder', id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Make public</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
- %endif
- %if can_modify:
- %if not library.deleted and not folder.deleted:
- <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Delete this folder</a>
- %elif not library.deleted and folder.deleted and not folder.purged:
- <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a>
- %endif
- %endif
- </div>
- %endif
- <td>
- %if folder.description:
- ${folder.description}
- %endif
- <td colspan="3"></td>
- </tr>
- <%
- my_row = row_counter.count
- row_counter.increment()
- %>
- %endif
- <%
- # TODO: If show_deleted is set to True, then nothing is displayed. Why? This wasn't the case
- # in the past.
- if show_deleted:
- sub_folders, library_datasets = activatable_folders_and_library_datasets( trans, folder )
- else:
- sub_folders, library_datasets = active_folders_and_library_datasets( trans, folder )
- # Render all the subfolders:
- # TODO: Check permissions first.
- for sub_folder in sub_folders:
- render_folder( cntrller, sub_folder, pad, created_ldda_ids, library, [], tracked_datasets, show_deleted=show_deleted, parent=my_row, row_counter=row_counter, root_folder=False )
-
- # Map LibraryDatasets to LDDAs, then map LDDAs to Datasets.
- # Then determine which Datasets are accessible and which are not.
- # For every LibraryDataset, if there's an LDDA for it and it's
- # accessible then display it.
- if ( len( library_datasets ) > 0 ):
- lib_dataset_ldda_map = map_library_datasets_to_lddas( trans, library_datasets )
- dataset_list = datasets_for_lddas( trans, lib_dataset_ldda_map.values() )
- #can_access_datasets = trans.app.security_agent.dataset_access_mapping( trans, current_user_roles, dataset_list )
- can_access_datasets = trans.app.security_agent.dataset_permission_map_for_access( trans, current_user_roles, dataset_list )
- can_modify_datasets = trans.app.security_agent.item_permission_map_for_modify( trans, current_user_roles, dataset_list )
- can_manage_datasets = trans.app.security_agent.item_permission_map_for_manage( trans, current_user_roles, dataset_list )
- for library_dataset in library_datasets:
- ldda = lib_dataset_ldda_map[ library_dataset.id ]
- if ldda:
- # SMTODO: Fix awkard modify/manage permission checks.
- can_access = is_admin or can_access_datasets[ ldda.dataset_id ]
- can_modify = is_admin or ( cntrller in ['library', 'requests'] and can_modify_datasets[ ldda.dataset_id ])
- can_manage = is_admin or ( cntrller in ['library', 'requests'] and can_manage_datasets[ ldda.dataset_id ])
- selected = created_ldda_ids and str( ldda.id ) in created_ldda_ids
- if can_access:
- render_dataset( cntrller, ldda, library_dataset, can_modify, can_manage, selected, library, folder, pad, my_row, row_counter, tracked_datasets, show_deleted=show_deleted )
- %>
-</%def>
-
-<%def name="render_content(simple=False)">
- <%
- from galaxy import util
- from galaxy.webapps.galaxy.controllers.library_common import branch_deleted
- from time import strftime
- import logging
- log = logging.getLogger( __name__ )
-
- is_admin = trans.user_is_admin() and cntrller == 'library_admin'
-
- if is_admin:
- can_add = can_modify = can_manage = True
- elif cntrller in [ 'library', 'requests' ]:
- can_add = trans.app.security_agent.can_add_library_item( current_user_roles, library )
- can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, library )
- can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, library )
- else:
- can_add = can_modify = can_manage = False
-
- info_association, inherited = library.get_info_association()
- form_type = trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE
-
- # SM: These are mostly display-specific; ignore them for now.
- # The has_accessible_folders determines if anything can be shown - use it.
- self.has_accessible_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, library.root_folder, trans.user, current_user_roles )
- root_folder_has_accessible_library_datasets = trans.app.security_agent.has_accessible_library_datasets( trans, library.root_folder, trans.user, current_user_roles, search_downward=False )
- has_accessible_folders = is_admin or trans.app.security_agent.has_accessible_folders( trans, library.root_folder, trans.user, current_user_roles )
-
- tracked_datasets = {}
-
- class RowCounter( object ):
- def __init__( self ):
- self.count = 0
- def increment( self ):
- self.count += 1
- def __str__( self ):
- return str( self.count )
- %>
-
- <h2>Data Library “${library.name}”</h2>
-
- <ul class="manage-table-actions">
- %if not library.deleted and ( is_admin or can_add ):
- <li><a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( library.root_folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add datasets</a></li>
- <li><a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( library.root_folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add folder</a></li>
- %endif
- %if ( ( not library.deleted ) and ( can_modify or can_manage ) ) or ( can_modify and not library.purged ) or ( library.purged ):
- <li><a class="action-button" id="library-${library.id}-popup" class="menubutton">Library Actions</a></li>
- <div popupmenu="library-${library.id}-popup">
- %if not library.deleted:
- %if can_modify:
- <a class="action-button" href="${h.url_for( controller='library_common', action='library_info', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a>
- <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
- %if show_deleted:
- <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=False )}">Hide deleted items</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=True )}">Show deleted items</a>
- %endif
- %endif
- %if can_modify and not library.info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='library', form_type=form_type, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a>
- %endif
- %if can_modify and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='library', form_type=form_type, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='library', form_type=form_type, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a>
- %endif
- %if can_manage:
- %if not trans.app.security_agent.library_is_public( library, contents=True ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='library', id=trans.security.encode_id( library.id ), contents=True, use_panels=use_panels, show_deleted=show_deleted )}">Make public</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
- %endif
- %if root_folder_has_accessible_library_datasets:
- <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( library.root_folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a>
- %endif
- %elif can_modify and not library.purged:
- <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library', use_panels=use_panels )}">Undelete this data library</a>
- %elif library.purged:
- <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">This data library has been purged</a>
- %endif
- </div>
- %endif
- </ul>
-
- %if message:
- ${render_msg( message, status )}
- %endif
-
- %if library.synopsis not in [ '', 'None', None ]:
- <div class="libraryItemBody">
- ${library.synopsis}
- </div>
- %endif
-
- %if self.has_accessible_datasets:
- <form name="act_on_multiple_datasets" action="${h.url_for( controller='library_common', action='act_on_multiple_datasets', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}" onSubmit="javascript:return checkForm();" method="post">
- %endif
- %if has_accessible_folders:
- <table cellspacing="0" cellpadding="0" border="0" width="100%" class="grid" id="library-grid">
- <thead>
- <tr class="libraryTitle">
- <th>
- %if self.has_accessible_datasets:
- <input type="checkbox" id="checkAll" name=select_all_datasets_checkbox value="true" onclick='checkAllFields(1);'/><input type="hidden" name=select_all_datasets_checkbox value="true"/>
- %endif
- Name
- </th>
- % if not simple:
- <th>Message</th>
- <th>Data type</th>
- % endif
- <th>Date uploaded</th>
- <th>File size</th>
- </tr>
- </thead>
- <% row_counter = RowCounter() %>
- ## SM: Here is where we render the libraries based on admin/non-admin privileges:
- %if cntrller in [ 'library', 'requests' ]:
- ${self.render_folder( 'library', library.root_folder, 0, created_ldda_ids, library, hidden_folder_ids, tracked_datasets, show_deleted=show_deleted, parent=None, row_counter=row_counter, root_folder=True, simple=simple )}
- ## SM: TODO: WTF?
- %if not library.deleted and self.has_accessible_datasets and not simple:
- ${render_actions_on_multiple_items()}
- %endif
- %elif ( trans.user_is_admin() and cntrller in [ 'library_admin', 'requests_admin' ] ):
- ${self.render_folder( 'library_admin', library.root_folder, 0, created_ldda_ids, library, [], tracked_datasets, show_deleted=show_deleted, parent=None, row_counter=row_counter, root_folder=True )}
- ## SM: TODO: WTF?
- %if not library.deleted and not show_deleted and self.has_accessible_datasets:
- ${render_actions_on_multiple_items()}
- %endif
- %endif
- </table>
- %endif
- %if self.has_accessible_datasets:
- </form>
- %endif
-
- %if tracked_datasets:
- <script type="text/javascript">
- // Updater
- updater({${ ",".join( [ '"%s" : "%s"' % ( k, v ) for k, v in tracked_datasets.iteritems() ] ) }});
- </script>
- <!-- running: do not change this comment, used by TwillTestCase.library_wait -->
- %endif
-
- %if self.has_accessible_datasets and not simple:
- ${render_compression_types_help( comptypes )}
- %endif
- %if not has_accessible_folders:
- The data library '${library.name}' does not contain any datasets that you can access.
- %endif
-</%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

17 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/ba9a8b52e853/
changeset: ba9a8b52e853
user: dan
date: 2012-10-17 22:14:17
summary: Fix importing ordering of boto in cloudlaunch.
affected #: 1 file
diff -r b9c0d2847d68269f67241f730e5f3ca8bc534ed3 -r ba9a8b52e8539693606b07811a6b2bf48b071ae2 lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -11,10 +11,10 @@
import os
import tempfile
import time
-import boto
import pkg_resources
from galaxy import eggs
pkg_resources.require('boto')
+import boto
from galaxy import web
from galaxy.web.base.controller import BaseUIController
from galaxy.util.json import to_json_string
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/be1853972823/
changeset: be1853972823
user: dan
date: 2012-10-17 22:06:20
summary: Use simplejson for python2.5 compatibility in genome index.
affected #: 1 file
diff -r be7a8d4808676c7519919483f115811a1b77ec9f -r be1853972823836ffd50654900632d6cd7c74acb lib/galaxy/tools/genome_index/index_genome.py
--- a/lib/galaxy/tools/genome_index/index_genome.py
+++ b/lib/galaxy/tools/genome_index/index_genome.py
@@ -7,7 +7,11 @@
"""
from __future__ import with_statement
-import optparse, sys, os, tempfile, time, subprocess, shlex, json, tarfile, shutil
+import optparse, sys, os, tempfile, time, subprocess, shlex, tarfile, shutil
+
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson
class ManagedIndexer():
def __init__( self, output_file, infile, workingdir, rsync_url, tooldata ):
@@ -72,7 +76,7 @@
return result
def _flush_files( self ):
- json.dump( self.locations, self.outfile )
+ simplejson.dump( self.locations, self.outfile )
self.outfile.close()
self.logfile.close()
https://bitbucket.org/galaxy/galaxy-central/changeset/b9c0d2847d68/
changeset: b9c0d2847d68
user: dan
date: 2012-10-17 22:06:22
summary: Fix for enumerator in python2.5 in datatype sniffer
affected #: 1 file
diff -r be1853972823836ffd50654900632d6cd7c74acb -r b9c0d2847d68269f67241f730e5f3ca8bc534ed3 lib/galaxy/datatypes/sniff.py
--- a/lib/galaxy/datatypes/sniff.py
+++ b/lib/galaxy/datatypes/sniff.py
@@ -94,10 +94,14 @@
"""
fd, temp_name = tempfile.mkstemp()
fp = os.fdopen( fd, "wt" )
- i = 0
- for i, line in enumerate( file( fname, "U" ), 1 ):
+ i = None
+ for i, line in enumerate( file( fname, "U" ) ):
fp.write( "%s\n" % line.rstrip( "\r\n" ) )
fp.close()
+ if i is None:
+ i = 0
+ else:
+ i += 1
if in_place:
shutil.move( temp_name, fname )
# Return number of lines in file.
@@ -119,12 +123,16 @@
regexp = re.compile( patt )
fd, temp_name = tempfile.mkstemp()
fp = os.fdopen( fd, "wt" )
- i = 0
- for i, line in enumerate( file( fname ), 1):
+ i = None
+ for i, line in enumerate( file( fname ) ):
line = line.rstrip( '\r\n' )
elems = regexp.split( line )
fp.write( "%s\n" % '\t'.join( elems ) )
fp.close()
+ if i is None:
+ i = 0
+ else:
+ i += 1
if in_place:
shutil.move( temp_name, fname )
# Return number of lines in file.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
8 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/73dabef59a23/
changeset: 73dabef59a23
user: dan
date: 2012-10-17 21:56:11
summary: Add util.isinf function.
affected #: 1 file
diff -r 53c2605a8ca2fa8086c5c6da3bbbfacd37737510 -r 73dabef59a235e318973fab5a80e844ebc917cc3 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -16,6 +16,14 @@
except ImportError:
from md5 import new as md5
+try:
+ from math import isinf
+except ImportError:
+ INF = float( 'inf' )
+ NEG_INF = -INF
+ ISINF_LIST = [ INF, NEG_INF ]
+ isinf = lambda x: x in ISINF_LIST
+
from galaxy import eggs
import pkg_resources
https://bitbucket.org/galaxy/galaxy-central/changeset/33c475973e46/
changeset: 33c475973e46
user: dan
date: 2012-10-17 21:56:11
summary: Have exit range isinf test use util.isinf for python2.5 compatibility.
affected #: 1 file
diff -r 73dabef59a235e318973fab5a80e844ebc917cc3 -r 33c475973e46d91ff7daef18f537357cbdaf6c06 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1276,8 +1276,8 @@
# isn't bogus. If we have two infinite values, then
# the start must be -inf and the end must be +inf.
# So at least warn about this situation:
- if ( math.isinf( exit_code.range_start ) and
- math.isinf( exit_code.range_end ) ):
+ if ( util.isinf( exit_code.range_start ) and
+ util.isinf( exit_code.range_end ) ):
log.warning( "Tool exit_code range %s will match on "
+ "all exit codes" % code_range )
self.stdio_exit_codes.append( exit_code )
https://bitbucket.org/galaxy/galaxy-central/changeset/1de87a3f82a2/
changeset: 1de87a3f82a2
user: dan
date: 2012-10-17 21:56:12
summary: Fix file read sentinel. Use simplejson for python2.5 compatibility in genome index.
affected #: 1 file
diff -r 33c475973e46d91ff7daef18f537357cbdaf6c06 -r 1de87a3f82a27b89461c0964b77f647ac8619a69 lib/galaxy/tools/genome_index/__init__.py
--- a/lib/galaxy/tools/genome_index/__init__.py
+++ b/lib/galaxy/tools/genome_index/__init__.py
@@ -1,6 +1,6 @@
from __future__ import with_statement
-import os, shutil, logging, tempfile, json, tarfile
+import os, shutil, logging, tempfile, tarfile
from galaxy import model, util
from galaxy.web.framework.helpers import to_unicode
@@ -9,6 +9,10 @@
from galaxy.web.base.controller import UsesHistoryMixin
from galaxy.tools.data import ToolDataTableManager
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson
+
log = logging.getLogger(__name__)
def load_genome_index_tools( toolbox ):
@@ -70,7 +74,7 @@
fp = open( gitd.dataset.get_file_name(), 'r' )
deferred = sa_session.query( model.DeferredJob ).filter_by( id=gitd.deferred_job_id ).first()
try:
- logloc = json.load( fp )
+ logloc = simplejson.load( fp )
except ValueError:
deferred.state = app.model.DeferredJob.states.ERROR
sa_session.add( deferred )
@@ -211,7 +215,7 @@
import hashlib
md5 = hashlib.md5()
with open( filename, 'rb' ) as f:
- for chunk in iter( lambda: f.read( 8192 ), b'' ):
+ for chunk in iter( lambda: f.read( 8192 ), '' ):
md5.update( chunk )
return md5.digest()
https://bitbucket.org/galaxy/galaxy-central/changeset/3fd0416c1062/
changeset: 3fd0416c1062
user: dan
date: 2012-10-17 21:56:12
summary: Use simplejson in lib/galaxy/visualization/data_providers/phyloviz/baseparser.py for python2.5 compatibility.
affected #: 1 file
diff -r 1de87a3f82a27b89461c0964b77f647ac8619a69 -r 3fd0416c1062e269e813004263532d85f1ac7f9b lib/galaxy/visualization/data_providers/phyloviz/baseparser.py
--- a/lib/galaxy/visualization/data_providers/phyloviz/baseparser.py
+++ b/lib/galaxy/visualization/data_providers/phyloviz/baseparser.py
@@ -1,4 +1,6 @@
-import json
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson
class Node(object):
"""Node class of PhyloTree, which represents a CLAUDE in a phylogenetic tree"""
@@ -116,7 +118,7 @@
def toJson(self, jsonDict):
"""Convenience method to get a json string from a python json dict"""
- return json.dumps(jsonDict)
+ return simplejson.dumps(jsonDict)
def _writeJsonToFile(self, filepath, json):
"""Writes the file out to the system"""
https://bitbucket.org/galaxy/galaxy-central/changeset/cc3550b576f8/
changeset: cc3550b576f8
user: dan
date: 2012-10-17 21:56:12
summary: Use simplejson in lib/galaxy/visualization/data_providers/phyloviz/newickparser.py for python2.5 compatibility.
affected #: 1 file
diff -r 3fd0416c1062e269e813004263532d85f1ac7f9b -r cc3550b576f8a1d64b81c4b209aa209d25bf73d9 lib/galaxy/visualization/data_providers/phyloviz/newickparser.py
--- a/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py
+++ b/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
from baseparser import Base_Parser, PhyloTree
import re
https://bitbucket.org/galaxy/galaxy-central/changeset/7389ec156e62/
changeset: 7389ec156e62
user: dan
date: 2012-10-17 21:56:12
summary: Use simplejson in lib/galaxy/visualization/data_providers/phyloviz/nexusparser.py for python2.5 compatibility.
affected #: 1 file
diff -r cc3550b576f8a1d64b81c4b209aa209d25bf73d9 -r 7389ec156e62c3ca3af24b7458396a58ed54ca68 lib/galaxy/visualization/data_providers/phyloviz/nexusparser.py
--- a/lib/galaxy/visualization/data_providers/phyloviz/nexusparser.py
+++ b/lib/galaxy/visualization/data_providers/phyloviz/nexusparser.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
from newickparser import Newick_Parser
import re
https://bitbucket.org/galaxy/galaxy-central/changeset/e6ab6f0524ea/
changeset: e6ab6f0524ea
user: dan
date: 2012-10-17 21:56:12
summary: Use simplejson in data_admin for python2.5 compatibility.
affected #: 1 file
diff -r 7389ec156e62c3ca3af24b7458396a58ed54ca68 -r e6ab6f0524eae90757c4aa17d24c43a2d65fabca lib/galaxy/webapps/galaxy/controllers/data_admin.py
--- a/lib/galaxy/webapps/galaxy/controllers/data_admin.py
+++ b/lib/galaxy/webapps/galaxy/controllers/data_admin.py
@@ -1,4 +1,4 @@
-import sys, ftplib, json
+import sys, ftplib
from galaxy import model, util
from galaxy.jobs import transfer_manager
from galaxy.web.base.controller import *
@@ -6,6 +6,10 @@
from galaxy.model.orm import *
from library_common import get_comptypes, lucene_search, whoosh_search
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson
+
# Older py compatibility
try:
set()
@@ -157,7 +161,7 @@
gname = deferred.params[ 'intname' ]
indexers = ', '.join( deferred.params[ 'indexes' ] )
jobs = self._get_jobs( deferred, trans )
- jsonjobs = json.dumps( jobs )
+ jsonjobs = simplejson.dumps( jobs )
return trans.fill_template( '/admin/data_admin/download_status.mako', name=gname, indexers=indexers, mainjob=jobid, jobs=jobs, jsonjobs=jsonjobs )
@web.expose
@@ -169,7 +173,7 @@
jobid = params.get( 'jobid', '' )
job = sa_session.query( model.DeferredJob ).filter_by( id=jobid ).first()
jobs = self._get_jobs( job, trans )
- return trans.fill_template( '/admin/data_admin/ajax_status.mako', json=json.dumps( jobs ) )
+ return trans.fill_template( '/admin/data_admin/ajax_status.mako', json=simplejson.dumps( jobs ) )
def _get_job( self, jobid, jobtype, trans ):
sa = trans.app.model.context.current
https://bitbucket.org/galaxy/galaxy-central/changeset/be7a8d480867/
changeset: be7a8d480867
user: dan
date: 2012-10-17 21:56:29
summary: Fix for trying to set httponly cookie attribute for python2.5 compatibility.
affected #: 1 file
diff -r e6ab6f0524eae90757c4aa17d24c43a2d65fabca -r be7a8d4808676c7519919483f115811a1b77ec9f lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -6,6 +6,7 @@
import os, sys, time, socket, random, string
import inspect
+from Cookie import CookieError
pkg_resources.require( "Cheetah" )
from Cheetah.Template import Template
@@ -414,7 +415,10 @@
tstamp = time.localtime ( time.time() + 3600 * 24 * age )
self.response.cookies[name]['expires'] = time.strftime( '%a, %d-%b-%Y %H:%M:%S GMT', tstamp )
self.response.cookies[name]['version'] = version
- self.response.cookies[name]['httponly'] = True
+ try:
+ self.response.cookies[name]['httponly'] = True
+ except CookieError, e:
+ log.warning( "Error setting httponly attribute in cookie '%s': %s" % ( name, e ) )
def _ensure_valid_session( self, session_cookie, create=True):
"""
Ensure that a valid Galaxy session exists and is available as
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: dannon: CloudLaunch: Add password confirm field to cloudlaunch to prevent accidentally not knowing your password during presentations.
by Bitbucket 17 Oct '12
by Bitbucket 17 Oct '12
17 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/53c2605a8ca2/
changeset: 53c2605a8ca2
user: dannon
date: 2012-10-17 19:25:29
summary: CloudLaunch: Add password confirm field to cloudlaunch to prevent accidentally not knowing your password during presentations.
Actually display errormessage box to show issues.
affected #: 2 files
diff -r a70bb556b9a5458a878e8abef7a55c88e2f0e058 -r 53c2605a8ca2fa8086c5c6da3bbbfacd37737510 lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -61,7 +61,7 @@
# We need to get persistent data, and the cluster name.
for key in bucket.list():
if key.name.endswith('.clusterName'):
- clusters.append({'name':key.name.split('.clusterName')[0], 'persistent_data': pd.get_contents_as_string()})
+ clusters.append({'name': key.name.split('.clusterName')[0], 'persistent_data': pd.get_contents_as_string()})
account_info['clusters'] = clusters
return to_json_string(account_info)
@@ -76,13 +76,13 @@
except EC2ResponseError, err:
ec2_error = err.error_message
if ec2_error:
- #return trans.fill_template("cloud/run.mako", error = ec2_error)
- return {'errors':[ec2_error]}
+ trans.response.status = 400
+ return ec2_error
else:
- user_provided_data={'cluster_name':cluster_name,
- 'access_key':key_id,
- 'secret_key':secret,
- 'instance_type':instance_type}
+ user_provided_data = {'cluster_name': cluster_name,
+ 'access_key': key_id,
+ 'secret_key': secret,
+ 'instance_type': instance_type}
if password:
user_provided_data['password'] = password
if share_string:
@@ -95,15 +95,13 @@
instance = rs.instances[0]
ct = 0
while not instance.public_dns_name:
- # Can take a second to have public dns name registered.
- # DBTODO, push this into a page update, this is not ideal.
try:
instance.update()
except EC2ResponseError:
- #This can happen when update is invoked before the instance is fully registered. Prevent
- #failure, wait it out.
+ #This can happen when update is invoked before the instance is fully registered.
+ #Prevent failure, wait it out.
pass
- ct +=1
+ ct += 1
time.sleep(1)
if kp_material:
#We have created a keypair. Save to tempfile for one time retrieval.
@@ -123,7 +121,8 @@
'kp_material_tag':kp_material_tag
})
else:
- return {'errors':["Instance failure, but no specific error was detected. Please check your AWS Console."]}
+ trans.response.status = 400
+ return "Instance failure, but no specific error was detected. Please check your AWS Console."
@web.expose
def get_pkey(self, trans, kp_material_tag=None):
diff -r a70bb556b9a5458a878e8abef7a55c88e2f0e058 -r 53c2605a8ca2fa8086c5c6da3bbbfacd37737510 templates/cloud/index.mako
--- a/templates/cloud/index.mako
+++ b/templates/cloud/index.mako
@@ -113,9 +113,16 @@
type: 'POST',
dataType: 'json',
beforeSubmit: function(data){
- //Hide the form, show pending box with spinner.
- $('#launchFormContainer').hide('fast');
- $('#responsePanel').show('fast');
+ if ($('#id_password').val() != $('#id_password_confirm').val()){
+ //Passwords don't match.
+ $('#cloudlaunch_form').prepend('<div class="errormessage">Passwords do not match</div>');
+ return false;
+ }else{
+ $('.errormessage').remove()
+ //Hide the form, show pending box with spinner.
+ $('#launchFormContainer').hide('fast');
+ $('#responsePanel').show('fast');
+ }
},
success: function(data){
//Success Message, link to key download if required, link to server itself.
@@ -144,6 +151,9 @@
$('#instance_dns').text(data.public_dns_name);
$('#launchSuccess').show('fast');
}
+ },
+ error: function(data){
+ $('#cloudlaunch_form').prepend('<div class="errormessage">' + data.responseText + '</div>');
}
});
});
@@ -201,6 +211,12 @@
</div><div class="form-row">
+ <label for="id_password_confirm">Cluster Password - Confirmation</label>
+ <input type="password" size="40" name="password_confirm" id="id_password_confirm"/><br/>
+ </div>
+
+
+ <div class="form-row"><label for="id_keypair">Key Pair</label><select name="keypair" id="id_keypair"><option name="Create" value="cloudman_keypair">cloudman_keypair</option>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0