details: http://www.bx.psu.edu/hg/galaxy/rev/8570bf26275d changeset: 3327:8570bf26275d user: jeremy goecks <jeremy.goecks@emory.edu> date: Thu Feb 04 10:11:50 2010 -0500 description: Added slug editing. Also updated/added HTML escaping on display templates. diffstat: lib/galaxy/web/base/controller.py | 6 ++++ lib/galaxy/web/controllers/history.py | 11 +++++++- lib/galaxy/web/controllers/page.py | 9 ++++++ lib/galaxy/web/controllers/workflow.py | 9 ++++++ static/images/pencil.png | 0 static/scripts/galaxy.base.js | 16 ++++++++++- templates/dataset/display.mako | 10 ++++--- templates/display_base.mako | 8 +++--- templates/display_common.mako | 2 + templates/history/display.mako | 2 +- templates/root/history.mako | 4 +- templates/sharing_base.mako | 43 +++++++++++++++++++++++++++++++- templates/workflow/display.mako | 2 +- templates/workflow/editor.mako | 4 +- templates/workflow/list.mako | 4 +- 15 files changed, 109 insertions(+), 21 deletions(-) diffs (350 lines): diff -r da557305232f -r 8570bf26275d lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py Thu Feb 04 09:18:17 2010 -0500 +++ b/lib/galaxy/web/base/controller.py Thu Feb 04 10:11:50 2010 -0500 @@ -204,6 +204,12 @@ return self.sharing( trans, id, **kwargs ) # Abstract methods. + + @web.expose + @web.require_login( "modify Galaxy items" ) + def set_slug_async( self, trans, id, new_slug ): + """ Set item slug asynchronously. """ + pass @web.expose @web.require_login( "share Galaxy items" ) diff -r da557305232f -r 8570bf26275d lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Thu Feb 04 09:18:17 2010 -0500 +++ b/lib/galaxy/web/controllers/history.py Thu Feb 04 10:11:50 2010 -0500 @@ -395,7 +395,16 @@ trans.sa_session.flush() return - + + @web.expose + @web.require_login( "modify Galaxy items" ) + def set_slug_async( self, trans, id, new_slug ): + history = self.get_history( trans, id ) + if history: + history.slug = new_slug + trans.sa_session.flush() + return + @web.expose def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ): """Return autocomplete data for history names""" diff -r da557305232f -r 8570bf26275d lib/galaxy/web/controllers/page.py --- a/lib/galaxy/web/controllers/page.py Thu Feb 04 09:18:17 2010 -0500 +++ b/lib/galaxy/web/controllers/page.py Thu Feb 04 10:11:50 2010 -0500 @@ -541,6 +541,15 @@ return @web.expose + @web.require_login( "modify Galaxy items" ) + def set_slug_async( self, trans, id, new_slug ): + page = self.get_page( trans, id ) + if page: + page.slug = new_slug + trans.sa_session.flush() + return + + @web.expose @web.json @web.require_login( "use Galaxy pages" ) def get_name_and_link_async( self, trans, id=None ): diff -r da557305232f -r 8570bf26275d lib/galaxy/web/controllers/workflow.py --- a/lib/galaxy/web/controllers/workflow.py Thu Feb 04 09:18:17 2010 -0500 +++ b/lib/galaxy/web/controllers/workflow.py Thu Feb 04 10:11:50 2010 -0500 @@ -383,6 +383,15 @@ return @web.expose + @web.require_login( "modify Galaxy items" ) + def set_slug_async( self, trans, id, new_slug ): + stored = get_stored_workflow( trans, id ) + if stored: + stored.slug = new_slug + trans.sa_session.flush() + return + + @web.expose @web.json @web.require_login( "use Galaxy workflows" ) def get_name_and_link_async( self, trans, id=None ): diff -r da557305232f -r 8570bf26275d static/images/pencil.png Binary file static/images/pencil.png has changed diff -r da557305232f -r 8570bf26275d static/scripts/galaxy.base.js --- a/static/scripts/galaxy.base.js Thu Feb 04 09:18:17 2010 -0500 +++ b/static/scripts/galaxy.base.js Thu Feb 04 10:11:50 2010 -0500 @@ -211,7 +211,7 @@ // // Edit and save text asynchronously. // -function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, use_textarea, num_rows) +function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, use_textarea, num_rows, on_start, on_finish) { $("#" + click_to_edit_elt).click( function() { var old_text = $("#" + text_elt_id).text() @@ -236,13 +236,25 @@ $.ajax({ url: save_url, data: ajax_data, - error: function() { alert( "Text editing for elt " + text_elt_id + " failed" ) }, + error: function() { + alert( "Text editing for elt " + text_elt_id + " failed" ); + // TODO: call finish or no? For now, let's not because error occurred. + }, success: function() { + // Set new text and call finish method. $("#" + text_elt_id).text( new_text ); + if (on_finish != null) + on_finish(t); } }); } }); + + // Call onstart method if it exists. + if (on_start != null) + on_start(t); + + // Replace text with input object and focus & select. $("#" + text_elt_id).hide(); t.insertAfter( $("#" + text_elt_id) ); t.focus(); diff -r da557305232f -r 8570bf26275d templates/dataset/display.mako --- a/templates/dataset/display.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/dataset/display.mako Thu Feb 04 10:11:50 2010 -0500 @@ -18,7 +18,7 @@ </%def> <%def name="title()"> - Galaxy | ${get_class_display_name( item.__class__ )} | ${get_item_name( item )} + Galaxy | ${get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h} </%def> <%def name="render_item_links( data )"> @@ -43,7 +43,7 @@ <div class="unified-panel-header" unselectable="on"> <div class="unified-panel-header-inner"> ${get_class_display_name( item.__class__ )} - | ${get_item_name( item )} + | ${get_item_name( item ) | h} </div> </div> @@ -72,11 +72,13 @@ <div style="padding: 10px;"> <h4>Author</h4> - <p>${item.history.user.username}</p> + <p>${item.history.user.username | h}</p> <div><img src="http://www.gravatar.com/avatar/${h.md5(item.history.user.email)}?s=150"></div> - ## Page meta. No page meta for datasets for now. + ## Page meta. + + ## No links for datasets right now. ## Tags. <p> diff -r da557305232f -r 8570bf26275d templates/display_base.mako --- a/templates/display_base.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/display_base.mako Thu Feb 04 10:11:50 2010 -0500 @@ -13,13 +13,13 @@ <%namespace file="/display_common.mako" import="*" /> <%def name="title()"> - Galaxy | ${iff( item.published, "Published ", iff( item.importable , "Accessible ", iff( item.users_shared_with, "Shared ", "Private " ) ) ) + get_class_display_name( item.__class__ )} | ${get_item_name( item )} + Galaxy | ${iff( item.published, "Published ", iff( item.importable , "Accessible ", iff( item.users_shared_with, "Shared ", "Private " ) ) ) + get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h} </%def> <%def name="init()"> <% self.has_left_panel=False - self.has_right_panel=item.published + self.has_right_panel=True self.message_box_visible=False self.active_view="user" self.overlay_visible=False @@ -152,7 +152,7 @@ <div style="padding: 10px;"> <h4>Author</h4> - <p>${item.user.username}</p> + <p>${item.user.username | h}</p> <div><img src="http://www.gravatar.com/avatar/${h.md5(item.user.email)}?s=150"></div> @@ -162,7 +162,7 @@ <h4>Related ${item_plural}</h4> <p> <a href="${href_to_all_items}">All published ${item_plural.lower()}</a><br> - <a href="${href_to_user_items}">${item_plural} owned by ${item.user.username}</a> + <a href="${href_to_user_items}">Published ${item_plural.lower()} by ${item.user.username | h}</a> ## Tags. <h4>Tags</strong></h4> diff -r da557305232f -r 8570bf26275d templates/display_common.mako --- a/templates/display_common.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/display_common.mako Thu Feb 04 10:11:50 2010 -0500 @@ -1,6 +1,8 @@ ## ## Utilities for sharing items and displaying shared items. +## HACK: these should probably go in the web helper object. ## + <%! from galaxy import model %> ## Get display name for a class. diff -r da557305232f -r 8570bf26275d templates/history/display.mako --- a/templates/history/display.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/history/display.mako Thu Feb 04 10:11:50 2010 -0500 @@ -241,7 +241,7 @@ <%def name="render_item( history, datasets )"> <div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold; padding: 0px 0px 5px 0px"> - <div id="history-name">${history.get_display_name()}</div> + <div id="history-name">${history.get_display_name() | h}</div> </div> %if history.deleted: diff -r da557305232f -r 8570bf26275d templates/root/history.mako --- a/templates/root/history.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/root/history.mako Thu Feb 04 10:11:50 2010 -0500 @@ -276,7 +276,7 @@ <div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold;"> <div style="float: right"><a id="history-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='rename' )}"></a></div> - <div id="history-name">${h.escape( history.get_display_name() )}</div> + <div id="history-name">${history.get_display_name() | h}</div> </div> %if history.deleted: @@ -311,7 +311,7 @@ <label>Annotation / Notes:</label> <div style="float: right"><a id="history-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='annotate_async' )}"></a></div> %if annotation: - <div id="history-annotation">${h.escape(annotation)}</div> + <div id="history-annotation">${annotation | h}</div> %else: <div id="history-annotation"></div> %endif diff -r da557305232f -r 8570bf26275d templates/sharing_base.mako --- a/templates/sharing_base.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/sharing_base.mako Thu Feb 04 10:11:50 2010 -0500 @@ -15,6 +15,40 @@ Sharing and Publishing ${get_class_display_name( item.__class__ )} '${get_item_name( item )}' </%def> +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + $(document).ready( function() + { + // + // Set up slug-editing functionality. + // + var on_start = function( text_elt ) + { + // Because text element is inside a URL, need to disable click so that clicking on element does not trigger URL. + $( text_elt ).click( function() { + return false; + }); + + // Allow only lowercase alphanumeric and '-' characters in slug. + text_elt.keyup(function(){ + text_elt.val( $(this).val().replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() ) + }); + }; + + var on_finish = function( text_elt ) + { + // Set URL to new value. + var item_url_obj = $('#item-url'); + item_url_obj.attr( "href", item_url_obj.text() ); + }; + + <% controller_name = get_controller_name( item ) %> + async_save_text("edit-identifier", "item-identifier", "${h.url_for( controller=controller_name, action='set_slug_async', id=trans.security.encode_id( item.id ) )}", "new_slug", false, 0, on_start, on_finish); + }); + </script> +</%def> + <%def name="stylesheets()"> ${parent.stylesheets()} <style> @@ -77,9 +111,14 @@ This ${item_class_name_lc} <strong>${item_status}</strong>. <div> <p>Anyone can view and import this ${item_class_name_lc} by visiting the following URL: - <% url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True ) %> + <blockquote> - <a href="${url}" target="_top">${url}</a> + <% + url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True ) + url_parts = url.split("/") + %> + <a id="item-url" href="${url}" target="_top">${"/".join( url_parts[:-1] )}/<span id='item-identifier'>${url_parts[-1]}</span></a> + <a href="#" id="edit-identifier"><img src="${h.url_for('/static/images/pencil.png')}"/></a> </blockquote> %if item.published: diff -r da557305232f -r 8570bf26275d templates/workflow/display.mako --- a/templates/workflow/display.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/workflow/display.mako Thu Feb 04 10:11:50 2010 -0500 @@ -78,7 +78,7 @@ </%def> <%def name="render_item( workflow, steps )"> - <h2>${workflow.name}</h2> + <h2>${workflow.name | h}</h2> %for i, step in enumerate( steps ): %if step.type == 'tool' or step.type is None: <% tool = app.toolbox.tools_by_id[step.tool_id] %> diff -r da557305232f -r 8570bf26275d templates/workflow/editor.mako --- a/templates/workflow/editor.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/workflow/editor.mako Thu Feb 04 10:11:50 2010 -0500 @@ -784,7 +784,7 @@ <div id="workflow-name-area" class="form-row"> <label>Name:</label> <div style="float: right"><a id="workflow-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='rename_sync' )}"></a></div> - <div id="workflow-name">${h.escape( stored.name )}</div> + <div id="workflow-name">${stored.name | h}</div> <div style="clear: both"></div> </div> ## Workflow tags. @@ -809,7 +809,7 @@ <div id="workflow-annotation-area" class="form-row"> <label>Annotation / Notes:</label> <div style="float: right"><a id="workflow-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div> - <div id="workflow-annotation">${h.escape( annotation )}</div> + <div id="workflow-annotation">${annotation | h}</div> <div style="clear: both"></div> <div class="toolParamHelp">Add an annotation or notes to a workflow; annotations are available when a workflow is viewed.</div> </div> diff -r da557305232f -r 8570bf26275d templates/workflow/list.mako --- a/templates/workflow/list.mako Thu Feb 04 09:18:17 2010 -0500 +++ b/templates/workflow/list.mako Thu Feb 04 10:11:50 2010 -0500 @@ -38,7 +38,7 @@ <tr> <td> <div class="menubutton" style="float: left;" id="wf-${i}-popup"> - ${workflow.name} + ${workflow.name | h} </div> </td> <td>${len(workflow.latest_workflow.steps)}</td> @@ -76,7 +76,7 @@ <% workflow = association.stored_workflow %> <tr> <td> - <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name}</a> + <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a> </td> <td>${workflow.user.email}</td> <td>${len(workflow.latest_workflow.steps)}</td>