1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/f0eea6ef4824/ changeset: f0eea6ef4824 user: carlfeberhard date: 2012-09-26 23:42:45 summary: compile_templates.py: handle multi-template files better; (alternate_)history: fix download popup menus affected #: 15 files diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/galaxy.base.js --- a/static/scripts/galaxy.base.js +++ b/static/scripts/galaxy.base.js @@ -66,14 +66,15 @@ }; function make_popupmenu(button_element, initial_options) { - /* Use the $.data feature to store options with the link element. This allows options to be changed at a later time */ var element_menu_exists = (button_element.data("menu_options")); button_element.data("menu_options", initial_options); + // If element already has menu, nothing else to do since HTML and actions are already set. if (element_menu_exists) { return; } + button_element.bind("click.show_popup", function(e) { // Close existing visible menus $(".popmenu-wrapper").remove(); @@ -93,7 +94,8 @@ menu_element.append( $("<li></li>").addClass( "head" ).append( $("<a href='#'></a>").html(k) ) ); } }); - var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ).append( menu_element ).appendTo( "body" ); + var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ) + .append( menu_element ).appendTo( "body" ); var x = e.pageX - wrapper.width() / 2 ; x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 5 ); @@ -137,6 +139,7 @@ var confirmtext = link_dom.getAttribute( "confirm" ), href = link_dom.getAttribute( "href" ), target = link_dom.getAttribute( "target" ); + if (!href) { options[ link.text() ] = null; } else { @@ -161,6 +164,7 @@ }; } }); + // locate the element with the id corresponding to the menu's popupmenu attr var box = $( "#" + menu.attr( 'popupmenu' ) ); // For menus with clickable link text, make clicking on the link go through instead @@ -170,6 +174,7 @@ return true; }); + // attach the click events and menu box building to the box element make_popupmenu(box, options); box.addClass("popup"); menu.remove(); diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/mvc/history.js --- a/static/scripts/mvc/history.js +++ b/static/scripts/mvc/history.js @@ -1,4 +1,8 @@ -/* +//define([ +// "../mvc/base-mvc" +// +//], function(){ +/* ============================================================================= Backbone.js implementation of history panel TODO: @@ -10,6 +14,8 @@ _render_displayApps _render_downloadButton widget building (popupmenu, etc.) + history.mako js: updater, etc. + have info bodies prev. opened, redisplay on refresh don't draw body until it's first unhide event all history.mako js -> this @@ -30,26 +36,7 @@ move inline styles into base.less add classes, ids on empty divs watch the magic strings -*/ - -//============================================================================== - -//============================================================================== -//TODO: move to Galaxy obj./namespace, decorate for current page (as GalaxyPaths) -/* -var Localizable = { - localizedStrings : {}, - setLocalizedString : function( str, localizedString ){ - this.localizedStrings[ str ] = localizedString; - }, - localize : function( str ){ - if( str in this.localizedStrings ){ return this.localizedStrings[ str ]; } - return str; - } -}; -var LocalizableView = LoggingView.extend( Localizable ); -*/ -//TODO: wire up to views +============================================================================= */ //============================================================================== // jq plugin? @@ -204,12 +191,7 @@ // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.) itemWrapper.find( '.tooltip' ).tooltip({ placement : 'bottom' }); - //TODO: broken - var popupmenus = itemWrapper.find( '[popupmenu]' ); - popupmenus.each( function( i, menu ){ - menu = $( menu ); - make_popupmenu( menu ); - }); + make_popup_menus(); //TODO: better transition/method than this... this.$el.children().remove(); @@ -343,54 +325,23 @@ // ................................................................................ primary actions _render_primaryActionButtons : function( buttonRenderingFuncs ){ - var primaryActionButtons = $( '<div/>' ), + var primaryActionButtons = $( '<div/>' ).attr( 'id', 'primary-actions-' + this.model.get( 'id' ) ), view = this; _.each( buttonRenderingFuncs, function( fn ){ - primaryActionButtons.append( fn.call( view ) ); + var render_return = fn.call( view ); + primaryActionButtons.append( render_return ); }); return primaryActionButtons; }, _render_downloadButton : function(){ + // don't show anything if the data's been purged + //if( this.model.get( 'purged' ) ){ return null; } + // return either: a single download icon-button (if there are no meta files) // or a popupmenu with links to download assoc. meta files (if there are meta files) - - // don't show anything if the data's been purged - if( this.model.get( 'purged' ) ){ return null; } - - var downloadLink = linkHTMLTemplate({ - title : 'Download', - href : this.model.get( 'download_url' ), - classes : [ 'icon-button', 'tooltip', 'disk' ] - }); - - // if no metafiles, return only the main download link - var download_meta_urls = this.model.get( 'download_meta_urls' ); - if( !download_meta_urls ){ - return downloadLink; - } - - // build the popupmenu for downloading main, meta files - var popupmenu = $( '<div popupmenu="dataset-' + this.model.get( 'id' ) + '-popup"></div>' ); - popupmenu.append( linkHTMLTemplate({ - text : 'Download Dataset', - title : 'Download', - href : this.model.get( 'download_url' ), - classes : [ 'icon-button', 'tooltip', 'disk' ] - })); - popupmenu.append( '<a>Additional Files</a>' ); - for( file_type in download_meta_urls ){ - popupmenu.append( linkHTMLTemplate({ - text : 'Download ' + file_type, - href : download_meta_urls[ file_type ], - classes : [ 'action-button' ] - })); - } - var menuButton = $( ( '<div style="float:left;" class="menubutton split popup"' - + ' id="dataset-${dataset_id}-popup"></div>' ) ); - menuButton.append( downloadLink ); - popupmenu.append( menuButton ); - return popupmenu; + var downloadLinkHTML = HistoryItemView.templates.downloadLinks( this.model.toJSON() ); + return $( downloadLinkHTML ); }, //NOTE: button renderers have the side effect of caching their IconButtonViews to this view @@ -451,8 +402,12 @@ // ................................................................................ secondary actions _render_secondaryActionButtons : function( buttonRenderingFuncs ){ // move to the right (same level as primary) - var secondaryActionButtons = $( '<div style="float: right;"></div>' ), + var secondaryActionButtons = $( '<div/>' ), view = this; + secondaryActionButtons + .attr( 'style', 'float: right;' ) + .attr( 'id', 'secondary-actions-' + this.model.get( 'id' ) ); + _.each( buttonRenderingFuncs, function( fn ){ secondaryActionButtons.append( fn.call( view ) ); }); @@ -817,7 +772,8 @@ hdaSummary : 'template-history-hdaSummary', failedMetadata : 'template-history-failedMetaData', tagArea : 'template-history-tagArea', - annotationArea : 'template-history-annotationArea' + annotationArea : 'template-history-annotationArea', + downloadLinks : 'template-history-downloadLinks' } }); @@ -967,163 +923,10 @@ //============================================================================== -function createMockHistoryData(){ - mockHistory = {}; - mockHistory.data = { - - template : { - id : 'a799d38679e985db', - name : 'template', - data_type : 'fastq', - file_size : 226297533, - genome_build : '?', - metadata_data_lines : 0, - metadata_dbkey : '?', - metadata_sequences : 0, - misc_blurb : '215.8 MB', - misc_info : 'uploaded fastq file (misc_info)', - model_class : 'HistoryDatasetAssociation', - download_url : '', - state : 'ok', - visible : true, - deleted : false, - purged : false, - - hid : 0, - //TODO: move to history - for_editing : true, - //for_editing : false, - - //?? not needed - //can_edit : true, - //can_edit : false, - - accessible : true, - - //TODO: move into model functions (build there (and cache?)) - //!! be careful with adding these accrd. to permissions - //!! IOW, don't send them via template/API if the user doesn't have perms to use - //!! (even if they don't show up) - undelete_url : '', - purge_url : '', - unhide_url : '', - - display_url : 'example.com/display', - edit_url : 'example.com/edit', - delete_url : 'example.com/delete', - - show_params_url : 'example.com/show_params', - rerun_url : 'example.com/rerun', - - retag_url : 'example.com/retag', - annotate_url : 'example.com/annotate', - - peek : [ - '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>', - '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>', - '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>', - '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>', - '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>', - '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', - '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', - '</table>' - ].join( '' ) - } - - }; - _.extend( mockHistory.data, { - - notAccessible : - _.extend( _.clone( mockHistory.data.template ), - { accessible : false }), - - //deleted, purged, visible - deleted : - _.extend( _.clone( mockHistory.data.template ), - { deleted : true, - delete_url : '', - purge_url : 'example.com/purge', - undelete_url : 'example.com/undelete' }), - purgedNotDeleted : - _.extend( _.clone( mockHistory.data.template ), - { purged : true, - delete_url : '' }), - notvisible : - _.extend( _.clone( mockHistory.data.template ), - { visible : false, - unhide_url : 'example.com/unhide' }), - - hasDisplayApps : - _.extend( _.clone( mockHistory.data.template ), - { display_apps : { - 'display in IGB' : { - Web: "/display_application/63cd3858d057a6d1/igb_bam/Web", - Local: "/display_application/63cd3858d057a6d1/igb_bam/Local" - } - } - } - ), - canTrackster : - _.extend( _.clone( mockHistory.data.template ), - { trackster_urls : { - 'data-url' : "example.com/trackster-data", - 'action-url' : "example.com/trackster-action", - 'new-url' : "example.com/trackster-new" - } - } - ), - zeroSize : - _.extend( _.clone( mockHistory.data.template ), - { file_size : 0 }), - - hasMetafiles : - _.extend( _.clone( mockHistory.data.template ), { - download_meta_urls : { - 'bam_index' : "example.com/bam-index" - } - }), - - //states - upload : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.UPLOAD }), - queued : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.QUEUED }), - running : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.RUNNING }), - empty : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.EMPTY }), - error : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.ERROR, - report_error_url: 'example.com/report_err' }), - discarded : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.DISCARDED }), - setting_metadata : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.SETTING_METADATA }), - failed_metadata : - _.extend( _.clone( mockHistory.data.template ), - { state : HistoryItem.STATES.FAILED_METADATA }) -/* -*/ - }); - - $( document ).ready( function(){ - //mockHistory.views.deleted.logger = console; - mockHistory.items = {}; - mockHistory.views = {}; - for( key in mockHistory.data ){ - mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] ); - mockHistory.items[ key ].set( 'name', key ); - mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] }); - //console.debug( 'view: ', mockHistory.views[ key ] ); - $( 'body' ).append( mockHistory.views[ key ].render() ); - } - }); -} - +//return { +// HistoryItem : HistoryItem, +// HitoryItemView : HistoryItemView, +// HistoryCollection : HistoryCollection, +// History : History, +// HistoryView : HistoryView +//};}); diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/compile_templates.py --- a/static/scripts/templates/compile_templates.py +++ b/static/scripts/templates/compile_templates.py @@ -46,153 +46,99 @@ from glob import glob from subprocess import call -from shutil import copyfile -from os import path +import os from optparse import OptionParser -from HTMLParser import HTMLParser +import re -import logging -log = logging.getLogger( __name__ ) +import logging as log +log.basicConfig( + #level = log.DEBUG, + name = __name__ +) COMPILED_DIR = 'compiled' COMPILED_EXT = '.js' COMPILE_CMD_STR = "handlebars %s -f %s" COMPILE_MINIMIZE_SWITCH = ' -m' +TEMPLATE_TAG = 'script' +TEMPLATE_TYPE = 'text/template' +HELPER_TYPE = 'text/javascript' + # both of these are off by default for backward compat DEFAULT_MINIMIZATION = False DEFAULT_MULTI_EXT = None #'.html' # ------------------------------------------------------------------------------ -class HTMLMultiTemplateParser( HTMLParser ): - """Parses multiple templates from an HTML file, saving them to a map of: - { id : template_text, ... } +def parse_html_tag_attrs( string ): + attrs = {} + for match in re.finditer( r'(?P<key>\w+?)=[\'|\"](?P<val>.*?)[\'|\"]', string, re.DOTALL | re.MULTILINE ): + match = match.groupdict() + key = match[ 'key' ] + val = match[ 'val' ] + attrs[ key ] = val + return attrs + +def split_on_html_tag( string, tag ): + tag_pattern = r'<%s\s*(?P<attrs>.*?)>(?P<body>.*?)</%s>' % ( tag, tag ) + log.debug( tag_pattern ) + tag_pattern = re.compile( tag_pattern, re.MULTILINE | re.DOTALL ) + + found_list = re.findall( tag_pattern, string ) + for attrs, body in found_list: + yield ( parse_html_tag_attrs( attrs ), body ) + +def filter_on_tag_type( generator, type_attr_to_match ): + for attrs, body in generator: + log.debug( 'attrs: %s', str( attrs ) ) + if( ( 'type' in attrs ) + and ( attrs[ 'type' ] == type_attr_to_match ) ): + yield attrs, body + - Templates must: - * be within the TEMPLATE_TAG - * TEMPLATE_TAG must have a type attribute - * that attr must == TEMPLATE_TYPE - * TEMPLATE_TAG cannot be nested within one another - * TEMPLATE_TAG must have an id attribute - """ - TEMPLATE_TAG = 'script' - TEMPLATE_TYPES = [ 'text/template' ] - - HELPER_TAG = 'script' - HELPER_TYPES = [ 'text/javascript' ] - - def __init__( self ): - HTMLParser.__init__( self ) - self.templates = {} - self.curr_template_id = None - self.template_data = '' - - self.helpers = {} - self.curr_helper_id = None - self.helper_data = '' - - def is_template_tag( self, tag, attr_dict ): - # both tag and type attr must match - return ( ( tag == self.TEMPLATE_TAG ) - and ( 'type' in attr_dict ) - and ( attr_dict[ 'type' ] in self.TEMPLATE_TYPES ) ) - - def is_helper_tag( self, tag, attr_dict ): - # both tag and type attr must match - return ( ( tag == self.HELPER_TAG ) - and ( 'type' in attr_dict ) - and ( attr_dict[ 'type' ] in self.HELPER_TYPES ) ) - - def handle_starttag( self, tag, attrs ): - attr_dict = dict( attrs ) - if self.is_template_tag( tag, attr_dict ): - log.debug( "\t template tag: %s, %s", tag, str( attr_dict ) ); - - # as far as I know these tags can't/shouldn't nest/overlap - #pre: not already inside a template/helper tag - assert self.curr_template_id == None, "Found nested template tag: %s" % ( self.curr_template_id ) - assert self.curr_helper_id == None, "Found template tag inside helper: %s" % ( self.curr_helper_id ) - #pre: must have an id - assert 'id' in attr_dict, "No id attribute in template: " + str( attr_dict ) - - self.curr_template_id = attr_dict[ 'id' ] - - elif self.is_helper_tag( tag, attr_dict ): - log.debug( "\t helper tag: %s, %s", tag, str( attr_dict ) ); - - #pre: not already inside a template/helper tag - assert self.curr_helper_id == None, "Found nested helper tag: %s" % ( self.curr_helper_id ) - assert self.curr_template_id == None, "Found helper tag inside template: %s" % ( self.curr_template_id ) - #pre: must have an id - assert 'id' in attr_dict, "No id attribute in helper: " + str( attr_dict ) - - self.curr_helper_id = attr_dict[ 'id' ] - - def handle_endtag( self, tag ): - if( ( tag == self.TEMPLATE_TAG ) - and ( self.curr_template_id ) ): - log.debug( "\t ending template tag :", tag, self.curr_template_id ); - - # store the template data by the id - if self.template_data: - self.templates[ self.curr_template_id ] = self.template_data - - #! reset for next template - self.curr_template_id = None - self.template_data = '' - - elif( ( tag == self.HELPER_TAG ) - and ( self.curr_helper_id ) ): - log.debug( "\t ending helper tag :", tag, self.curr_template_id ); - - # store the template data by the id - if self.helper_data: - self.helpers[ self.curr_helper_id ] = self.helper_data - - #! reset for next template - self.curr_helper_id = None - self.helper_data = '' - - def handle_data(self, data): - data = data.strip() - if data: - if self.curr_template_id: - log.debug( "\t template text :", data ); - self.template_data += data - - elif self.curr_helper_id: - log.debug( "\t helper js fn :", data ); - self.helper_data += data - - # ------------------------------------------------------------------------------ def break_multi_template( multi_template_filename ): """parse the multi template, writing each template into a new handlebars tmpl and returning their names""" template_filenames = [] - parser = HTMLMultiTemplateParser() # parse the multi template print "\nBreaking multi-template file %s into individual templates and helpers:" % ( multi_template_filename ) with open( multi_template_filename, 'r' ) as multi_template_file: - # wish I could use a gen here - parser.feed( multi_template_file.read() ) + multi_template_file_text = multi_template_file.read() - # after breaking, write each indiv. template and save the names - for template_id, template_text in parser.templates.items(): + # write a template file for each template (name based on id in tag) + tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG ) + for attrs, template_text in filter_on_tag_type( tag_generator, TEMPLATE_TYPE ): + if( 'id' not in attrs ): + log.warning( 'Template has no "id". attrs: %s' %( str( attrs ) ) ) + continue + + template_id = attrs[ 'id' ] + template_text = template_text.strip() handlebar_template_filename = template_id + '.handlebars' with open( handlebar_template_filename, 'w' ) as handlebar_template_file: handlebar_template_file.write( template_text ) + log.debug( "%s\n%s\n", template_id, template_text ) template_filenames.append( handlebar_template_filename ) - # write all helpers to a 'helper-' prefixed js file in the compilation dir - if parser.helpers: - helper_filename = 'helpers-' + path.splitext( multi_template_filename )[0] + '.js' - helper_filename = path.join( COMPILED_DIR, helper_filename ) + ## write all helpers to a single 'helper-' prefixed js file in the compilation dir + helper_fns = [] + # same tag, different type + tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG ) + for attrs, helper_text in filter_on_tag_type( tag_generator, HELPER_TYPE ): + helper_text = helper_text.strip() + print '(helper):', ( attrs[ 'id' ] if 'id' in attrs else '(No id)' ) + + helper_fns.append( helper_text ) + + if helper_fns: + # prefix original filename (in compiled dir) and write all helper funcs to that file + helper_filename = 'helpers-' + os.path.splitext( multi_template_filename )[0] + '.js' + helper_filename = os.path.join( COMPILED_DIR, helper_filename ) with open( helper_filename, 'w' ) as helper_file: - for helper_fn_name, helper_fn in parser.helpers.items(): - print '(helper)', helper_fn_name - helper_file.write( helper_fn + '\n' ) + helper_file.write( '\n'.join( helper_fns ) ) + print '(helper functions written to %s)' % helper_filename print '\n'.join( template_filenames ) return template_filenames @@ -204,8 +150,8 @@ Use the basename of the template file for the outputed js. """ - template_basename = path.splitext( path.split( template_filename )[1] )[0] - compiled_filename = path.join( COMPILED_DIR, template_basename + COMPILED_EXT ) + template_basename = os.path.splitext( os.path.split( template_filename )[1] )[0] + compiled_filename = os.path.join( COMPILED_DIR, template_basename + COMPILED_EXT ) command_string = COMPILE_CMD_STR % ( template_filename, compiled_filename ) if minimize: @@ -233,6 +179,7 @@ # if desired, break up any passed-in or found multi template files # adding the names of the new single templates to those needing compilation + multi_template_template_filenames = [] if options.multi_ext: multi_templates = [] if len( args ) >= 1: @@ -241,10 +188,10 @@ multi_templates = glob( '*' + options.multi_ext ) for multi_template_filename in multi_templates: - handlebars_templates.extend( break_multi_template( multi_template_filename ) ) + multi_template_template_filenames.extend( break_multi_template( multi_template_filename ) ) # unique filenames only (Q&D) - handlebars_templates = list( set( handlebars_templates ) ) + handlebars_templates = list( set( handlebars_templates + multi_template_template_filenames ) ) # compile the templates print "\nCompiling templates:" @@ -260,6 +207,12 @@ print ',\n'.join( filenames_w_possible_errors ) print "\nCall this script with the '-h' for more help" + # delete multi template intermediate files + print "\nCleaning up intermediate multi-template template files:" + for filename in multi_template_template_filenames: + print 'removing', filename + os.remove( filename ) + # ------------------------------------------------------------------------------ if __name__ == '__main__': diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/compiled/helpers-common-templates.js --- a/static/scripts/templates/compiled/helpers-common-templates.js +++ b/static/scripts/templates/compiled/helpers-common-templates.js @@ -3,6 +3,11 @@ Handlebars.registerPartial( 'clearFloatDiv', function( options ){ return '<div class="clear"></div>'; }); +/** Renders a warning in a (mostly css) highlighted, iconned warning box + */ +Handlebars.registerHelper( 'warningmessagesmall', function( options ){ + return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>' +}); /** Renders a glx style icon-button (see IconButton in mvc/ui.js) * can be used in either of the following ways: * within a template: {{> iconButton buttonData}} @@ -29,9 +34,4 @@ buffer += '>' + ( ( buttonData.enabled )?( '</a>' ):( '</span>' ) ); return buffer; -}); -/** Renders a warning in a (mostly css) highlighted, iconned warning box - */ -Handlebars.registerHelper( 'warningmessagesmall', function( options ){ - return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>' -}); +}); \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/compiled/template-history-downloadLinks.js --- /dev/null +++ b/static/scripts/templates/compiled/template-history-downloadLinks.js @@ -0,0 +1,55 @@ +(function() { + var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; +templates['template-history-downloadLinks'] = template(function (Handlebars,depth0,helpers,partials,data) { + helpers = helpers || Handlebars.helpers; + var stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; + +function program1(depth0,data) { + + var buffer = "", stack1, foundHelper; + buffer += "\n<div popupmenu=\"dataset-"; + foundHelper = helpers.id; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "-popup\">\n <a class=\"action-button\" href=\""; + foundHelper = helpers.download_url; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\">Download Dataset</a>\n <a>Additional Files</a>\n "; + stack1 = depth0.meta_files; + stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n</div>\n<div style=\"float:left;\" class=\"menubutton split popup\" id=\"dataset-"; + foundHelper = helpers.id; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "-popup\">\n <a href=\""; + foundHelper = helpers.download_url; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n</div>\n"; + return buffer;} +function program2(depth0,data) { + + var buffer = "", stack1, foundHelper; + buffer += "\n <a class=\"action-button\" href=\""; + foundHelper = helpers.meta_download_url; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.meta_download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "\">Download "; + foundHelper = helpers.meta_file_type; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.meta_file_type; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "</a>\n "; + return buffer;} + +function program4(depth0,data) { + + + return "\n <a href=\"\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n";} + + stack1 = depth0.meta_files; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(4, program4, data),fn:self.program(1, program1, data)}); + if(stack1 || stack1 === 0) { return stack1; } + else { return ''; }}); +})(); \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/history-templates.html --- a/static/scripts/templates/history-templates.html +++ b/static/scripts/templates/history-templates.html @@ -70,3 +70,21 @@ </div></script> +<script type="text/template" class="template-history" id="template-history-downloadLinks"> +{{#if meta_files}} +<div popupmenu="dataset-{{id}}-popup"> + <a class="action-button" href="{{download_url}}">Download Dataset</a> + <a>Additional Files</a> + {{#each meta_files}} + <a class="action-button" href="{{meta_download_url}}">Download {{meta_file_type}}</a> + {{/each}} +</div> +<div style="float:left;" class="menubutton split popup" id="dataset-{{id}}-popup"> + <a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a> +</div> +{{else}} + <a href="" title="Download" class="icon-button disk tooltip"></a> +{{/if}} +</script> + + diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-annotationArea.handlebars --- a/static/scripts/templates/template-history-annotationArea.handlebars +++ /dev/null @@ -1,7 +0,0 @@ -{{! TODO: move to mvc/annotations.js templates, editable-text }} -<div id="{{ id }}-annotation-area" class="annotation-area" style="display: none;"> - <strong>Annotation:</strong> - <div id="{{ id }}-anotation-elt" class="annotation-elt tooltip editable-text" - style="margin: 1px 0px 1px 0px" title="Edit dataset annotation"> - </div> -</div> \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-failedMetaData.handlebars --- a/static/scripts/templates/template-history-failedMetaData.handlebars +++ /dev/null @@ -1,4 +0,0 @@ -{{#warningmessagesmall}} -An error occurred setting the metadata for this dataset. -You may be able to <a href="{{ edit_url }}" target="galaxy_main">set it manually or retry auto-detection</a>. -{{/warningmessagesmall}} \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-hdaSummary.handlebars --- a/static/scripts/templates/template-history-hdaSummary.handlebars +++ /dev/null @@ -1,13 +0,0 @@ -<div class="hda-summary"> - {{ misc_blurb }}<br /> - format: <span class="{{ data_type }}">{{ data_type }}</span>, - database: - {{#if dbkey_unknown_and_editable }} - <a href="{{ edit_url }}" target="galaxy_main">{{ metadata_dbkey }}</a> - {{else}} - <span class="{{ metadata_dbkey }}">{{ metadata_dbkey }}</span> - {{/if}} -</div> -{{#if misc_info}} -<div class="hda-info">{{ misc_info }}</div> -{{/if}} \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-tagArea.handlebars --- a/static/scripts/templates/template-history-tagArea.handlebars +++ /dev/null @@ -1,6 +0,0 @@ -{{! TODO: move to mvc/tag.js templates }} -<div class="tag-area" style="display: none;"> - <strong>Tags:</strong> - <div class="tag-elt"> - </div> -</div> \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-titleLink.handlebars --- a/static/scripts/templates/template-history-titleLink.handlebars +++ /dev/null @@ -1,1 +0,0 @@ -<a href="javascript:void(0);"><span class="historyItemTitle">{{ hid }}: {{ name }}</span></a> \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-history-warning-messages.handlebars --- a/static/scripts/templates/template-history-warning-messages.handlebars +++ /dev/null @@ -1,23 +0,0 @@ -{{#if deleted}}{{#warningmessagesmall}} - This dataset has been deleted. - {{#if undelete_url}} - Click <a href="{{ undelete_url }}" class="historyItemUndelete" id="historyItemUndeleter-{{ id }}" - target="galaxy_history">here</a> to undelete it - {{#if purge_url}} - or <a href="{{ purge_url }}" class="historyItemPurge" id="historyItemPurger-{{ id }}" - target="galaxy_history">here</a> to immediately remove it from disk - {{/if}} - {{/if}} -{{/warningmessagesmall}}{{/if}} - -{{#if purged}}{{#warningmessagesmall}} - This dataset has been deleted and removed from disk. -{{/warningmessagesmall}}{{/if}} - -{{#unless visible}}{{#warningmessagesmall}} - This dataset has been hidden. - {{#if unhide_url}} - Click <a href="{{ unhide_url }}" class="historyItemUnhide" id="historyItemUnhider-{{ id }}" - target="galaxy_history">here</a> to unhide it - {{/if}} -{{/warningmessagesmall}}{{/unless}} \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-iconButton.handlebars --- a/static/scripts/templates/template-iconButton.handlebars +++ /dev/null @@ -1,2 +0,0 @@ -{{! alternate template-based icon-button }} -{{> iconButton this}} \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b static/scripts/templates/template-warningmessagesmall.handlebars --- a/static/scripts/templates/template-warningmessagesmall.handlebars +++ /dev/null @@ -1,2 +0,0 @@ -{{! renders a warning in a (mostly css) highlighted, iconned warning box }} - <div class="warningmessagesmall"><strong>{{{ warning }}}</strong></div> \ No newline at end of file diff -r 9c29a51ec0b1e21c2578250ceb00c37325cbe1ff -r f0eea6ef482453ccc3cc466917ae4ed93920666b templates/root/alternate_history.mako --- a/templates/root/alternate_history.mako +++ b/templates/root/alternate_history.mako @@ -7,6 +7,40 @@ ## ?? add: if string != _(string) </%def> +##<%def name="render_download_links( data, dataset_id )"> +## ## +## %if data.purged: return +## <% +## from galaxy.datatypes.metadata import FileParameter +## download_url = h.url_for( controller='/dataset', action='display', dataset_id=dataset_id, to_ext=data.ext ) +## meta_files = [] +## for k in data.metadata.spec.keys(): +## if isinstance( data.metadata.spec[ k ].param, FileParameter ): +## file_type = k +## download_url = h.url_for( controller='/dataset', action='get_metadata_file', +## hda_id=dataset_id, metadata_name=file_type ) +## meta_files.append( ( file_type, download_url ) ) +## %> +## +## %if meta_files: +## <div popupmenu="dataset-${dataset_id}-popup"> +## <a class="action-button" href="${download_url}">Download Dataset</a> +## +## <a>Additional Files</a> +## %for meta_file_type, meta_download_url in zip( meta_download_types, meta_download_urls ): +## <a class="action-button" href="${meta_download_url}">Download ${meta_file_type}</a> +## %endfor +## +## <div style="float:left;" class="menubutton split popup" id="dataset-${dataset_id}-popup"> +## <a href="${download_url}" title='${_("Download")}' class="icon-button disk tooltip"></a> +## </div> +## </div> +## +## %else +## <a href="${download_url}" title='${_("Download")}' class="icon-button disk tooltip"></a> +## %endif +##</%def> + <%def name="get_page_localized_strings()"> ## a list of localized strings used in the backbone views, etc. (to be loaded and cached) ##! change on per page basis @@ -54,33 +88,34 @@ <%def name="get_urls_for_hda( hda, encoded_data_id, for_editing )"><% from galaxy.datatypes.metadata import FileParameter + #print '\n', hda.name data_dict = {} def add_to_data( **kwargs ): data_dict.update( kwargs ) - # download links (for both main hda and associated meta files) - if hda.has_data(): - add_to_data( download_url=h.url_for( controller='/dataset', action='display', - dataset_id=encoded_data_id, to_ext=hda.ext ) ) - - download_meta_urls = {} - for file_type in hda.metadata.spec.keys(): - if not isinstance( hda.metadata.spec[ file_type ].param, FileParameter ): - continue - - download_meta_urls[ file_type ] = h.url_for( controller='/dataset', action='get_metadata_file', - hda_id=encoded_data_id, metadata_name=file_type ) - if download_meta_urls: - #TODO:?? needed? isn't this the same as download_url? - add_to_data( download_dataset_url=h.url_for( controller='dataset', action='display', - dataset_id=encoded_data_id, to_ext=hda.ext ) ) - add_to_data( download_meta_urls=download_meta_urls ) - #TODO??: better way to do urls (move into js galaxy_paths (decorate) - _not_ dataset specific) deleted = hda.deleted purged = hda.purged + # download links (for both main hda and associated meta files) + if not hda.purged: + add_to_data( download_url=h.url_for( controller='/dataset', action='display', + dataset_id=encoded_data_id, to_ext=hda.ext ) ) + + meta_files = [] + for k in hda.metadata.spec.keys(): + if isinstance( hda.metadata.spec[ k ].param, FileParameter ): + file_type = k + download_url = h.url_for( controller='/dataset', action='get_metadata_file', + hda_id=encoded_data_id, metadata_name=file_type ) + meta_files.append( dict( meta_file_type=file_type, meta_download_url=download_url ) ) + + if meta_files: + print hda.name, meta_files + add_to_data( meta_files=meta_files ) + + #purged = purged or hda.dataset.purged //?? # all of these urls are 'datasets/data_id/<action> @@ -305,7 +340,8 @@ "template-history-hdaSummary", "template-history-failedMetadata", "template-history-tagArea", - "template-history-annotationArea" + "template-history-annotationArea", + "template-history-downloadLinks" )} ## if using in-dom templates they need to go here (before the Backbone classes are defined) @@ -339,6 +375,7 @@ createMockHistoryData(); return; + //TODO: handle empty history } else if ( window.USE_CURR_DATA ){ if( console && console.debug ){ console.debug( '\t using current history data' ); } glx_history = new History( pageData.history ).loadDatasetsAsHistoryItems( pageData.hdas ); @@ -409,3 +446,163 @@ </%def><body class="historyPage"></body> + +<script type="text/javascript"> +function createMockHistoryData(){ + mockHistory = {}; + mockHistory.data = { + + template : { + id : 'a799d38679e985db', + name : 'template', + data_type : 'fastq', + file_size : 226297533, + genome_build : '?', + metadata_data_lines : 0, + metadata_dbkey : '?', + metadata_sequences : 0, + misc_blurb : '215.8 MB', + misc_info : 'uploaded fastq file (misc_info)', + model_class : 'HistoryDatasetAssociation', + download_url : '', + state : 'ok', + visible : true, + deleted : false, + purged : false, + + hid : 0, + //TODO: move to history + for_editing : true, + //for_editing : false, + + //?? not needed + //can_edit : true, + //can_edit : false, + + accessible : true, + + //TODO: move into model functions (build there (and cache?)) + //!! be careful with adding these accrd. to permissions + //!! IOW, don't send them via template/API if the user doesn't have perms to use + //!! (even if they don't show up) + undelete_url : '', + purge_url : '', + unhide_url : '', + + display_url : 'example.com/display', + edit_url : 'example.com/edit', + delete_url : 'example.com/delete', + + show_params_url : 'example.com/show_params', + rerun_url : 'example.com/rerun', + + retag_url : 'example.com/retag', + annotate_url : 'example.com/annotate', + + peek : [ + '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>', + '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>', + '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>', + '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>', + '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>', + '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', + '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>', + '</table>' + ].join( '' ) + } + + }; + _.extend( mockHistory.data, { + + notAccessible : + _.extend( _.clone( mockHistory.data.template ), + { accessible : false }), + + //deleted, purged, visible + deleted : + _.extend( _.clone( mockHistory.data.template ), + { deleted : true, + delete_url : '', + purge_url : 'example.com/purge', + undelete_url : 'example.com/undelete' }), + purgedNotDeleted : + _.extend( _.clone( mockHistory.data.template ), + { purged : true, + delete_url : '' }), + notvisible : + _.extend( _.clone( mockHistory.data.template ), + { visible : false, + unhide_url : 'example.com/unhide' }), + + hasDisplayApps : + _.extend( _.clone( mockHistory.data.template ), + { display_apps : { + 'display in IGB' : { + Web: "/display_application/63cd3858d057a6d1/igb_bam/Web", + Local: "/display_application/63cd3858d057a6d1/igb_bam/Local" + } + } + } + ), + canTrackster : + _.extend( _.clone( mockHistory.data.template ), + { trackster_urls : { + 'data-url' : "example.com/trackster-data", + 'action-url' : "example.com/trackster-action", + 'new-url' : "example.com/trackster-new" + } + } + ), + zeroSize : + _.extend( _.clone( mockHistory.data.template ), + { file_size : 0 }), + + hasMetafiles : + _.extend( _.clone( mockHistory.data.template ), { + download_meta_urls : { + 'bam_index' : "example.com/bam-index" + } + }), + + //states + upload : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.UPLOAD }), + queued : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.QUEUED }), + running : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.RUNNING }), + empty : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.EMPTY }), + error : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.ERROR, + report_error_url: 'example.com/report_err' }), + discarded : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.DISCARDED }), + setting_metadata : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.SETTING_METADATA }), + failed_metadata : + _.extend( _.clone( mockHistory.data.template ), + { state : HistoryItem.STATES.FAILED_METADATA }) +/* +*/ + }); + + //mockHistory.views.deleted.logger = console; + mockHistory.items = {}; + mockHistory.views = {}; + for( key in mockHistory.data ){ + mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] ); + mockHistory.items[ key ].set( 'name', key ); + mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] }); + //console.debug( 'view: ', mockHistory.views[ key ] ); + $( 'body' ).append( mockHistory.views[ key ].render() ); + } +} +</script> \ No newline at end of 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.