galaxy-dev
Threads by month
- ----- 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
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
February 2010
- 32 participants
- 180 discussions
15 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/0f4e5a057322
changeset: 3376:0f4e5a057322
user: rc
date: Fri Feb 12 11:19:37 2010 -0500
description:
Migration script fix. This restores the 'request' table if it got deleted in the previous script (only for sqlite).
diffstat:
lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py | 31 +++++++++-
1 files changed, 30 insertions(+), 1 deletions(-)
diffs (53 lines):
diff -r 049a86b8691d -r 0f4e5a057322 lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py
--- a/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py Fri Feb 12 11:01:30 2010 -0500
+++ b/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py Fri Feb 12 11:19:37 2010 -0500
@@ -1,12 +1,16 @@
"""
Migration script to add an inheritable column to the following tables:
library_info_association, library_folder_info_association.
+Also, in case of sqlite check if the previous migration script deleted the
+request table and if so, restore the table.
"""
from sqlalchemy import *
from migrate import *
from migrate.changeset import *
-
+from galaxy.model.custom_types import *
+import datetime
+now = datetime.datetime.utcnow
import logging
log = logging.getLogger( __name__ )
@@ -14,6 +18,31 @@
def upgrade():
print __doc__
+
+ #
+ # In case of sqlite, check if the previous migration script deleted the
+ # request table and if so, restore the table.
+ #
+ if migrate_engine.name == 'sqlite':
+ if not migrate_engine.has_table('request'):
+ # load the tables referenced in foreign keys
+ metadata.reflect(only=['form_values', 'request_type', 'galaxy_user'])
+ # create a temporary table
+ Request_table = Table( 'request', metadata,
+ Column( "id", Integer, primary_key=True),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "name", TrimmedString( 255 ), nullable=False ),
+ Column( "desc", TEXT ),
+ Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
+ Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+ try:
+ Request_table.create()
+ except Exception, e:
+ log.debug( "Creating request table failed: %s" % str( e ) )
+
metadata.reflect()
LibraryInfoAssociation_table = Table( "library_info_association", metadata, autoload=True )
1
0
15 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/049a86b8691d
changeset: 3375:049a86b8691d
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Feb 12 11:01:30 2010 -0500
description:
Introduce a new style of external display applications. Display applications can now be entirely defined using xml files, similar to how tools are integrated.
Applications are assigned to specific datatypes (i.e. on an extension basis) via the datatypes_conf.xml file.
View the sample display applications at /display_applications/[ucsc/]*.xml for examples of usage.
Provided sample display applications:
View BAM files (with bai indexes) at UCSC using BigDataUrl support.
ucsc interval as bed viewer - not enabled by default (the old style display app is still used by default; both can be used simultaneously - but this would likely be confusing)
GeneTrack viewer - any interval datatype can now be viewed at GeneTrack, if the application is enabled for a particular datatype; also a valid display application for genetrack datatype.
Display applications can make full use of datatype converters, even allowing explicitly defined multi-step conversions, e.g. interval --> bed --> genetrack; the datatype conversion framework will need to be enhanced to natively support multi-step conversions before this can be done implicitly.
A new datatype, bedstrict, has been defined, the only way to have an item with this datatype is to be created by a tool; metadata cannot be edited; and sniffing this datatype would require aggressively parsing the entirety of the file. A bedstrict file must conform exactly to the BED specification (whereas Galaxy allows BED files to have non-standard columns). These files are suitable e.g. for display at the UCSC genome browser and is used by the new ucsc interval display application.
Add a bed to bedstrict converter, this is used by the ucsc interval display application.
Add a bed to genetrack converter, this is used by the new GeneTrack display application. TODO: If the GeneTrack indexer can be enhanced to accept column assignments, this should be an interval to genetrack converter.
Several performance enhancements available for the ucsc tools, such as bigurl support, potential speed improvement when loading a user's history than the old style for certain displays, e.g. ucsc interval display no longer requires the viewport (position) to be calculated for each relevant history item in a users history; this calculation now occurs on a separate page after the user clicks a view link. Non-strict BED files no longer have their content calculated on the fly and then streamed, etc.
Refer to additional comments in code.
diffstat:
datatypes_conf.xml.sample | 15 +-
display_applications/genetrack.xml | 18 +
display_applications/ucsc/bam.xml | 8 +
display_applications/ucsc/interval_as_bed.xml | 37 +
lib/galaxy/datatypes/converters/bed_to_genetrack_converter.py | 44 ++
lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml | 17 +
lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py | 114 +++++
lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.xml | 15 +
lib/galaxy/datatypes/data.py | 9 +-
lib/galaxy/datatypes/display_applications/__init__.py | 1 +
lib/galaxy/datatypes/display_applications/application.py | 116 +++++
lib/galaxy/datatypes/display_applications/helpers.py | 31 +
lib/galaxy/datatypes/display_applications/parameters.py | 195 ++++++++++
lib/galaxy/datatypes/interval.py | 30 +
lib/galaxy/datatypes/registry.py | 18 +-
lib/galaxy/web/buildapp.py | 1 +
lib/galaxy/web/controllers/dataset.py | 71 +++-
templates/dataset/display_application/display.mako | 17 +
templates/dataset/display_application/launch_display.mako | 15 +
templates/root/history_common.mako | 6 +
20 files changed, 773 insertions(+), 5 deletions(-)
diffs (981 lines):
diff -r 81d84a03f2ec -r 049a86b8691d datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample Thu Feb 11 16:18:45 2010 -0500
+++ b/datatypes_conf.xml.sample Fri Feb 12 11:01:30 2010 -0500
@@ -5,11 +5,19 @@
<datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true"/>
<datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true">
<converter file="bam_to_bai.xml" target_datatype="bai"/>
+ <display file="ucsc/bam.xml" />
</datatype>
<datatype extension="bed" type="galaxy.datatypes.interval:Bed" display_in_upload="true">
<converter file="bed_to_gff_converter.xml" target_datatype="gff"/>
<converter file="interval_to_coverage.xml" target_datatype="coverage"/>
<converter file="bed_to_interval_index_converter.xml" target_datatype="interval_index"/>
+ <converter file="bed_to_genetrack_converter.xml" target_datatype="genetrack"/>
+ <!-- <display file="ucsc/interval_as_bed.xml" /> -->
+ <display file="genetrack.xml" />
+ </datatype>
+ <datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict">
+ <display file="ucsc/interval_as_bed.xml" />
+ <display file="genetrack.xml" />
</datatype>
<datatype extension="binseq.zip" type="galaxy.datatypes.binary:Binseq" mimetype="application/zip" display_in_upload="true"/>
<datatype extension="len" type="galaxy.datatypes.chrominfo:ChromInfo" display_in_upload="true">
@@ -26,7 +34,9 @@
</datatype>
<datatype extension="fastq" type="galaxy.datatypes.sequence:Fastq" display_in_upload="true"/>
<datatype extension="fastqsanger" type="galaxy.datatypes.sequence:FastqSanger" display_in_upload="true"/>
- <datatype extension="genetrack" type="galaxy.datatypes.tracks:GeneTrack"/>
+ <datatype extension="genetrack" type="galaxy.datatypes.tracks:GeneTrack">
+ <!-- <display file="genetrack.xml" /> -->
+ </datatype>
<datatype extension="gff" type="galaxy.datatypes.interval:Gff" display_in_upload="true">
<converter file="gff_to_bed_converter.xml" target_datatype="bed"/>
</datatype>
@@ -36,7 +46,10 @@
<datatype extension="html" type="galaxy.datatypes.images:Html" mimetype="text/html"/>
<datatype extension="interval" type="galaxy.datatypes.interval:Interval" display_in_upload="true">
<converter file="interval_to_bed_converter.xml" target_datatype="bed"/>
+ <converter file="interval_to_bedstrict_converter.xml" target_datatype="bedstrict"/>
<indexer file="interval_awk.xml" />
+ <!-- <display file="ucsc/interval_as_bed.xml" /> -->
+ <display file="genetrack.xml" />
</datatype>
<datatype extension="jpg" type="galaxy.datatypes.images:Image" mimetype="image/jpeg"/>
<datatype extension="laj" type="galaxy.datatypes.images:Laj"/>
diff -r 81d84a03f2ec -r 049a86b8691d display_applications/genetrack.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/display_applications/genetrack.xml Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,18 @@
+<display id="genetrack_interval" version="1.0.0" name="view in">
+ <link id="genetrack" name="GeneTrack">
+ <url target_frame="galaxy_main">http://genetrack.g2.bx.psu.edu/galaxy?filename=${encoded_filename.qp}&h…</url>
+ <param type="data" name="bed_file" viewable="False" format="bed,genetrack"/> <!-- for now, we'll explicitly take care of the multi-step conversion; walk genetrack datatype down as a conversion of genetrack to genetrack doesn't exist and would likely be pointless -->
+ <param type="data" dataset="bed_file" name="genetrack_file" format="genetrack" viewable="False" />
+ <param type="template" name="galaxy_url" strip="True" >
+ ${BASE_URL}/tool_runner?tool_id=predict2genetrack
+ </param>
+ <param type="template" name="hash_key" strip="True" >
+ #from galaxy.util.hash_util import hmac_new
+ ${hmac_new( $APP.config.tool_secret, $genetrack_file.file_name )}
+ </param>
+ <param type="template" name="encoded_filename" strip="True" >
+ #import binascii
+ ${binascii.hexlify( $genetrack_file.file_name )}
+ </param>
+ </link>
+</display>
diff -r 81d84a03f2ec -r 049a86b8691d display_applications/ucsc/bam.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/display_applications/ucsc/bam.xml Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,8 @@
+<display id="ucsc_bam" version="1.0.0" name="display at UCSC">
+ <link id="main" name="main">
+ <url>http://genome.ucsc.edu/cgi-bin/hgTracks?db=${qp($bam_file.dbkey)}&hgt.c…</url>
+ <param type="data" name="bam_file" url="galaxy.bam" strip_https="True" />
+ <param type="data" name="bai_file" url="galaxy.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai -->
+ <param type="template" name="track" viewable="True" strip_https="True">track type=bam name="${bam_file.name}" bigDataUrl=${bam_file.url} db=${bam_file.dbkey}</param>
+ </link>
+</display>
diff -r 81d84a03f2ec -r 049a86b8691d display_applications/ucsc/interval_as_bed.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/display_applications/ucsc/interval_as_bed.xml Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,37 @@
+<display id="ucsc_interval_as_bed" version="1.0.0" name="display at UCSC">
+ <link id="main" name="main">
+ <url>http://genome.ucsc.edu/cgi-bin/hgTracks?db=${qp($bed_file.dbkey)}&posit…</url>
+ <param type="data" name="bed_file" url="galaxy.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file -->
+ <param type="template" name="position" strip="True" >
+#set line_count = 0
+#set chrom = None
+#set start = float( 'inf' )
+#set end = 0
+#for $line in open( $bed_file.file_name ):
+ #if $line_count > 10: ##10 max lines to check for view port
+ #break
+ #end if
+ #if not $line.startswith( "#" ):
+ #set $fields = $line.split( "\t" )
+ #try:
+ #if len( $fields ) >= max( $bed_file.metadata.startCol, $bed_file.metadata.endCol, $bed_file.metadata.chromCol ):
+ #if $chrom is None or $fields[ $bed_file.metadata.chromCol - 1 ] == $chrom:
+ #set chrom = $fields[ $bed_file.metadata.chromCol - 1 ]
+ #set start = min( $start, int( $fields[ $bed_file.metadata.startCol - 1 ] ) )
+ #set end = max( $end, int( $fields[ $bed_file.metadata.endCol - 1 ] ) )
+ #end if
+ #end if
+ #except:
+ #pass
+ #end try
+ #end if
+ #set line_count += 1
+#end for
+#if $chrom is not None:
+${chrom}:${start}-${end + 1}
+#else:
+:-
+#end if
+ </param>
+ </link>
+</display>
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/converters/bed_to_genetrack_converter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/bed_to_genetrack_converter.py Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+#FIXME: THIS IS 1:1 COPY OF THE SAME FUNCTIONED TOOL - ALLOW REGULAR TOOLS TO MASCARADE AS CONVERTERS
+
+"""
+Wraps genetrack.scripts.tabs2genetrack so the tool can be executed from Galaxy.
+
+usage: %prog input output shift
+"""
+
+import sys, shutil, os
+from galaxy import eggs
+import pkg_resources
+pkg_resources.require( "GeneTrack" )
+
+from genetrack.scripts import tabs2genetrack
+from genetrack import logger
+
+if __name__ == "__main__":
+ import os
+ os.environ[ 'LC_ALL' ] = 'C'
+ #os.system( 'export' )
+
+ parser = tabs2genetrack.option_parser()
+
+ options, args = parser.parse_args()
+
+ # uppercase the format
+ options.format = options.format.upper()
+
+ if options.format not in ('BED', 'GFF'):
+ sys.stdout = sys.stderr
+ parser.print_help()
+ sys.exit(-1)
+
+ logger.disable(options.verbosity)
+
+ # missing file names
+ if not (options.inpname and options.outname and options.format):
+ parser.print_help()
+ sys.exit(-1)
+ else:
+ tabs2genetrack.transform(inpname=options.inpname, outname=options.outname,\
+ format=options.format, shift=options.shift, index=options.index, options=options)
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/bed_to_genetrack_converter.xml Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,17 @@
+<tool id="CONVERTER_bed_to_genetrack_0" name="Convert BED to GeneTrack Index" version="1.0.0">
+<!-- FIXME: THIS IS ALMOST 1:1 COPY OF THE SAME FUNCTIONED TOOL - ALLOW REGULAR TOOLS TO MASCARADE AS CONVERTERS
+Using a shift of 0, but tool allows specifying...
+-->
+<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <command interpreter="python">bed_to_genetrack_converter.py -i $input1 -o $output1 -s 0 -v 0 -f BED -x</command>
+ <inputs>
+ <page>
+ <param format="bed" name="input1" type="data" label="Choose BED file"/>
+ </page>
+ </inputs>
+ <outputs>
+ <data format="genetrack" name="output1"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.py Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#Dan Blankenberg
+
+import sys
+from galaxy import eggs
+import pkg_resources; pkg_resources.require( "bx-python" )
+import bx.intervals.io
+
+assert sys.version_info[:2] >= ( 2, 4 )
+
+def stop_err( msg ):
+ sys.stderr.write( msg )
+ sys.exit()
+
+def __main__():
+ output_name = sys.argv[1]
+ input_name = sys.argv[2]
+ try:
+ chromCol = int( sys.argv[3] ) - 1
+ except:
+ stop_err( "'%s' is an invalid chrom column, correct the column settings before attempting to convert the data format." % str( sys.argv[3] ) )
+ try:
+ startCol = int( sys.argv[4] ) - 1
+ except:
+ stop_err( "'%s' is an invalid start column, correct the column settings before attempting to convert the data format." % str( sys.argv[4] ) )
+ try:
+ endCol = int( sys.argv[5] ) - 1
+ except:
+ stop_err( "'%s' is an invalid end column, correct the column settings before attempting to convert the data format." % str( sys.argv[5] ) )
+ try:
+ strandCol = int( sys.argv[6] ) - 1
+ except:
+ strandCol = -1
+ try:
+ nameCol = int( sys.argv[7] ) - 1
+ except:
+ nameCol = -1
+ try:
+ extension = sys.argv[8]
+ except:
+ extension = 'interval' #default extension
+
+ skipped_lines = 0
+ first_skipped_line = None
+ out = open( output_name,'w' )
+ count = 0
+ #does file already conform to bed strict?
+ #if so, we want to keep extended columns, otherwise we'll create a generic 6 column bed file
+ strict_bed = True
+ if extension == 'bed' and ( chromCol, startCol, endCol, nameCol, strandCol ) == ( 0, 1, 2, 3, 5 ):
+ for count, line in enumerate( open( input_name ) ):
+ line = line.strip()
+ if line == "" or line.startswith("#"):
+ skipped_lines += 1
+ if first_skipped_line is None:
+ first_skipped_line = count + 1
+ continue
+ fields = line.split('\t')
+ try:
+ if len(fields) > 12:
+ strict_bed = False
+ break
+ if len(fields) > 6:
+ int(fields[6])
+ if len(fields) > 7:
+ int(fields[7])
+ if len(fields) > 8:
+ if int(fields[8]) != 0:
+ strict_bed = False
+ break
+ if len(fields) > 9:
+ int(fields[9])
+ if len(fields) > 10:
+ fields2 = fields[10].rstrip(",").split(",") #remove trailing comma and split on comma
+ for field in fields2:
+ int(field)
+ if len(fields) > 11:
+ fields2 = fields[11].rstrip(",").split(",") #remove trailing comma and split on comma
+ for field in fields2:
+ int(field)
+ except:
+ strict_bed = False
+ break
+ out.write( "%s\n" % line )
+ else:
+ strict_bed = False
+ out.close()
+
+ if not strict_bed:
+ skipped_lines = 0
+ first_skipped_line = None
+ out = open( output_name,'w' )
+ count = 0
+ for count, region in enumerate( bx.intervals.io.NiceReaderWrapper( open( input_name, 'r' ), chrom_col=chromCol, start_col=startCol, end_col=endCol, strand_col=strandCol, fix_strand=True, return_header=False, return_comments=False ) ):
+ try:
+ if nameCol >= 0:
+ name = region.fields[nameCol]
+ else:
+ raise IndexError
+ except:
+ name = "region_%i" % count
+ try:
+
+ out.write( "%s\t%i\t%i\t%s\t%i\t%s\n" % ( region.chrom, region.start, region.end, name, 0, region.strand ) )
+ except:
+ skipped_lines += 1
+ if first_skipped_line is None:
+ first_skipped_line = count + 1
+ out.close()
+ print "%i regions converted to BED." % ( count + 1 - skipped_lines )
+ if skipped_lines > 0:
+ print "Skipped %d blank or invalid lines starting with line # %d." % ( skipped_lines, first_skipped_line )
+
+if __name__ == "__main__": __main__()
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/interval_to_bedstrict_converter.xml Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,15 @@
+<tool id="CONVERTER_interval_to_bedstrict_0" name="Convert Genomic Intervals To Strict BED">
+ <!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <!-- Used on the metadata edit page. -->
+ <command interpreter="python">interval_to_bedstrict_converter.py $output1 $input1 ${input1.metadata.chromCol} ${input1.metadata.startCol} ${input1.metadata.endCol} ${input1.metadata.strandCol} ${input1.metadata.nameCol} ${input1.extension}</command>
+ <inputs>
+ <page>
+ <param format="interval" name="input1" type="data" label="Choose intervals"/>
+ </page>
+ </inputs>
+ <outputs>
+ <data format="bedstrict" name="output1"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py Thu Feb 11 16:18:45 2010 -0500
+++ b/lib/galaxy/datatypes/data.py Fri Feb 12 11:01:30 2010 -0500
@@ -63,6 +63,7 @@
object.__init__(self, **kwd)
self.supported_display_apps = self.supported_display_apps.copy()
self.composite_files = self.composite_files.copy()
+ self.display_applications = odict()
def write_from_stream(self, dataset, stream):
"""Writes data from a stream"""
fd = open(dataset.file_name, 'wb')
@@ -198,6 +199,12 @@
del self.supported_display_apps[app_id]
except:
log.exception('Tried to remove display app %s from datatype %s, but this display app is not declared.' % ( type, self.__class__.__name__ ) )
+ def clear_display_apps( self ):
+ self.supported_display_apps = {}
+ def add_display_application( self, display_application ):
+ """New style display applications"""
+ assert display_application.id not in self.display_applications, 'Attempted to add a display application twice'
+ self.display_applications[ display_application.id ] = display_application
def get_display_types(self):
"""Returns display types available"""
return self.supported_display_apps.keys()
@@ -239,7 +246,7 @@
"""This function adds a job to the queue to convert a dataset to another type. Returns a message about success/failure."""
converter = trans.app.datatypes_registry.get_converter_by_target_type( original_dataset.ext, target_type )
if converter is None:
- raise "A converter does not exist for %s to %s." % ( original_dataset.ext, target_type )
+ raise Exception( "A converter does not exist for %s to %s." % ( original_dataset.ext, target_type ) )
#Generate parameter dictionary
params = {}
#determine input parameter name and add to params
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/display_applications/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/display_applications/__init__.py Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,1 @@
+
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/display_applications/application.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/display_applications/application.py Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,116 @@
+#Contains objects for using external display applications
+from galaxy.util import parse_xml
+from galaxy.util.odict import odict
+from galaxy.util.template import fill_template
+from galaxy.web import url_for
+from parameters import DisplayApplicationParameter, DEFAULT_DATASET_NAME
+from urllib import quote_plus
+from helpers import encode_dataset_user
+
+#Any basic functions that we want to provide as a basic part of parameter dict should be added to this dict
+BASE_PARAMS = { 'qp': quote_plus, 'url_for':url_for } #url_for has route memory...
+
+class DisplayApplicationLink( object ):
+ @classmethod
+ def from_elem( cls, elem, display_application ):
+ rval = DisplayApplicationLink( display_application )
+ rval.id = elem.get( 'id', None )
+ assert rval.id, 'Link elements require a id.'
+ rval.name = elem.get( 'name', rval.id )
+ rval.url = elem.find( 'url' )
+ assert rval.url is not None, 'A url element must be provided for link elements.'
+ for param_elem in elem.findall( 'param' ):
+ param = DisplayApplicationParameter.from_elem( param_elem, rval )
+ assert param, 'Unable to load parameter from element: %s' % param_elem
+ rval.parameters[ param.name ] = param
+ rval.url_param_name_map[ param.url ] = param.name
+ return rval
+ def __init__( self, display_application ):
+ self.display_application = display_application
+ self.parameters = odict() #parameters are populated in order, allowing lower listed ones to have values of higher listed ones
+ self.url_param_name_map = {}
+ self.url = None
+ self.id = None
+ self.name = None
+ def get_display_url( self, data, trans ):
+ dataset_hash, user_hash = encode_dataset_user( trans, data, trans.user )
+ return url_for( controller = 'dataset', action = "display_application", dataset_id = dataset_hash, user_id = user_hash, app_name = self.display_application.id, link_name = self.id, app_action = 'display' )
+ def get_inital_values( self, data, trans ):
+ rval = odict( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) #trans automatically appears as a response, need to add properties of trans that we want here
+ for key, value in BASE_PARAMS.iteritems(): #add helper functions/variables
+ rval[ key ] = value
+ rval[ DEFAULT_DATASET_NAME ] = data #always have the display dataset name available
+ return rval
+ def build_parameter_dict( self, data, trans ):
+ other_values = self.get_inital_values( data, trans )
+ for name, param in self.parameters.iteritems():
+ assert name not in other_values, "The display parameter '%s' has been defined more than once." % name
+ if param.ready( other_values ):
+ other_values[ name ] = param.get_value( other_values, trans )#subsequent params can rely on this value
+ else:
+ other_values[ name ] = None
+ return False, other_values #need to stop here, next params may need this value
+ return True, other_values #we built other_values, lets provide it as well, or else we will likely regenerate it in the next step
+
+class PopulatedDisplayApplicationLink( object ):
+ def __init__( self, display_application_link, data, trans ):
+ self.link = display_application_link
+ self.data = data
+ self.trans = trans
+ self.ready, self.parameters = self.link.build_parameter_dict( self.data, trans )
+ def display_ready( self ):
+ return self.ready
+ def get_param_value( self, name ):
+ value = None
+ if self.ready:
+ value = self.parameters.get( name, None )
+ assert value, 'Unknown parameter requested'
+ return value
+ def preparing_display( self ):
+ if not self.ready:
+ return self.link.parameters[ self.parameters.keys()[ -1 ] ].is_preparing( self.parameters )
+ return False
+ def prepare_display( self ):
+ if not self.ready and not self.preparing_display():
+ other_values = self.parameters
+ for name, param in self.link.parameters.iteritems():
+ if other_values.keys()[ -1 ] == name: #found last parameter to be populated
+ value = param.prepare( other_values, self.trans )
+ if value is None:
+ return #we can go no further until we have a value for this parameter
+ other_values[ name ] = value
+ def display_url( self ):
+ assert self.display_ready(), 'Display is not yet ready, cannot generate display link'
+ return fill_template( self.link.url.text, context = self.parameters )
+ def get_param_name_by_url( self, name ):
+ assert name in self.link.url_param_name_map, "Unknown URL parameter name provided: %s" % name
+ return self.link.url_param_name_map[ name ]
+
+class DisplayApplication( object ):
+ @classmethod
+ def from_file( cls, filename, datatypes_registry ):
+ return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry )
+ @classmethod
+ def from_elem( cls, elem, datatypes_registry ):
+ display_id = elem.get( 'id', None )
+ assert display_id, "ID tag is required for a Display Application"
+ name = elem.get( 'name', display_id )
+ version = elem.get( 'version', None )
+ rval = DisplayApplication( display_id, name, datatypes_registry, version )
+ for link_elem in elem.findall( 'link' ):
+ link = DisplayApplicationLink.from_elem( link_elem, rval )
+ if link:
+ rval.links[ link.id ] = link
+ return rval
+ def __init__( self, display_id, name, datatypes_registry, version = None ):
+ self.id = display_id
+ self.name = name
+ self.datatypes_registry = datatypes_registry
+ if version is None:
+ version = "1.0.0"
+ self.version = version
+ self.links = odict()
+ def get_link( self, link_name, data, trans ):
+ #returns a link object with data knowledge to generate links
+ return PopulatedDisplayApplicationLink( self.links[ link_name ], data, trans )
+
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/display_applications/helpers.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/display_applications/helpers.py Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,31 @@
+import pkg_resources
+pkg_resources.require( "pycrypto" )
+from Crypto.Cipher import Blowfish
+
+def encode_dataset_user( trans, dataset, user ):
+ #encode dataset id as usual
+ #encode user id using the dataset create time as the key
+ dataset_hash = trans.security.encode_id( dataset.id )
+ if user is None:
+ user_id = 'None'
+ else:
+ user_id = str( user.id )
+ # Pad to a multiple of 8 with leading "!"
+ user_id = ( "!" * ( 8 - len( user_id ) % 8 ) ) + user_id
+ cipher = Blowfish.new( str( dataset.create_time ) )
+ return dataset_hash, cipher.encrypt( user_id ).encode( 'hex' )
+
+def decode_dataset_user( trans, dataset_hash, user_hash ):
+ #decode dataset id as usual
+ #decode user id using the dataset create time as the key
+ dataset_id = trans.security.decode_id( dataset_hash )
+ dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id )
+ assert dataset, "Bad Dataset id provided to decode_dataset_user"
+ cipher = Blowfish.new( str( dataset.create_time ) )
+ user_id = cipher.decrypt( user_hash.decode( 'hex' ) ).lstrip( "!" )
+ if user_id =='None':
+ user = None
+ else:
+ user = trans.sa_session.query( trans.app.model.User ).get( int( user_id ) )
+ assert user, "A Bad user id was passed to decode_dataset_user"
+ return dataset, user
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/display_applications/parameters.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/display_applications/parameters.py Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,195 @@
+#Contains parameters that are used in Display Applications
+from helpers import encode_dataset_user
+from galaxy.util import string_as_bool
+from galaxy.util.bunch import Bunch
+from galaxy.util.template import fill_template
+from galaxy.web import url_for
+import mimetypes
+
+DEFAULT_DATASET_NAME = 'dataset'
+
+class DisplayApplicationParameter( object ):
+ """ Abstract Class for Display Application Parameters """
+
+ type = None
+
+ @classmethod
+ def from_elem( cls, elem, link ):
+ param_type = elem.get( 'type', None )
+ assert param_type, 'DisplayApplicationParameter requires a type'
+ return parameter_type_to_class[ param_type ]( elem, link )
+ def __init__( self, elem, link ):
+ self.name = elem.get( 'name', None )
+ assert self.name, 'DisplayApplicationParameter requires a name'
+ self.link = link
+ self.url = elem.get( 'url', self.name ) #name used in url for display purposes defaults to name; e.g. want the form of file.ext, where a '.' is not allowed as python variable name/keyword
+ self.mime_type = elem.get( 'mimetype', None )
+ self.guess_mime_type = string_as_bool( elem.get( 'guess_mimetype', 'False' ) )
+ self.viewable = string_as_bool( elem.get( 'viewable', 'False' ) ) #only allow these to be viewed via direct url when explicitly set to viewable
+ self.strip = string_as_bool( elem.get( 'strip', 'False' ) )
+ self.strip_https = string_as_bool( elem.get( 'strip_https', 'False' ) )
+ def get_value( self, other_values, trans ):
+ raise Exception, 'Unimplemented'
+ def prepare( self, other_values, trans ):
+ return self.get_value( other_values, trans )
+ def ready( self, other_values ):
+ return True
+ def is_preparing( self, other_values ):
+ return False
+
+class DisplayApplicationDataParameter( DisplayApplicationParameter ):
+ """ Parameter that returns a file_name containing the requested content """
+
+ type = 'data'
+
+ def __init__( self, elem, link ):
+ DisplayApplicationParameter.__init__( self, elem, link )
+ self.extensions = elem.get( 'format', None )
+ if self.extensions:
+ self.extensions = self.extensions.split( "," )
+ self.metadata = elem.get( 'metadata', None )
+ self.dataset = elem.get( 'dataset', DEFAULT_DATASET_NAME ) # 'dataset' is default name assigned to dataset to be displayed
+ assert not ( self.extensions and self.metadata ), 'A format or a metadata can be defined for a DisplayApplicationParameter, but not both.'
+ self.viewable = string_as_bool( elem.get( 'viewable', 'True' ) ) #data params should be viewable
+ self.force_url_param = string_as_bool( elem.get( 'force_url_param', 'False' ) )
+ self.force_conversion = string_as_bool( elem.get( 'force_conversion', 'False' ) )
+ @property
+ def formats( self ):
+ if self.extensions:
+ return tuple( map( type, map( self.link.display_application.datatypes_registry.get_datatype_by_extension, self.extensions ) ) )
+ return None
+ def _get_dataset_like_object( self, other_values ):
+ #this returned object has file_name, state, and states attributes equivalent to a DatasetAssociation
+ data = other_values.get( self.dataset, None )
+ assert data, 'Base dataset could not be found in values provided to DisplayApplicationDataParameter'
+ if isinstance( data, DisplayDataValueWrapper ):
+ data = data.value
+ if self.metadata:
+ rval = getattr( data.metadata, self.metadata, None )
+ assert rval, 'Unknown metadata name (%s) provided for dataset type (%s).' % ( self.metadata, data.datatype.__class__.name )
+ return Bunch( file_name = rval.file_name, state = data.state, states = data.states, extension='data' )
+ elif self.extensions and ( self.force_conversion or not isinstance( data.datatype, self.formats ) ):
+ for ext in self.extensions:
+ rval = data.get_converted_files_by_type( ext )
+ if rval:
+ return rval[0]
+ assert data.find_conversion_destination( self.formats )[0] is not None, "No conversion path found for data param: %s" % self.name
+ return None
+ return data
+ def get_value( self, other_values, trans ):
+ data = self._get_dataset_like_object( other_values )
+ if data:
+ return DisplayDataValueWrapper( data, self, other_values, trans )
+ return None
+ def prepare( self, other_values, trans ):
+ data = self._get_dataset_like_object( other_values )
+ if not data and self.formats:
+ data = other_values.get( self.dataset, None )
+ trans.sa_session.refresh( data )
+ #start conversion
+ #FIXME: Much of this is copied (more than once...); should be some abstract method elsewhere called from here
+ #find target ext
+ target_ext, converted_dataset = data.find_conversion_destination( self.formats, converter_safe = True )
+ if target_ext and not converted_dataset:
+ assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = data, file_type = target_ext, metadata_safe = False )
+ new_data = data.datatype.convert_dataset( trans, data, target_ext, return_output = True, visible = False ).values()[0]
+ new_data.hid = data.hid
+ new_data.name = data.name
+ trans.sa_session.add( new_data )
+ trans.sa_session.flush()
+ assoc.dataset = new_data
+ trans.sa_session.add( assoc )
+ trans.sa_session.flush()
+ elif converted_dataset and converted_dataset.state == converted_dataset.states.ERROR:
+ raise Exception, "Dataset conversion failed for data parameter: %s" % self.name
+ return self.get_value( other_values, trans )
+ def is_preparing( self, other_values ):
+ value = self._get_dataset_like_object( other_values )
+ if value and value.state in ( value.states.NEW, value.states.UPLOAD, value.states.QUEUED, value.states.RUNNING ):
+ return True
+ return False
+ def ready( self, other_values ):
+ value = self._get_dataset_like_object( other_values )
+ if value:
+ if value.state == value.states.OK:
+ return True
+ elif value.state == value.states.ERROR:
+ raise Exception( 'A data display parameter is in the error state: %s' % ( self.name ) )
+ return False
+
+class DisplayApplicationTemplateParameter( DisplayApplicationParameter ):
+ """ Parameter that returns a string containing the requested content """
+
+ type = 'template'
+
+ def __init__( self, elem, link ):
+ DisplayApplicationParameter.__init__( self, elem, link )
+ self.text = elem.text
+ def get_value( self, other_values, trans ):
+ value = fill_template( self.text, context = other_values )
+ if self.strip:
+ value = value.strip()
+ return DisplayParameterValueWrapper( value, self, other_values, trans )
+
+parameter_type_to_class = { DisplayApplicationDataParameter.type:DisplayApplicationDataParameter, DisplayApplicationTemplateParameter.type:DisplayApplicationTemplateParameter }
+
+class DisplayParameterValueWrapper( object ):
+ ACTION_NAME = 'param'
+ def __init__( self, value, parameter, other_values, trans ):
+ self.value = value
+ self.parameter = parameter
+ self.other_values = other_values
+ self.trans = trans
+ self._dataset_hash, self._user_hash = encode_dataset_user( trans, self.other_values[ DEFAULT_DATASET_NAME ], trans.user )
+ def __str__( self ):
+ return str( self.value )
+ def mime_type( self ):
+ if self.parameter.mime_type is not None:
+ return self.parameter.mime_type
+ if self.parameter.guess_mime_type:
+ mime, encoding = mimetypes.guess_type( self.parameter.url )
+ if not mime:
+ mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self.parameter.url )[ -1 ], None )
+ if mime:
+ return mime
+ return 'text/plain'
+ @property
+ def url( self ):
+ base_url = self.trans.request.base
+ if self.parameter.strip_https and base_url[ : 5].lower() == 'https':
+ base_url = "http%s" % base_url[ 5: ]
+ return "%s%s" % ( base_url, url_for( controller = 'dataset', action = "display_application", dataset_id = self._dataset_hash, user_id = self._user_hash, app_name = self.parameter.link.display_application.id, link_name = self.parameter.link.id, app_action = self.action_name, action_param = self.parameter.url ) )
+ @property
+ def action_name( self ):
+ return self.ACTION_NAME
+ @property
+ def qp( self ):
+ #returns quoted str contents
+ return self.other_values[ 'qp' ]( str( self ) )
+ def __getattr__( self, key ):
+ return getattr( self.value, key )
+
+class DisplayDataValueWrapper( DisplayParameterValueWrapper ):
+ ACTION_NAME = 'data'
+ def __str__( self ):
+ #string of data param is filename
+ return str( self.value.file_name )
+ def mime_type( self ):
+ if self.parameter.mime_type is not None:
+ return self.parameter.mime_type
+ if self.parameter.guess_mime_type:
+ mime, encoding = mimetypes.guess_type( self.parameter.url )
+ if not mime:
+ mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self.parameter.url )[ -1 ], None )
+ if mime:
+ return mime
+ return self.other_values[ DEFAULT_DATASET_NAME ].get_mime()
+ @property
+ def action_name( self ):
+ if self.parameter.force_url_param:
+ return super( DisplayParameterValueWrapper, self ).action_name
+ return self.ACTION_NAME
+ @property
+ def qp( self ):
+ #returns quoted url contents
+ return self.other_values[ 'qp' ]( self.url )
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py Thu Feb 11 16:18:45 2010 -0500
+++ b/lib/galaxy/datatypes/interval.py Fri Feb 12 11:01:30 2010 -0500
@@ -486,6 +486,36 @@
def get_track_type( self ):
return "FeatureTrack", "interval_index"
+class BedStrict( Bed ):
+ """Tab delimited data in strict BED format - no non-standard columns allowed"""
+
+ file_ext = "bedstrict"
+
+ #no user change of datatype allowed
+ allow_datatype_change = False
+
+ #Read only metadata elements
+ MetadataElement( name="chromCol", default=1, desc="Chrom column", readonly=True, param=metadata.MetadataParameter )
+ MetadataElement( name="startCol", default=2, desc="Start column", readonly=True, param=metadata.MetadataParameter ) #TODO: start and end should be able to be set to these or the proper thick[start/end]?
+ MetadataElement( name="endCol", default=3, desc="End column", readonly=True, param=metadata.MetadataParameter )
+ MetadataElement( name="strandCol", desc="Strand column (click box & select)", readonly=True, param=metadata.MetadataParameter, no_value=0, optional=True )
+ MetadataElement( name="nameCol", desc="Name/Identifier column (click box & select)", readonly=True, param=metadata.MetadataParameter, no_value=0, optional=True )
+ MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False )
+
+ def __init__( self, **kwd ):
+ Tabular.__init__( self, **kwd )
+ self.clear_display_apps() #only new style display applications for this datatype
+
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ Tabular.set_meta( self, dataset, overwrite = overwrite, **kwd) #need column count first
+ if dataset.metadata.columns >= 4:
+ dataset.metadata.nameCol = 4
+ if dataset.metadata.columns >= 6:
+ dataset.metadata.strandCol = 6
+
+ def sniff( self, filename ):
+ return False #NOTE: This would require aggressively validating the entire file
+
class _RemoteCallMixin:
def _get_remote_call_url( self, redirect_url, site_name, dataset, type, app, base_url ):
"""Retrieve the URL to call out to an external site and retrieve data.
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py Thu Feb 11 16:18:45 2010 -0500
+++ b/lib/galaxy/datatypes/registry.py Fri Feb 12 11:01:30 2010 -0500
@@ -6,6 +6,7 @@
import data, tabular, interval, images, sequence, qualityscore, genetics, xml, coverage, tracks, chrominfo, binary
import galaxy.util
from galaxy.util.odict import odict
+from display_applications.application import DisplayApplication
class ConfigurationError( Exception ):
pass
@@ -23,6 +24,7 @@
self.indexers = []
self.sniff_order = []
self.upload_file_formats = []
+ self.display_applications = odict() #map a display application id to a display application
if root_dir and config:
# Parse datatypes_conf.xml
tree = galaxy.util.parse_xml( config )
@@ -32,6 +34,7 @@
registration = root.find( 'registration' )
self.datatype_converters_path = os.path.join( root_dir, registration.get( 'converters_path', 'lib/galaxy/datatypes/converters' ) )
self.datatype_indexers_path = os.path.join( root_dir, registration.get( 'indexers_path', 'lib/galaxy/datatypes/indexers' ) )
+ self.display_applications_path = os.path.join( root_dir, registration.get( 'display_path', 'display_applications' ) )
if not os.path.isdir( self.datatype_converters_path ):
raise ConfigurationError( "Directory does not exist: %s" % self.datatype_converters_path )
if not os.path.isdir( self.datatype_indexers_path ):
@@ -79,6 +82,17 @@
optional = composite_file.get( 'optional', False )
mimetype = composite_file.get( 'mimetype', None )
self.datatypes_by_extension[extension].add_composite_file( name, optional=optional, mimetype=mimetype )
+ for display_app in elem.findall( 'display' ):
+ display_file = display_app.get( 'file', None )
+ assert display_file is not None, "A file must be specified for a datatype display tag."
+ display_app = DisplayApplication.from_file( os.path.join( self.display_applications_path, display_file ), self )
+ if display_app:
+ if display_app.id in self.display_applications:
+ #if we already loaded this display application, we'll use the first one again
+ display_app = self.display_applications[ display_app.id ]
+ self.log.debug( "Loaded display application '%s' for datatype '%s'" % ( display_app.id, extension ) )
+ self.display_applications[ display_app.id ] = display_app #Display app by id
+ self.datatypes_by_extension[ extension ].add_display_application( display_app )
except Exception, e:
self.log.warning( 'Error loading datatype "%s", problem: %s' % ( extension, str( e ) ) )
@@ -213,13 +227,13 @@
def get_available_tracks(self):
return self.available_tracks
- def get_mimetype_by_extension(self, ext ):
+ def get_mimetype_by_extension(self, ext, default = 'application/octet-stream' ):
"""Returns a mimetype based on an extension"""
try:
mimetype = self.mimetypes_by_extension[ext]
except KeyError:
#datatype was never declared
- mimetype = 'application/octet-stream'
+ mimetype = default
self.log.warning('unknown mimetype in data factory %s' % ext)
return mimetype
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/web/buildapp.py
--- a/lib/galaxy/web/buildapp.py Thu Feb 11 16:18:45 2010 -0500
+++ b/lib/galaxy/web/buildapp.py Fri Feb 12 11:01:30 2010 -0500
@@ -74,6 +74,7 @@
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='root', action='index' )
webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None)
+ webapp.add_route( '/display_application/:dataset_id/:user_id/:app_name/:link_name/:app_action/:action_param', controller='dataset', action='display_application', dataset_id=None, user_id=None, app_name = None, link_name = None, app_action = None, action_param = None )
webapp.add_route( '/u/:username/d/:slug', controller='dataset', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/h/:slug', controller='history', action='display_by_username_and_slug' )
diff -r 81d84a03f2ec -r 049a86b8691d lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Thu Feb 11 16:18:45 2010 -0500
+++ b/lib/galaxy/web/controllers/dataset.py Fri Feb 12 11:01:30 2010 -0500
@@ -4,6 +4,7 @@
from galaxy.web.framework.helpers import time_ago, iff, grids
from galaxy import util, datatypes, jobs, web, model
from cgi import escape, FieldStorage
+from galaxy.datatypes.display_applications.helpers import decode_dataset_user
from email.MIMEText import MIMEText
@@ -188,7 +189,7 @@
dataset_id = int( dataset_id )
except ValueError:
dataset_id = trans.security.decode_id( dataset_id )
- data = data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id )
+ data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id )
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
current_user_roles = trans.get_current_user_roles()
@@ -339,6 +340,74 @@
else:
return trans.show_error_message( "You are not allowed to view this dataset at external sites. Please contact your Galaxy administrator to acquire management permissions for this dataset." )
+ @web.expose
+ def display_application( self, trans, dataset_id=None, user_id=None, app_name = None, link_name = None, app_action = None, action_param = None ):
+ """Access to external display applications"""
+ #decode ids
+ data, user = decode_dataset_user( trans, dataset_id, user_id )
+ if not data:
+ raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
+ if user:
+ user_roles = user.all_roles()
+ else:
+ user_roles = []
+ if None in [ app_name, link_name ]:
+ return trans.show_error_message( "A display application name and link name must be provided." )
+
+ if app_action is None:
+ app_action = "display" # default action is display
+
+ if trans.app.security_agent.can_access_dataset( user_roles, data.dataset ):
+ msg = []
+ refresh = False
+ display_app = trans.app.datatypes_registry.display_applications.get( app_name )
+ assert display_app, "Unknown display application has been requested: %s" % app_name
+ display_link = display_app.get_link( link_name, data, trans )
+ assert display_link, "Unknown display link has been requested: %s" % link_name
+ if data.state == data.states.ERROR:
+ msg.append( ( 'This dataset is in an error state, you cannot view it at an external display application.', 'error' ) )
+ elif data.deleted:
+ msg.append( ( 'This dataset has been deleted, you cannot view it at an external display application.', 'error' ) )
+ elif data.state != data.states.OK:
+ msg.append( ( 'You must wait for this dataset to be created before you can view it at an external display application.', 'info' ) )
+ refresh = True
+ else:
+ #We have permissions, dataset is not deleted and is in OK state, allow access
+ if display_link.display_ready():
+ if app_action in [ 'data', 'param' ]:
+ assert action_param, "An action param must be provided for a data or param action"
+ #data is used for things with filenames that could be passed off to a proxy
+ #in case some display app wants all files to be in the same 'directory',
+ #data can be forced to param, but not the other way (no filename for other direction)
+ #get param name from url param name
+ action_param = display_link.get_param_name_by_url( action_param )
+ value = display_link.get_param_value( action_param )
+ assert value, "An invalid parameter name was provided: %s" % action_param
+ assert value.parameter.viewable, "This parameter is not viewable."
+ if value.parameter.type == 'data':
+ content_length = os.path.getsize( value.file_name )
+ rval = open( value.file_name )
+ else:
+ rval = str( value )
+ content_length = len( rval )
+ trans.response.set_content_type( value.mime_type() )
+ trans.response.headers[ 'Content-Length' ] = content_length
+ return rval
+ elif app_action == "display":
+ return trans.fill_template_mako( "dataset/display_application/launch_display.mako", display_link = display_link )
+ else:
+ msg.append( ( 'Invalid action provided: %s' % app_action, 'error' ) )
+ else:
+ msg.append( ( 'This display application is being prepared.', 'info' ) )
+ if app_action == "display":
+ refresh = True
+ if not display_link.preparing_display():
+ display_link.prepare_display()
+ else:
+ raise Exception( 'Attempted a view action (%s) on a non-ready display application' % app_action )
+ return trans.fill_template_mako( "dataset/display_application/display.mako", msg = msg, display_app = display_app, display_link = display_link, refresh = refresh )
+ return trans.show_error_message( 'You do not have permission to view this dataset at an external display application.' )
+
def _undelete( self, trans, id ):
try:
id = int( id )
diff -r 81d84a03f2ec -r 049a86b8691d templates/dataset/display_application/display.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/dataset/display_application/display.mako Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,17 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%def name="title()">Display Application: ${display_link.link.display_application.name} ${display_link.link.name}</%def>
+<% refresh_rate = 10 %>
+%if refresh:
+<script type="text/javascript">
+ setTimeout( "location.reload(true);", ${ refresh_rate * 1000 } );
+</script>
+%endif
+%for message, message_type in msg:
+ ${render_msg( message, message_type )}
+%endfor
+%if refresh:
+<p>
+This page will <a href="javascript:location.reload(true);">refresh</a> after ${refresh_rate} seconds.
+</p>
+%endif
diff -r 81d84a03f2ec -r 049a86b8691d templates/dataset/display_application/launch_display.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/dataset/display_application/launch_display.mako Fri Feb 12 11:01:30 2010 -0500
@@ -0,0 +1,15 @@
+<%inherit file="/base.mako"/>
+<%def name="title()">Launching Display Application: ${display_link.link.display_application.name} ${display_link.link.name}</%def>
+
+<script type="text/javascript">
+ location.href = '${display_link.display_url()}';
+</script>
+<p>
+All data has been prepared for the external display application: ${display_link.link.display_application.name} ${display_link.link.name}.
+</p>
+<p>
+You are now being automatically forwarded to the external application.
+</p>
+<p>
+Click <a href="${display_link.display_url()}">here</a> if this redirect has failed.
+</p>
diff -r 81d84a03f2ec -r 049a86b8691d templates/root/history_common.mako
--- a/templates/root/history_common.mako Thu Feb 11 16:18:45 2010 -0500
+++ b/templates/root/history_common.mako Fri Feb 12 11:01:30 2010 -0500
@@ -101,6 +101,12 @@
%endif
%endfor
%endif
+ %for display_app in data.datatype.display_applications.itervalues():
+ | ${display_app.name}
+ %for link_app in display_app.links.itervalues():
+ <a target="${link_app.url.get( 'target_frame', '_blank' )}" href="${link_app.get_display_url( data, trans )}">${_(link_app.name)}</a>
+ %endfor
+ %endfor
</div>
%if data.peek != "no peek":
<div><pre id="peek${data.id}" class="peek">${_(data.display_peek())}</pre></div>
1
0
Dear Galaxy Team,
I wanted to know if I can run a saved workflow in the database from the
shell.
Regards,
--
Sondos Seif El-Din
2
1
Dear Galaxy Team,
I wanted to know if I can run a saved workflow in the database from the
shell.
Regards,
--
Sondos Seif El-Din
1
0
11 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/81d84a03f2ec
changeset: 3374:81d84a03f2ec
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Thu Feb 11 16:18:45 2010 -0500
description:
Add the library description to the browse library page, and update the tool config for main.
diffstat:
templates/library/browse_libraries.mako | 2 +-
templates/library/common/browse_library.mako | 5 +++++
tool_conf.xml.main | 1 +
3 files changed, 7 insertions(+), 1 deletions(-)
diffs (38 lines):
diff -r a3e6350ffc57 -r 81d84a03f2ec templates/library/browse_libraries.mako
--- a/templates/library/browse_libraries.mako Thu Feb 11 14:26:25 2010 -0500
+++ b/templates/library/browse_libraries.mako Thu Feb 11 16:18:45 2010 -0500
@@ -23,7 +23,7 @@
%for library in libraries:
<tr class="libraryRow libraryOrFolderRow" id="libraryRow">
<td><a href="${h.url_for( controller='library_common', action='browse_library', cntrller='library', id=trans.security.encode_id( library.id ), hidden_folder_ids='' )}">${library.name}</a></td>
- <td><i>${library.description}</i></td>
+ <td>${library.description}</td>
</tr>
%endfor
</tbody>
diff -r a3e6350ffc57 -r 81d84a03f2ec templates/library/common/browse_library.mako
--- a/templates/library/common/browse_library.mako Thu Feb 11 14:26:25 2010 -0500
+++ b/templates/library/common/browse_library.mako Thu Feb 11 16:18:45 2010 -0500
@@ -366,6 +366,11 @@
${render_msg( msg, messagetype )}
%endif
+%if library.description:
+ <div class="libraryItemBody">${library.description}</div>
+ <br/>
+%endif
+
<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 ) )}" onSubmit="javascript:return checkForm();" method="post">
<table cellspacing="0" cellpadding="0" border="0" width="100%" class="grid" id="library-grid">
<thead>
diff -r a3e6350ffc57 -r 81d84a03f2ec tool_conf.xml.main
--- a/tool_conf.xml.main Thu Feb 11 14:26:25 2010 -0500
+++ b/tool_conf.xml.main Thu Feb 11 16:18:45 2010 -0500
@@ -37,6 +37,7 @@
<tool file="filters/headWrapper.xml" />
<tool file="filters/tailWrapper.xml" />
<tool file="filters/trimmer.xml" />
+ <tool file="stats/dna_filtering.xml" />
</section>
<section name="Convert Formats" id="convert">
<tool file="filters/bed2gff.xml" />
1
0
11 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/a3e6350ffc57
changeset: 3373:a3e6350ffc57
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Thu Feb 11 14:26:25 2010 -0500
description:
Add the ability to edit library templates and make library template inheritance optional.  Fix another bug in the form builder's CheckboxField.is_checked() method, and clean up some library code. With regard to template inheritance, a LibraryFolder is a special case because if it inherited the template from it's parent, we want to set inheritable to True for it's info_association.  This allows for the default inheritance to be False for each level in the Library hierarchy unless we're creating a new level in the hierarchy, in which case we'll inherit the "inheritable" setting from the parent level.
diffstat:
lib/galaxy/model/__init__.py | 39 +-
lib/galaxy/model/mapping.py | 2 +
lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py | 40 +
lib/galaxy/tools/actions/upload_common.py | 4 +
lib/galaxy/web/controllers/forms.py | 63 +-
lib/galaxy/web/controllers/library_admin.py | 50 +-
lib/galaxy/web/controllers/library_common.py | 352 ++++++---
lib/galaxy/web/form_builder.py | 4 +-
templates/admin/forms/edit_form.mako | 13 +-
templates/library/common/browse_library.mako | 77 +-
templates/library/common/common.mako | 98 +-
templates/library/common/edit_template.mako | 35 +
templates/library/common/folder_info.mako | 2 +-
templates/library/common/ldda_edit_info.mako | 2 +-
templates/library/common/ldda_info.mako | 23 +-
templates/library/common/library_dataset_info.mako | 3 +-
templates/library/common/library_info.mako | 74 +-
templates/library/common/new_folder.mako | 7 +-
templates/library/common/select_info_template.mako | 75 --
templates/library/common/select_template.mako | 82 ++
test/base/twilltestcase.py | 41 +-
test/functional/test_security_and_libraries.py | 56 +-
22 files changed, 678 insertions(+), 464 deletions(-)
diffs (2031 lines):
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/model/__init__.py Thu Feb 11 14:26:25 2010 -0500
@@ -755,14 +755,17 @@
self.root_folder = root_folder
def get_info_association( self, restrict=False, inherited=False ):
if self.info_association:
- return self.info_association[0], inherited
+ if not inherited or self.info_association[0].inheritable:
+ return self.info_association[0], inherited
+ else:
+ return None, inherited
return None, inherited
def get_template_widgets( self, trans, get_contents=True ):
# See if we have any associated templates - the returned value for
# inherited is not applicable at the library level. The get_contents
# param is passed by callers that are inheriting a template - these
# are usually new library datsets for which we want to include template
- # fields on the upload form.
+ # fields on the upload form, but not the contents of the inherited template.
info_association, inherited = self.get_info_association()
if info_association:
template = info_association.template
@@ -807,11 +810,14 @@
def get_info_association( self, restrict=False, inherited=False ):
# If restrict is True, we will return this folder's info_association, not inheriting.
# If restrict is False, we'll return the next available info_association in the
- # inheritable hierarchy. True is also returned if the info_association was inherited,
- # and False if not. This enables us to eliminate displaying the any contents of the inherited
- # template.
+ # inheritable hierarchy if it is "inheritable". True is also returned if the
+ # info_association was inherited and False if not. This enables us to eliminate
+ # displaying any contents of the inherited template.
if self.info_association:
- return self.info_association[0], inherited
+ if not inherited or self.info_association[0].inheritable:
+ return self.info_association[0], inherited
+ else:
+ return None, inherited
if restrict:
return None, inherited
if self.parent:
@@ -1004,19 +1010,22 @@
return []
class LibraryInfoAssociation( object ):
- def __init__( self, library, form_definition, info ):
+ def __init__( self, library, form_definition, info, inheritable=False ):
self.library = library
self.template = form_definition
self.info = info
+ self.inheritable = inheritable
class LibraryFolderInfoAssociation( object ):
- def __init__( self, folder, form_definition, info ):
+ def __init__( self, folder, form_definition, info, inheritable=False ):
self.folder = folder
self.template = form_definition
self.info = info
+ self.inheritable = inheritable
class LibraryDatasetDatasetInfoAssociation( object ):
def __init__( self, library_dataset_dataset_association, form_definition, info ):
+ # TODO: need to figure out if this should be inheritable to the associated LibraryDataset
self.library_dataset_dataset_association = library_dataset_dataset_association
self.template = form_definition
self.info = info
@@ -1252,8 +1261,18 @@
else:
value = util.restore_text( params.get( field_name, '' ) )
elif contents:
- # this field has a saved value
- value = str( contents[ index ] )
+ try:
+ # This field has a saved value.
+ value = str( contents[ index ] )
+ except:
+ # If there was an error getting the saved value, we'll still
+ # display the widget, but it will be empty.
+ if field[ 'type' ] == 'CheckboxField':
+ # Since we do not have contents, set checkbox value to False
+ value = False
+ else:
+ # Set other field types to empty string
+ value = ''
else:
# if none of the above, then leave the field empty
if field[ 'type' ] == 'CheckboxField':
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/model/mapping.py Thu Feb 11 14:26:25 2010 -0500
@@ -294,6 +294,7 @@
Column( "library_id", Integer, ForeignKey( "library.id" ), index=True ),
Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ),
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
+ Column( "inheritable", Boolean, index=True, default=False ),
Column( "deleted", Boolean, index=True, default=False ) )
LibraryFolderInfoAssociation.table = Table( 'library_folder_info_association', metadata,
@@ -301,6 +302,7 @@
Column( "library_folder_id", Integer, ForeignKey( "library_folder.id" ), nullable=True, index=True ),
Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ),
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
+ Column( "inheritable", Boolean, index=True, default=False ),
Column( "deleted", Boolean, index=True, default=False ) )
LibraryDatasetDatasetInfoAssociation.table = Table( 'library_dataset_dataset_info_association', metadata,
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0038_add_inheritable_column_to_library_template_assoc_tables.py Thu Feb 11 14:26:25 2010 -0500
@@ -0,0 +1,40 @@
+"""
+Migration script to add an inheritable column to the following tables:
+library_info_association, library_folder_info_association.
+"""
+
+from sqlalchemy import *
+from migrate import *
+from migrate.changeset import *
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ LibraryInfoAssociation_table = Table( "library_info_association", metadata, autoload=True )
+ c = Column( "inheritable", Boolean, index=True, default=False )
+ c.create( LibraryInfoAssociation_table )
+ assert c is LibraryInfoAssociation_table.c.inheritable
+ cmd = "UPDATE library_info_association SET inheritable = false"
+ try:
+ db_session.execute( cmd )
+ except Exception, e:
+ log.debug( "Setting value of column inheritable to false in library_info_association failed: %s" % ( str( e ) ) )
+
+ LibraryFolderInfoAssociation_table = Table( "library_folder_info_association", metadata, autoload=True )
+ c = Column( "inheritable", Boolean, index=True, default=False )
+ c.create( LibraryFolderInfoAssociation_table )
+ assert c is LibraryFolderInfoAssociation_table.c.inheritable
+ cmd = "UPDATE library_folder_info_association SET inheritable = false"
+ try:
+ db_session.execute( cmd )
+ except Exception, e:
+ log.debug( "Setting value of column inheritable to false in library_folder_info_association failed: %s" % ( str( e ) ) )
+
+def downgrade():
+ pass
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/tools/actions/upload_common.py
--- a/lib/galaxy/tools/actions/upload_common.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/tools/actions/upload_common.py Thu Feb 11 14:26:25 2010 -0500
@@ -191,6 +191,8 @@
trans.sa_session.add( form_values )
trans.sa_session.flush()
# Create a new info_association between the current ldda and form_values
+ # TODO: Currently info_associations at the ldda level are not inheritable to the associated LibraryDataset,
+ # we need to figure out if this is optimal
info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation( ldda, library_bunch.template, form_values )
trans.sa_session.add( info_association )
trans.sa_session.flush()
@@ -235,6 +237,8 @@
trans.sa_session.add( form_values )
trans.sa_session.flush()
# Create a new info_association between the current ldda and form_values
+ # TODO: Currently info_associations at the ldda level are not inheritable to the associated LibraryDataset,
+ # we need to figure out if this is optimal
info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation( data, library_bunch.template, form_values )
trans.sa_session.add( info_association )
trans.sa_session.flush()
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/web/controllers/forms.py
--- a/lib/galaxy/web/controllers/forms.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/web/controllers/forms.py Thu Feb 11 14:26:25 2010 -0500
@@ -92,7 +92,7 @@
elif operation == "undelete":
return self.__undelete( trans, **kwd )
elif operation == "edit":
- return self.__edit( trans, **kwd )
+ return self.edit( trans, **kwd )
return self.forms_grid( trans, **kwd )
def __view(self, trans, **kwd):
try:
@@ -141,13 +141,11 @@
self.__get_saved_form( fd )
if self.__imported_from_file:
return trans.response.send_redirect( web.url_for( controller='forms',
- action='manage',
- operation='edit',
+ action='edit',
id=trans.security.encode_id(fd.current.id)) )
else:
return trans.response.send_redirect( web.url_for( controller='forms',
- action='manage',
- operation='edit',
+ action='edit',
id=trans.security.encode_id(fd.current.id),
add_field_button='Add field',
name=fd.name,
@@ -197,10 +195,13 @@
action='manage',
message='%i form(s) is undeleted.' % len(id_list),
status='done') )
- def __edit( self, trans, **kwd ):
+ @web.expose
+ def edit( self, trans, response_redirect=None, **kwd ):
'''
- This callback method is for handling all the editing functions like
- renaming fields, adding/deleting fields, changing fields attributes.
+ This callback method is for handling form editing. The value of response_redirect
+ should be an URL that is defined by the caller. This allows for redirecting as desired
+ when the form changes have been saved. For an example of how this works, see the
+ edit_template() method in the library_common controller.
'''
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
@@ -223,13 +224,16 @@
if not fd_new:
current_form = self.__get_form( trans, **kwd )
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype='error', **kwd )
- # everything went fine. form saved successfully. Show the saved form
+ msg=msg, messagetype='error', response_redirect=response_redirect, **kwd )
+ # everything went fine. form saved successfully. Show the saved form or redirect
+ # to response_redirect if appropriate.
+ if response_redirect:
+ return trans.response.send_redirect( response_redirect )
fd = fd_new
current_form = self.__get_saved_form( fd )
msg = "The form '%s' has been updated with the changes." % fd.name
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
#
# Add a layout grid
#
@@ -238,7 +242,7 @@
current_form['layout'].append('')
# show the form again
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
#
# Delete a layout grid
#
@@ -247,7 +251,7 @@
index = int( kwd[ 'remove_layout_grid_button' ].split( ' ' )[2] ) - 1
del current_form['layout'][index]
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
#
# Add a field
#
@@ -256,7 +260,7 @@
current_form['fields'].append( self.empty_field )
# show the form again with one empty field
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
#
# Delete a field
#
@@ -266,33 +270,33 @@
index = int( kwd[ 'remove_button' ].split( ' ' )[2] ) - 1
del current_form['fields'][index]
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
#
# Add SelectField option
#
elif 'Add' in kwd.values():
- return self.__add_selectbox_option(trans, fd, msg, messagetype, **kwd)
+ return self.__add_selectbox_option(trans, fd, msg, messagetype, response_redirect=response_redirect, **kwd)
#
# Remove SelectField option
#
elif 'Remove' in kwd.values():
- return self.__remove_selectbox_option(trans, fd, msg, messagetype, **kwd)
+ return self.__remove_selectbox_option(trans, fd, msg, messagetype, response_redirect=response_redirect, **kwd)
#
# Refresh page
#
elif params.get( 'refresh', False ):
current_form = self.__get_form( trans, **kwd )
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
#
# Show the form for editing
#
else:
current_form = self.__get_saved_form( fd )
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
- def __add_selectbox_option( self, trans, fd, msg, messagetype, **kwd ):
+ def __add_selectbox_option( self, trans, fd, msg, messagetype, response_redirect=None, **kwd ):
'''
This method adds a selectbox option. The kwd dict searched for
the field index which needs to be removed
@@ -309,12 +313,12 @@
# something wrong happened
return self.__show( trans=trans, form=fd, current_form=current_form,
msg='Error in adding selectfield option',
- messagetype='error', **kwd )
+ messagetype='error', response_redirect=response_redirect, **kwd )
# add an empty option
current_form[ 'fields' ][ index ][ 'selectlist' ].append( '' )
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
- def __remove_selectbox_option( self, trans, fd, msg, messagetype, **kwd ):
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
+ def __remove_selectbox_option( self, trans, fd, msg, messagetype, response_redirect=None, **kwd ):
'''
This method removes a selectbox option. The kwd dict searched for
the field index and option index which needs to be removed
@@ -332,11 +336,11 @@
# something wrong happened
return self.__show( trans=trans, form=fd, current_form=current_form,
msg='Error in removing selectfield option',
- messagetype='error', **kwd )
+ messagetype='error', response_redirect=response_redirect, **kwd )
# remove the option
del current_form[ 'fields' ][ index ][ 'selectlist' ][ option ]
return self.__show( trans=trans, form=fd, current_form=current_form,
- msg=msg, messagetype=messagetype, **kwd )
+ msg=msg, messagetype=messagetype, response_redirect=response_redirect, **kwd )
def __get_field(self, index, **kwd):
@@ -597,7 +601,7 @@
def label(self):
return str(self.index)+'.'+self.label
- def __show( self, trans, form, current_form, msg='', messagetype='done', **kwd ):
+ def __show( self, trans, form, current_form, msg='', messagetype='done', response_redirect=None, **kwd ):
'''
This method displays the form and any of the changes made to it,
The empty_form param allows for this method to simulate clicking
@@ -606,9 +610,11 @@
'''
params = util.Params( kwd )
# name & description
+ # TODO: RC, I've changed Type to be a hidden field since it should not be displayed on the edit_form.mako
+ # template. Make sure this is the optimal solution for this problem. See my additional TODO in edit_form.mako.
form_details = [ ( 'Name', TextField( 'name', 40, current_form[ 'name' ] ) ),
( 'Description', TextField( 'description', 40, current_form[ 'desc' ] ) ),
- ( 'Type', self.__form_types_widget(trans, selected=current_form[ 'type' ]) ) ]
+ ( 'Type', HiddenField( 'form_type_selectbox', current_form['type']) ) ]
form_layout = []
if current_form[ 'type' ] == trans.app.model.FormDefinition.types.SAMPLE:
for index, lg in enumerate(current_form[ 'layout' ]):
@@ -629,7 +635,8 @@
msg=msg,
messagetype=messagetype,
current_form_type=current_form[ 'type' ],
- layout_grids=form_layout )
+ layout_grids=form_layout,
+ response_redirect=response_redirect )
# Common methods for all components that use forms
def get_all_forms( trans, all_versions=False, filter=None, form_type='All' ):
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/web/controllers/library_admin.py
--- a/lib/galaxy/web/controllers/library_admin.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/web/controllers/library_admin.py Thu Feb 11 14:26:25 2010 -0500
@@ -162,7 +162,7 @@
status='done' ) )
@web.expose
@web.require_admin
- def delete_library_item( self, trans, library_id, library_item_id, library_item_type, **kwd ):
+ def delete_library_item( self, trans, library_id, item_id, item_type, **kwd ):
# This action will handle deleting all types of library items. State is saved for libraries and
# folders ( i.e., if undeleted, the state of contents of the library or folder will remain, so previously
# deleted / purged contents will have the same state ). When a library or folder has been deleted for
@@ -171,24 +171,24 @@
# enables clean maintenance of libraries and library dataset disk files. This is also why the following
# 3 objects, and not any of the associations ( the cleanup_datasets.py scipot handles everything else ).
show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) )
- library_item_types = { 'library': trans.app.model.Library,
- 'folder': trans.app.model.LibraryFolder,
- 'library_dataset': trans.app.model.LibraryDataset }
- if library_item_type not in library_item_types:
- msg = 'Bad library_item_type specified: %s' % str( library_item_type )
+ item_types = { 'library': trans.app.model.Library,
+ 'folder': trans.app.model.LibraryFolder,
+ 'library_dataset': trans.app.model.LibraryDataset }
+ if item_type not in item_types:
+ msg = 'Bad item_type specified: %s' % str( item_type )
messagetype = 'error'
else:
- if library_item_type == 'library_dataset':
- library_item_desc = 'Dataset'
+ if item_type == 'library_dataset':
+ item_desc = 'Dataset'
else:
- library_item_desc = library_item_type.capitalize()
- library_item = trans.sa_session.query( library_item_types[ library_item_type ] ).get( trans.security.decode_id( library_item_id ) )
+ item_desc = item_type.capitalize()
+ library_item = trans.sa_session.query( item_types[ item_type ] ).get( trans.security.decode_id( item_id ) )
library_item.deleted = True
trans.sa_session.add( library_item )
trans.sa_session.flush()
- msg = util.sanitize_text( "%s '%s' has been marked deleted" % ( library_item_desc, library_item.name ) )
+ msg = util.sanitize_text( "%s '%s' has been marked deleted" % ( item_desc, library_item.name ) )
messagetype = 'done'
- if library_item_type == 'library':
+ if item_type == 'library':
return self.browse_libraries( trans, message=msg, status=messagetype )
else:
return trans.response.send_redirect( web.url_for( controller='library_common',
@@ -200,31 +200,31 @@
messagetype=messagetype ) )
@web.expose
@web.require_admin
- def undelete_library_item( self, trans, library_id, library_item_id, library_item_type, **kwd ):
+ def undelete_library_item( self, trans, library_id, item_id, item_type, **kwd ):
# This action will handle undeleting all types of library items
show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) )
- library_item_types = { 'library': trans.app.model.Library,
- 'folder': trans.app.model.LibraryFolder,
- 'library_dataset': trans.app.model.LibraryDataset }
- if library_item_type not in library_item_types:
- msg = 'Bad library_item_type specified: %s' % str( library_item_type )
+ item_types = { 'library': trans.app.model.Library,
+ 'folder': trans.app.model.LibraryFolder,
+ 'library_dataset': trans.app.model.LibraryDataset }
+ if item_type not in item_types:
+ msg = 'Bad item_type specified: %s' % str( item_type )
status = ERROR
else:
- if library_item_type == 'library_dataset':
- library_item_desc = 'Dataset'
+ if item_type == 'library_dataset':
+ item_desc = 'Dataset'
else:
- library_item_desc = library_item_type.capitalize()
- library_item = trans.sa_session.query( library_item_types[ library_item_type ] ).get( trans.security.decode_id( library_item_id ) )
+ item_desc = item_type.capitalize()
+ library_item = trans.sa_session.query( item_types[ item_type ] ).get( trans.security.decode_id( item_id ) )
if library_item.purged:
- msg = '%s %s has been purged, so it cannot be undeleted' % ( library_item_desc, library_item.name )
+ msg = '%s %s has been purged, so it cannot be undeleted' % ( item_desc, library_item.name )
status = ERROR
else:
library_item.deleted = False
trans.sa_session.add( library_item )
trans.sa_session.flush()
- msg = util.sanitize_text( "%s '%s' has been marked undeleted" % ( library_item_desc, library_item.name ) )
+ msg = util.sanitize_text( "%s '%s' has been marked undeleted" % ( item_desc, library_item.name ) )
status = SUCCESS
- if library_item_type == 'library':
+ if item_type == 'library':
return self.browse_libraries( trans, message=msg, status=status )
else:
return trans.response.send_redirect( web.url_for( controller='library_common',
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/web/controllers/library_common.py
--- a/lib/galaxy/web/controllers/library_common.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/web/controllers/library_common.py Thu Feb 11 14:26:25 2010 -0500
@@ -6,7 +6,7 @@
from galaxy.util.json import to_json_string
from galaxy.tools.actions import upload_common
from galaxy.web.controllers.forms import get_all_forms
-from galaxy.web.form_builder import SelectField
+from galaxy.web.form_builder import SelectField, CheckboxField
from galaxy.model.orm import *
from galaxy.util.streamball import StreamBall
import logging, tempfile, zipfile, tarfile, os, sys
@@ -126,6 +126,7 @@
library_id = params.get( 'id', None )
library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
# See if we have any associated templates
+ info_association, inherited = library.get_info_association()
widgets = library.get_template_widgets( trans )
current_user_roles = trans.get_current_user_roles()
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
@@ -158,6 +159,8 @@
widgets=widgets,
current_user_roles=current_user_roles,
show_deleted=show_deleted,
+ info_association=info_association,
+ inherited=inherited,
msg=msg,
messagetype=messagetype )
@web.expose
@@ -202,8 +205,8 @@
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
- folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( parent_id ) )
- if not folder:
+ parent_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( parent_id ) )
+ if not parent_folder:
msg = "Invalid parent folder id (%s) specified" % str( parent_id )
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
@@ -212,19 +215,41 @@
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
messagetype='error' ) )
- if params.new == 'submitted':
+ if params.get( 'new_folder_button', False ):
new_folder = trans.app.model.LibraryFolder( name=util.restore_text( params.name ),
description=util.restore_text( params.description ) )
# We are associating the last used genome build with folders, so we will always
# initialize a new folder with the first dbkey in util.dbnames which is currently
# ? unspecified (?)
new_folder.genome_build = util.dbnames.default_value
- folder.add_folder( new_folder )
+ parent_folder.add_folder( new_folder )
trans.sa_session.add( new_folder )
trans.sa_session.flush()
# New folders default to having the same permissions as their parent folder
- trans.app.security_agent.copy_library_permissions( folder, new_folder )
- msg = "New folder named '%s' has been added to the library" % new_folder.name
+ trans.app.security_agent.copy_library_permissions( parent_folder, new_folder )
+ # If we have an inheritable template, redirect to the folder_info page so information
+ # can be filled in immediately.
+ widgets = []
+ info_association, inherited = new_folder.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = new_folder.get_template_widgets( trans )
+ if info_association:
+ current_user_roles = trans.get_current_user_roles()
+ msg = "The new folder named '%s' has been added to the data library. " % new_folder.name
+ msg += "Additional information about this folder may be added using the inherited template."
+ return trans.fill_template( '/library/common/folder_info.mako',
+ cntrller=cntrller,
+ folder=new_folder,
+ library_id=library_id,
+ widgets=widgets,
+ current_user_roles=current_user_roles,
+ show_deleted=show_deleted,
+ info_association=info_association,
+ inherited=inherited,
+ msg=msg,
+ messagetype='done' )
+ # If not inheritable info_association, redirect to the library.
+ msg = "The new folder named '%s' has been added to the library" % new_folder.name
return trans.response.send_redirect( web.url_for( controller='library_common',
action='browse_library',
cntrller=cntrller,
@@ -232,10 +257,12 @@
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
messagetype='done' ) )
+ # We do not render any template widgets on creation pages since saving the info_association
+ # cannot occur before the associated item is saved.
return trans.fill_template( '/library/common/new_folder.mako',
cntrller=cntrller,
library_id=library_id,
- folder=folder,
+ folder=parent_folder,
show_deleted=show_deleted,
msg=msg,
messagetype=messagetype )
@@ -248,7 +275,10 @@
folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( id ) )
current_user_roles = trans.get_current_user_roles()
# See if we have any associated templates
- widgets = folder.get_template_widgets( trans )
+ widgets = []
+ info_association, inherited = folder.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = folder.get_template_widgets( trans )
if params.get( 'rename_folder_button', False ):
if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, folder ):
old_name = folder.name
@@ -274,6 +304,8 @@
widgets=widgets,
current_user_roles=current_user_roles,
show_deleted=show_deleted,
+ info_association=info_association,
+ inherited=inherited,
msg=msg,
messagetype=messagetype )
@web.expose
@@ -354,7 +386,10 @@
file_formats = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems() if dtype_value.allow_datatype_change ]
file_formats.sort()
# See if we have any associated templates
- widgets = ldda.get_template_widgets( trans )
+ widgets = []
+ info_association, inherited = ldda.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = ldda.get_template_widgets( trans )
if params.get( 'change', False ):
# The user clicked the Save button on the 'Change data type' form
if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ):
@@ -369,16 +404,6 @@
else:
msg = "You are not authorized to change the data type of dataset '%s'" % ldda.name
messagetype = 'error'
- return trans.fill_template( "/library/common/ldda_edit_info.mako",
- cntrller=cntrller,
- ldda=ldda,
- library_id=library_id,
- file_formats=file_formats,
- widgets=widgets,
- current_user_roles=current_user_roles,
- show_deleted=show_deleted,
- msg=msg,
- messagetype=messagetype )
elif params.get( 'save', False ):
# The user clicked the Save button on the 'Edit Attributes' form
if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ):
@@ -411,16 +436,6 @@
else:
msg = "You are not authorized to edit the attributes of dataset '%s'" % ldda.name
messagetype = 'error'
- return trans.fill_template( "/library/common/ldda_edit_info.mako",
- cntrller=cntrller,
- ldda=ldda,
- library_id=library_id,
- file_formats=file_formats,
- widgets=widgets,
- current_user_roles=current_user_roles,
- show_deleted=show_deleted,
- msg=msg,
- messagetype=messagetype )
elif params.get( 'detect', False ):
# The user clicked the Auto-detect button on the 'Edit Attributes' form
if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ):
@@ -437,16 +452,6 @@
else:
msg = "You are not authorized to edit the attributes of dataset '%s'" % ldda.name
messagetype = 'error'
- return trans.fill_template( "/library/common/ldda_edit_info.mako",
- cntrller=cntrller,
- ldda=ldda,
- library_id=library_id,
- file_formats=file_formats,
- widgets=widgets,
- current_user_roles=current_user_roles,
- show_deleted=show_deleted,
- msg=msg,
- messagetype=messagetype )
if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda ):
if "dbkey" in ldda.datatype.metadata_spec and not ldda.metadata.dbkey:
# Copy dbkey into metadata, for backwards compatability
@@ -463,10 +468,12 @@
widgets=widgets,
current_user_roles=current_user_roles,
show_deleted=show_deleted,
+ info_association=info_association,
+ inherited=inherited,
msg=msg,
messagetype=messagetype )
@web.expose
- def ldda_display_info( self, trans, cntrller, library_id, folder_id, id, **kwd ):
+ def ldda_info( self, trans, cntrller, library_id, folder_id, id, **kwd ):
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
@@ -483,7 +490,10 @@
messagetype='error' ) )
library = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
# See if we have any associated templates
- widgets = ldda.get_template_widgets( trans )
+ widgets = []
+ info_association, inherited = ldda.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = ldda.get_template_widgets( trans )
current_user_roles = trans.get_current_user_roles()
return trans.fill_template( '/library/common/ldda_info.mako',
cntrller=cntrller,
@@ -492,6 +502,8 @@
show_deleted=show_deleted,
widgets=widgets,
current_user_roles=current_user_roles,
+ info_association=info_association,
+ inherited=inherited,
msg=msg,
messagetype=messagetype )
@web.expose
@@ -656,7 +668,7 @@
if not error:
# See if we have any inherited templates, but do not inherit contents.
info_association, inherited = folder.get_info_association( inherited=True )
- if info_association:
+ if info_association and info_association.inheritable:
template_id = str( info_association.template.id )
widgets = folder.get_template_widgets( trans, get_contents=False )
else:
@@ -718,7 +730,11 @@
msg=util.sanitize_text( msg ),
messagetype=messagetype ) )
# See if we have any inherited templates, but do not inherit contents.
- widgets = folder.get_template_widgets( trans, get_contents=False )
+ info_association, inherited = folder.get_info_association( inherited=True )
+ if info_association and info_association.inheritable:
+ widgets = folder.get_template_widgets( trans, get_contents=False )
+ else:
+ widgets = []
upload_option = params.get( 'upload_option', 'upload_file' )
# No dataset(s) specified, so display the upload form. Send list of data formats to the form
# so the "extension" select list can be populated dynamically
@@ -1071,6 +1087,11 @@
msg=util.sanitize_text( msg ),
messagetype='error' ) )
current_user_roles = trans.get_current_user_roles()
+ # See if we have any associated templates
+ widgets = []
+ info_association, inherited = library_dataset.library_dataset_dataset_association.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = library_dataset.library_dataset_dataset_association.get_template_widgets( trans )
if params.get( 'edit_attributes_button', False ):
if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ):
if params.get( 'edit_attributes_button', False ):
@@ -1095,6 +1116,9 @@
library_dataset=library_dataset,
library_id=library_id,
current_user_roles=current_user_roles,
+ info_association=info_association,
+ inherited=inherited,
+ widgets=widgets,
show_deleted=show_deleted,
msg=msg,
messagetype=messagetype )
@@ -1280,63 +1304,83 @@
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
messagetype=messagetype ) )
+ def get_item_and_stuff( self, trans, item_type, library_id, folder_id, ldda_id ):
+ # Return an item, description, action and an id based on the item_type.
+ if item_type == 'library':
+ item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
+ item_desc = 'data library'
+ action = 'library_info'
+ id = library_id
+ elif item_type == 'folder':
+ item = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) )
+ item_desc = 'folder'
+ action = 'folder_info'
+ id = folder_id
+ elif item_type == 'ldda':
+ item = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) )
+ item_desc = 'dataset'
+ action = 'ldda_edit_info'
+ id = ldda_id
+ else:
+ msg = "Invalid library item type ( %s )" % str( item_type )
+ return trans.response.send_redirect( web.url_for( controller='library_common',
+ action='browse_library',
+ cntrller=cntrller,
+ id=library_id,
+ show_deleted=show_deleted,
+ msg=util.sanitize_text( msg ),
+ messagetype='error' ) )
+ return item, item_desc, action, id
@web.expose
- def add_info_template( self, trans, cntrller, item_type, library_id, folder_id=None, ldda_id=None, **kwd ):
- # Only adding a new template to a Library, Folder or LibraryDatasetDatasetAssociation is currently allowed. Editing an existing
- # template is a future enhancement.
+ def add_template( self, trans, cntrller, item_type, library_id, folder_id=None, ldda_id=None, **kwd ):
+ # Template can only be added to a Library, Folder or LibraryDatasetDatasetAssociation.
forms = get_all_forms( trans,
filter=dict( deleted=False ),
form_type=trans.app.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE )
if not forms:
- msg = "There are no forms on which to base the template, so create a form and try to add the template again."
+ msg = "There are no forms on which to base the template, so create a form and then add the template."
trans.response.send_redirect( web.url_for( controller='forms',
action='new',
msg=msg,
messagetype='done',
form_type=trans.app.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE ) )
- params = util.Params( kwd )
- show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
- msg = util.restore_text( params.get( 'msg', '' ) )
- action = ''
- messagetype = params.get( 'messagetype', 'done' )
- if item_type == 'library':
- item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
- library_item_desc = 'data library'
- action = 'library_info'
- id = library_id
- elif item_type == 'folder':
- item = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) )
- library_item_desc = 'folder'
- action = 'folder_info'
- id = folder_id
- elif item_type == 'ldda':
- item = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) )
- library_item_desc = 'dataset'
- action = 'ldda_edit_info'
- id = ldda_id
- if params.get( 'add_info_template_button', False ):
- form = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( params.form_id ) )
- form_values = trans.app.model.FormValues( form, [] )
- trans.sa_session.add( form_values )
- trans.sa_session.flush()
- if item_type == 'library':
- assoc = trans.app.model.LibraryInfoAssociation( item, form, form_values )
- elif item_type == 'folder':
- assoc = trans.app.model.LibraryFolderInfoAssociation( item, form, form_values )
- elif item_type == 'ldda':
- assoc = trans.app.model.LibraryDatasetDatasetInfoAssociation( item, form, form_values )
- trans.sa_session.add( assoc )
- trans.sa_session.flush()
- msg = 'A template based on the form "%s" has been added to this %s.' % ( form.name, library_item_desc )
- trans.response.send_redirect( web.url_for( controller='library_common',
- action=action,
- cntrller=cntrller,
- library_id=library_id,
- folder_id=folder_id,
- id=id,
- show_deleted=show_deleted,
- msg=msg,
- messagetype='done' ) )
+ else:
+ params = util.Params( kwd )
+ show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ action = ''
+ messagetype = params.get( 'messagetype', 'done' )
+ item, item_desc, action, id = self.get_item_and_stuff( trans, item_type, library_id, folder_id, ldda_id )
+ # If the inheritable checkbox is checked, the param will be in the request
+ inheritable = CheckboxField.is_checked( params.get( 'inheritable', '' ) )
+ if params.get( 'add_template_button', False ):
+ form_id = params.get( 'form_id', 'none' )
+ if form_id not in [ None, 'None', 'none' ]:
+ form = trans.sa_session.query( trans.app.model.FormDefinition ).get( trans.security.decode_id( form_id ) )
+ form_values = trans.app.model.FormValues( form, [] )
+ trans.sa_session.add( form_values )
+ trans.sa_session.flush()
+ if item_type == 'library':
+ assoc = trans.app.model.LibraryInfoAssociation( item, form, form_values, inheritable=inheritable )
+ elif item_type == 'folder':
+ assoc = trans.app.model.LibraryFolderInfoAssociation( item, form, form_values, inheritable=inheritable )
+ elif item_type == 'ldda':
+ assoc = trans.app.model.LibraryDatasetDatasetInfoAssociation( item, form, form_values )
+ trans.sa_session.add( assoc )
+ trans.sa_session.flush()
+ msg = 'A template based on the form "%s" has been added to this %s.' % ( form.name, item_desc )
+ trans.response.send_redirect( web.url_for( controller='library_common',
+ action=action,
+ cntrller=cntrller,
+ library_id=library_id,
+ folder_id=folder_id,
+ id=id,
+ show_deleted=show_deleted,
+ msg=msg,
+ messagetype='done' ) )
+ else:
+ msg = "Select a form on which to base the template."
+ messagetype = "error"
def generate_template_stuff( trans, forms, form_id ):
# Returns the following:
# - a list of template ids
@@ -1367,10 +1411,10 @@
template_ids, widgets, template_select_list = generate_template_stuff( trans, forms, kwd.get( 'form_id' ) )
else:
template_ids, widgets, template_select_list = generate_template_stuff( trans, forms, 'none' )
- return trans.fill_template( '/library/common/select_info_template.mako',
+ return trans.fill_template( '/library/common/select_template.mako',
cntrller=cntrller,
- library_item_name=item.name,
- library_item_desc=library_item_desc,
+ item_name=item.name,
+ item_desc=item_desc,
item_type=item_type,
library_id=library_id,
folder_id=folder_id,
@@ -1378,37 +1422,85 @@
template_ids=template_ids,
widgets=widgets,
template_select_list=template_select_list,
+ inheritable_checked=inheritable,
show_deleted=show_deleted,
msg=msg,
messagetype=messagetype )
@web.expose
- def edit_template_info( self, trans, cntrller, item_type, library_id, num_widgets, folder_id=None, ldda_id=None, **kwd ):
+ def manage_template_inheritance( self, trans, cntrller, item_type, library_id, folder_id=None, ldda_id=None, **kwd ):
params = util.Params( kwd )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
- if item_type == 'library':
- item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
- action = 'library_info'
- id = library_id
- elif item_type == 'folder':
- item = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) )
- action = 'folder_info'
- id = folder_id
- elif item_type == 'ldda':
- item = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) )
- action = 'ldda_edit_info'
- folder_id = trans.security.encode_id( item.library_dataset.folder.id )
- id = ldda_id
- else:
- msg = "Invalid library item type ( %s ) sent to edit_template_info()" % str( item_type )
+ item, item_desc, action, id = self.get_item_and_stuff( trans, item_type, library_id, folder_id, ldda_id )
+ info_association, inherited = item.get_info_association( restrict=True )
+ if info_association:
+ if info_association.inheritable:
+ msg = "The template for this %s will no longer be inherited to contained folders and datasets." % item_desc
+ else:
+ msg = "The template for this %s will now be inherited to contained folders and datasets." % item_desc
+ info_association.inheritable = not( info_association.inheritable )
+ trans.sa_session.add( info_association )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='library_common',
+ action=action,
+ cntrller=cntrller,
+ library_id=library_id,
+ folder_id=folder_id,
+ id=id,
+ show_deleted=show_deleted,
+ msg=util.sanitize_text( msg ),
+ messagetype='done' ) )
+ @web.expose
+ def edit_template( self, trans, cntrller, item_type, library_id, folder_id=None, ldda_id=None, edited=False, **kwd ):
+ # Edit the template itself, keeping existing field contents, if any.
+ params = util.Params( kwd )
+ show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ item, item_desc, action, id = self.get_item_and_stuff( trans, item_type, library_id, folder_id, ldda_id )
+ # An info_association must exist at this point
+ info_association, inherited = item.get_info_association( restrict=True )
+ template = info_association.template
+ info = info_association.info
+ form_values = trans.sa_session.query( trans.app.model.FormValues ).get( info.id )
+ if edited:
+ # The form on which the template is based has been edited, so we need to update the
+ # info_association with the current form
+ fdc = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( template.form_definition_current_id )
+ info_association.template = fdc.latest_form
+ trans.sa_session.add( info_association )
+ trans.sa_session.flush()
+ msg = "The template for this %s has been updated with your changes." % item_desc
return trans.response.send_redirect( web.url_for( controller='library_common',
- action='browse_library',
+ action=action,
cntrller=cntrller,
- id=library_id,
+ library_id=library_id,
+ folder_id=folder_id,
+ id=id,
show_deleted=show_deleted,
msg=util.sanitize_text( msg ),
- messagetype='error' ) )
+ messagetype='done' ) )
+ # "template" is a FormDefinition, so since we're changing it, we need to use the latest version of it.
+ vars = dict( id=trans.security.encode_id( template.form_definition_current_id ),
+ response_redirect=web.url_for( controller='library_common',
+ action='edit_template',
+ cntrller=cntrller,
+ item_type=item_type,
+ library_id=library_id,
+ folder_id=folder_id,
+ ldda_id=ldda_id,
+ edited=True,
+ **kwd ) )
+ return trans.response.send_redirect( web.url_for( controller='forms', action='edit', **vars ) )
+ @web.expose
+ def edit_template_info( self, trans, cntrller, item_type, library_id, num_widgets, folder_id=None, ldda_id=None, **kwd ):
+ # Edit the contents of the template fields without altering the template itself.
+ params = util.Params( kwd )
+ show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ item, item_desc, action, id = self.get_item_and_stuff( trans, item_type, library_id, folder_id, ldda_id )
# Save updated template field contents
field_contents = []
for index in range( int( num_widgets ) ):
@@ -1439,10 +1531,17 @@
trans.sa_session.flush()
# Create a new info_association between the current library item and form_values
if item_type == 'folder':
- info_association = trans.app.model.LibraryFolderInfoAssociation( item, template, form_values )
+ # A LibraryFolder is a special case because if it inherited the template from it's parent,
+ # we want to set inheritable to True for it's info_association. This allows for the default
+ # inheritance to be False for each level in the Library hierarchy unless we're creating a new
+ # level in the hierarchy, in which case we'll inherit the "inheritable" setting from the parent
+ # level.
+ info_association = trans.app.model.LibraryFolderInfoAssociation( item, template, form_values, inheritable=inherited )
trans.sa_session.add( info_association )
trans.sa_session.flush()
elif item_type == 'ldda':
+ # TODO: Currently info_associations at teh ldda level are not inheritable to the associated LibraryDataset.
+ # We need to figure out if this is optimal.
info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation( item, template, form_values )
trans.sa_session.add( info_association )
trans.sa_session.flush()
@@ -1457,35 +1556,14 @@
msg=util.sanitize_text( msg ),
messagetype='done' ) )
@web.expose
- def delete_info_template( self, trans, cntrller, item_type, library_id, id=None, folder_id=None, ldda_id=None, **kwd ):
+ def delete_template( self, trans, cntrller, item_type, library_id, id=None, folder_id=None, ldda_id=None, **kwd ):
# Only adding a new template to a library or folder is currently allowed. Editing an existing template is
# a future enhancement.
params = util.Params( kwd )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
- if item_type == 'library':
- item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
- action = 'library_info'
- id = library_id
- elif item_type == 'folder':
- item = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) )
- action = 'folder_info'
- id = folder_id
- elif item_type == 'ldda':
- item = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) )
- action = 'ldda_edit_info'
- folder_id = trans.security.encode_id( item.library_dataset.folder.id )
- id = ldda_id
- else:
- msg = "Invalid library item type ( %s ) sent to edit_template_info()" % str( item_type )
- return trans.response.send_redirect( web.url_for( controller='library_common',
- action='browse_library',
- cntrller=cntrller,
- id=library_id,
- show_deleted=show_deleted,
- msg=util.sanitize_text( msg ),
- messagetype='error' ) )
+ item, item_desc, action, id = self.get_item_and_stuff( trans, item_type, library_id, folder_id, ldda_id )
info_association, inherited = item.get_info_association()
if not info_association:
msg = "There is no template for this %s" % item_type
diff -r 4a6bb3b64012 -r a3e6350ffc57 lib/galaxy/web/form_builder.py
--- a/lib/galaxy/web/form_builder.py Thu Feb 11 09:25:29 2010 -0500
+++ b/lib/galaxy/web/form_builder.py Thu Feb 11 14:26:25 2010 -0500
@@ -101,7 +101,9 @@
@staticmethod
def is_checked( value ):
if value == True:
- return value
+ return True
+ if isinstance( value, basestring ) and value.lower() in ( "yes", "true", "on" ):
+ return True
# This may look strange upon initial inspection, but see the comments in the get_html() method
# above for clarification. Basically, if value is not True, then it will always be a list with
# 2 input fields ( a checkbox and a hidden field ) if the checkbox is checked. If it is not
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/admin/forms/edit_form.mako
--- a/templates/admin/forms/edit_form.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/admin/forms/edit_form.mako Thu Feb 11 14:26:25 2010 -0500
@@ -96,7 +96,6 @@
</div>
</div>
</div>
-
</%def>
<%def name="render_layout( index, widget )">
@@ -111,10 +110,18 @@
<div class="toolForm">
<div class="toolFormTitle">Edit form definition "${form.name}"</div>
- <form id="edit_form" name="edit_form" action="${h.url_for( controller='forms', action='manage', operation="Edit", id=trans.security.encode_id(form.current.id) )}" method="post" >
+ <form id="edit_form" name="edit_form" action="${h.url_for( controller='forms', action='edit', id=trans.security.encode_id(form.current.id) )}" method="post" >
+ %if response_redirect:
+ <input type="hidden" name="response_redirect" value="${response_redirect}" size="40" />
+ %endif
%for label, input in form_details:
<div class="form-row">
- <label>${label}</label>
+ ## TODO: RC, this will keep the form type select list label
+ ## from being displayed here. At this point, the select list is a hidden field.
+ ## Make sure this is the best solution to this problem.
+ %if label != 'Type':
+ <label>${label}</label>
+ %endif
<div style="float: left; width: 250px; margin-right: 10px;">
${input.get_html()}
</div>
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/browse_library.mako
--- a/templates/library/common/browse_library.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/browse_library.mako Thu Feb 11 14:26:25 2010 -0500
@@ -158,8 +158,8 @@
if ldda == library_dataset.library_dataset_dataset_association:
current_version = True
if cntrller in [ 'library', 'requests' ]:
- can_modify_library_dataset = trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset )
- can_manage_library_dataset = trans.app.security_agent.can_manage_library_item( current_user_roles, library_dataset )
+ can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset )
+ can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, library_dataset )
else:
current_version = False
if current_version and ldda.state not in ( 'ok', 'error', 'empty', 'deleted', 'discarded' ):
@@ -182,27 +182,28 @@
%if ldda.library_dataset.deleted:
<span class="libraryItem-error">
%endif
- <a href="${h.url_for( controller='library_common', action='ldda_display_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 ), show_deleted=show_deleted )}"><b>${ldda.name[:50]}</b></a>
+ <a 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 ), show_deleted=show_deleted )}"><b>${ldda.name[:50]}</b></a>
%if ldda.library_dataset.deleted:
</span>
%endif
<a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="dataset-${ldda.id}-popup">
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( cntrller in [ 'library_admin', 'requests_admin' ] or can_modify_library_dataset ):
- <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 ), show_deleted=show_deleted )}">Edit this dataset's information</a>
+ %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( cntrller == 'library_admin' or 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 ), show_deleted=show_deleted )}">Edit information</a>
%else:
- <a class="action-button" href="${h.url_for( controller='library_common', action='ldda_display_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 ), show_deleted=show_deleted )}">View this dataset's information</a>
+ <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 ), show_deleted=show_deleted )}">View information</a>
%endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( ( cntrller in [ 'library_admin', 'requests_admin' ] or can_add ) and not info_association ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_info_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Add a template to this dataset</a>
+ %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( ( cntrller == 'library_admin' or 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', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Add template</a>
%endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and cntrller == 'library_admin' and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_info_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Delete this dataset's template</a>
+ %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( ( cntrller == 'library_admin' or can_modify ) and info_association ):
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), 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', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Delete template</a>
%endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( cntrller in [ 'library_admin', 'requests_admin' ] or can_manage_library_dataset ):
- <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 ), show_deleted=show_deleted )}">Edit this dataset's permissions</a>
+ %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( cntrller == 'library_admin' or can_manage ):
+ <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 ), show_deleted=show_deleted )}">Edit permissions</a>
%endif
- %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( cntrller in [ 'library_admin', 'requests_admin' ] or can_modify_library_dataset ):
+ %if not branch_deleted( folder ) and not ldda.library_dataset.deleted and ( cntrller == 'library_admin' or 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:
@@ -211,9 +212,9 @@
%endif
%if cntrller in [ 'library_admin', 'requests_admin' ]:
%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 '${ldda.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), library_item_id=trans.security.encode_id( library_dataset.id ), library_item_type='library_dataset', show_deleted=show_deleted )}">Delete this dataset</a>
+ <a class="action-button" confirm="Click OK to delete dataset '${ldda.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', 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_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), library_item_id=trans.security.encode_id( library_dataset.id ), library_item_type='library_dataset', show_deleted=show_deleted )}">Undelete this dataset</a>
+ <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', 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>
@@ -284,27 +285,28 @@
%endif
<a id="folder_img-${folder.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="folder_img-${folder.id}-popup">
- %if not branch_deleted( folder ) and ( cntrller in [ 'library_admin', 'requests_admin' ] or can_add ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=library_id, folder_id=trans.security.encode_id( folder.id ), show_deleted=show_deleted )}">Add datasets to this folder</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=library_id )}">Create a new sub-folder in this folder</a>
+ %if not branch_deleted( folder ) and ( cntrller == 'library_admin' or can_add ):
+ <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=library_id, folder_id=trans.security.encode_id( folder.id ), 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=library_id )}">Add sub-folder</a>
%endif
- %if not branch_deleted( folder ) and ( cntrller in [ 'library_admin', 'requests_admin' ] or 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=library_id, show_deleted=show_deleted )}">Edit this folder's information</a>
+ %if not branch_deleted( folder ) and ( cntrller == 'library_admin' or 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=library_id, show_deleted=show_deleted )}">Edit information</a>
%endif
- %if not branch_deleted( folder ) and ( ( cntrller in [ 'library_admin', 'requests_admin' ] or can_add ) and not info_association ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_info_template', cntrller=cntrller, item_type='folder', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), show_deleted=show_deleted )}">Add a template to this folder</a>
+ %if not branch_deleted( folder ) and ( ( cntrller == 'library_admin' or 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', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), show_deleted=show_deleted )}">Add template</a>
%endif
- %if not branch_deleted( folder ) and cntrller == 'library_admin' and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_info_template', cntrller=cntrller, item_type='folder', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), show_deleted=show_deleted )}">Delete this folder's template</a>
+ %if not branch_deleted( folder ) and ( ( cntrller == 'library_admin' or can_modify ) and info_association ):
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='folder', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), 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', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), show_deleted=show_deleted )}">Delete template</a>
%endif
- %if not branch_deleted( folder ) and ( cntrller in [ 'library_admin', 'requests_admin' ] or can_manage ):
- <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=library_id, show_deleted=show_deleted )}">Edit this folder's permissions</a>
+ %if not branch_deleted( folder ) and ( cntrller == 'library_admin' or can_manage ):
+ <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=library_id, show_deleted=show_deleted )}">Edit permissions</a>
%endif
%if cntrller in [ 'library_admin', 'requests_admin' ]:
%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_admin', action='delete_library_item', library_id=library_id, library_item_id=trans.security.encode_id( folder.id ), library_item_type='folder', show_deleted=show_deleted )}">Delete this folder and its contents</a>
+ <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_admin', action='delete_library_item', library_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_admin', action='undelete_library_item', library_id=library_id, library_item_id=trans.security.encode_id( folder.id ), library_item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a>
+ <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_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>
@@ -376,22 +378,19 @@
%if not library.deleted:
%if cntrller == 'library_admin' or 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 ), show_deleted=show_deleted )}">Edit information</a>
- ## Editing templates disabled until we determine optimal approach to re-linking library item to new version of form definition
- ##%if library.info_association:
- ## <% form_id = library.info_association[0].template.id %>
- ## <a class="action-button" href="${h.url_for( controller='forms', action='edit', form_id=form_id, show_form=True )}">Edit template</a>
%endif
- %if ( cntrller == 'library_admin' or can_add ) and not library.info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_info_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Add template</a>
+ %if ( cntrller == 'library_admin' or 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', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Add template</a>
%endif
- %if cntrller == 'library_admin' and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_info_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Delete template</a>
+ %if ( cntrller == 'library_admin' or can_modify ) and info_association:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), 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', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Delete template</a>
%endif
%if cntrller == 'library_admin' or can_manage:
<a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Edit permissions</a>
%endif
%if cntrller == 'library_admin':
- <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), library_item_id=trans.security.encode_id( library.id ), library_item_type='library' )}">Delete this data library and its contents</a>
+ <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
%endif
%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 ), show_deleted=False )}">Hide deleted items</a>
@@ -399,7 +398,9 @@
<a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=True )}">Show deleted items</a>
%endif
%elif cntrller == 'library_admin' and not library.purged:
- <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), library_item_id=trans.security.encode_id( library.id ), library_item_type='library' )}">Undelete this data library</a>
+ <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">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 ), show_deleted=show_deleted )}">This data library has been purged</a>
%endif
</div>
</th>
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/common.mako
--- a/templates/library/common/common.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/common.mako Thu Feb 11 14:26:25 2010 -0500
@@ -1,4 +1,4 @@
-<%def name="render_template_info( cntrller, item_type, library_id, widgets, folder_id=None, ldda_id=None, editable=True )">
+<%def name="render_template_info( cntrller, item_type, library_id, widgets, info_association, inherited, folder_id=None, ldda_id=None, editable=True )">
<%
if item_type == 'library':
item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
@@ -8,12 +8,35 @@
item = trans.sa_session.query( trans.app.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( ldda_id ) )
if cntrller == 'library':
current_user_roles = trans.get_current_user_roles()
+ can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, item )
%>
%if widgets:
- %if editable and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, item ) ):
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Other information about ${item.name}</div>
+ <p/>
+ <div class="toolForm">
+ %if editable and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, item ) ):
+ <div class="toolFormTitle">
+ %if inherited:
+ Other information <i>- this is an inherited template and is not required to be used with this ${item_type}</i>
+ %else:
+ Other information
+ %endif
+ %if info_association and not inherited and ( cntrller == 'library_admin' or can_modify ):
+ ## "inherited" will be true only if the info_association is not associated with the current item,
+ ## in which case we do not want to render the following popup menu.
+ <a id="item-${item.id}-popup" class="popup-arrow" style="display: none;">▼</a>
+ <div popupmenu="item-${item.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, 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=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Delete template</a>
+ %if item_type not in [ 'ldda', 'library_dataset' ]:
+ %if info_association.inheritable:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='manage_template_inheritance', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Dis-inherit template</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='manage_template_inheritance', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Inherit template</a>
+ %endif
+ %endif
+ </div>
+ %endif
+ </div>
<div class="toolFormBody">
<form name="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, num_widgets=len( widgets ), folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post">
%for i, field in enumerate( widgets ):
@@ -31,36 +54,36 @@
</div>
</form>
</div>
- </div>
- %else:
- <% contents = False %>
- %for i, field in enumerate( widgets ):
- %if field[ 'widget' ].value:
- <%
- contents = True
- break
- %>
+ %else:
+ <% contents = False %>
+ %for i, field in enumerate( widgets ):
+ %if field[ 'widget' ].value:
+ <%
+ contents = True
+ break
+ %>
+ %endif
+ %endfor
+ %if contents:
+ <div class="toolForm">
+ <div class="toolFormTitle">Other information about ${item.name}</div>
+ <div class="toolFormBody">
+ %for i, field in enumerate( widgets ):
+ %if field[ 'widget' ].value:
+ <div class="form-row">
+ <label>${field[ 'label' ]}</label>
+ <pre>${field[ 'widget' ].value}</pre>
+ <div class="toolParamHelp" style="clear: both;">
+ ${field[ 'helptext' ]}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endif
+ %endfor
+ </div>
%endif
- %endfor
- %if contents:
- <div class="toolForm">
- <div class="toolFormTitle">Other information about ${item.name}</div>
- <div class="toolFormBody">
- %for i, field in enumerate( widgets ):
- %if field[ 'widget' ].value:
- <div class="form-row">
- <label>${field[ 'label' ]}</label>
- <pre>${field[ 'widget' ].value}</pre>
- <div class="toolParamHelp" style="clear: both;">
- ${field[ 'helptext' ]}
- </div>
- <div style="clear: both"></div>
- </div>
- %endif
- %endfor
- </div>
%endif
- %endif
+ </div>
%endif
</%def>
@@ -85,7 +108,7 @@
%if replace_dataset not in [ None, 'None' ]:
<input type="hidden" name="replace_id" value="${trans.security.encode_id( replace_dataset.id )}"/>
<div class="form-row">
- You are currently selecting a new file to replace '<a href="${h.url_for( controller='library_common', action='ldda_display_info', cntrller=cntrller, library_id=library_id, folder_id=folder_id, id=trans.security.encode_id( replace_dataset.library_dataset_dataset_association.id ) )}">${replace_dataset.name}</a>'.
+ You are currently selecting a new file to replace '<a href="${h.url_for( controller='library_common', action='ldda_info', cntrller=cntrller, library_id=library_id, folder_id=folder_id, id=trans.security.encode_id( replace_dataset.library_dataset_dataset_association.id ) )}">${replace_dataset.name}</a>'.
<div style="clear: both"></div>
</div>
%endif
@@ -277,7 +300,10 @@
${field[ 'widget' ].get_html()}
</div>
<div class="toolParamHelp" style="clear: both;">
- ${field[ 'helptext' ]}, leave blank to add a different template to this dataset after upload.
+ %if field[ 'helptext' ]:
+ ${field[ 'helptext' ]}<br/>
+ %endif
+ *Inherited template field
</div>
<div style="clear: both"></div>
</div>
@@ -307,7 +333,7 @@
%if replace_dataset not in [ None, 'None' ]:
<input type="hidden" name="replace_id" value="${trans.security.encode_id( replace_dataset.id )}"/>
<div class="form-row">
- You are currently selecting a new file to replace '<a href="${h.url_for( controller='library_common', action='ldda_display_info', cntrller=cntrller, library_id=library_id, folder_id=folder_id, id=trans.security.encode_id( replace_dataset.library_dataset_dataset_association.id ) )}">${replace_dataset.name}</a>'.
+ You are currently selecting a new file to replace '<a href="${h.url_for( controller='library_common', action='ldda_info', cntrller=cntrller, library_id=library_id, folder_id=folder_id, id=trans.security.encode_id( replace_dataset.library_dataset_dataset_association.id ) )}">${replace_dataset.name}</a>'.
<div style="clear: both"></div>
</div>
%endif
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/edit_template.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/library/common/edit_template.mako Thu Feb 11 14:26:25 2010 -0500
@@ -0,0 +1,35 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=library_id, show_deleted=show_deleted )}"><span>Browse this data library</span></a>
+ </li>
+</ul>
+
+%if msg:
+ ${render_msg( msg, messagetype )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Edit the template for the ${item_desc} '${item_name}'</div>
+ <form id="edit_template" name="edit_template" action="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post" >
+ <div class="toolFormBody">
+ %for i, field in enumerate( widgets ):
+ <div class="form-row">
+ <label>${field[ 'label' ]}</label>
+ ${field[ 'widget' ].get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ ${field[ 'helptext' ]}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endfor
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <input type="submit" name="edit_template_button" value="Save"/>
+ </div>
+ </div>
+ </form>
+</div>
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/folder_info.mako
--- a/templates/library/common/folder_info.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/folder_info.mako Thu Feb 11 14:26:25 2010 -0500
@@ -47,5 +47,5 @@
</div>
</div>
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='folder', library_id=library_id, widgets=widgets, folder_id=trans.security.encode_id( folder.id ) )}
+ ${render_template_info( cntrller=cntrller, item_type='folder', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( folder.id ) )}
%endif
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/ldda_edit_info.mako
--- a/templates/library/common/ldda_edit_info.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/ldda_edit_info.mako Thu Feb 11 14:26:25 2010 -0500
@@ -161,5 +161,5 @@
</div>
%endif
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ) )}
+ ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ) )}
%endif
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/ldda_info.mako
--- a/templates/library/common/ldda_info.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/ldda_info.mako Thu Feb 11 14:26:25 2010 -0500
@@ -13,7 +13,9 @@
uploaded_by = ldda.user.email
else:
uploaded_by = 'anonymous'
- info_association, inherited = ldda.get_info_association( restrict=True )
+ if cntrller in [ 'library', 'requests' ]:
+ can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, ldda.library_dataset )
+ can_manage = trans.app.security_agent.can_manage_library_item( current_user_roles, ldda.library_dataset )
%>
%if current_version:
@@ -39,18 +41,19 @@
%if not library.deleted and not branch_deleted( ldda.library_dataset.folder ) and not ldda.library_dataset.deleted:
<a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="dataset-${ldda.id}-popup">
- %if cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda.library_dataset ):
- <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( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Edit this dataset's information</a>
+ %if cntrller=='library_admin' or 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( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Edit information</a>
%if not info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_info_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Add a template to this dataset</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Add template</a>
%else:
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_info_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Delete this dataset's template</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='ldda', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), 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', library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Delete template</a>
%endif
%endif
- %if cntrller=='library_admin' or trans.app.security_agent.can_manage_dataset( current_user_roles, ldda.dataset ) and trans.app.security_agent.can_manage_library_item( current_user_roles, ldda.library_dataset ):
- <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( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Edit this dataset's permissions</a>
+ %if cntrller=='library_admin' or can_manage:
+ <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( ldda.library_dataset.folder.id ), id=trans.security.encode_id( ldda.id ), show_deleted=show_deleted )}">Edit permissions</a>
%endif
- %if current_version and ( cntrller=='library_admin' or trans.app.security_agent.can_modify_library_item( current_user_roles, ldda.library_dataset ) ):
+ %if current_version and ( cntrller=='library_admin' or 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( ldda.library_dataset.folder.id ), replace_id=trans.security.encode_id( ldda.library_dataset.id ), show_deleted=show_deleted )}">Upload a new version of this dataset</a>
%endif
%if cntrller=='library' and ldda.has_data:
@@ -100,7 +103,7 @@
</div>
</div>
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), editable=False )}
+ ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), editable=False )}
%endif
%if current_version:
<% expired_lddas = [ e_ldda for e_ldda in ldda.library_dataset.expired_datasets ] %>
@@ -108,7 +111,7 @@
<div class="toolFormTitle">Expired versions of ${ldda.name}</div>
%for expired_ldda in expired_lddas:
<div class="form-row">
- <a href="${h.url_for( controller='library_common', action='ldda_display_info', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( expired_ldda.library_dataset.folder.id ), id=trans.security.encode_id( expired_ldda.id ), show_deleted=show_deleted )}">${expired_ldda.name}</a>
+ <a 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( expired_ldda.library_dataset.folder.id ), id=trans.security.encode_id( expired_ldda.id ), show_deleted=show_deleted )}">${expired_ldda.name}</a>
</div>
%endfor
%endif
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/library_dataset_info.mako
--- a/templates/library/common/library_dataset_info.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/library_dataset_info.mako Thu Feb 11 14:26:25 2010 -0500
@@ -62,5 +62,6 @@
%endif
%if widgets:
- ${render_template_info( cntrller, library_dataset, library_id, '', widgets )}
+ ## Templates are not currently supported for library_datasets, only the associated ldda.
+ ${render_template_info( cntrller, 'library_dataset', library_id, widgets, info_association=None, inherited=False, editable=False )}
%endif
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/library_info.mako
--- a/templates/library/common/library_info.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/library_info.mako Thu Feb 11 14:26:25 2010 -0500
@@ -7,7 +7,6 @@
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 )
- info_association, inherited = library.get_info_association()
%>
<br/><br/>
@@ -21,10 +20,32 @@
${render_msg( msg, messagetype )}
%endif
-%if cntrller == 'library_admin' or can_modify:
- <div class="toolForm">
- <div class="toolFormTitle">Change library name and description</div>
- <div class="toolFormBody">
+<div class="toolForm">
+ %if cntrller == 'library_admin' or can_add or can_modify or can_manage:
+ <div class="toolFormTitle">
+ <a href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}"><b>${library.name[:50]}</b></a>
+ <a id="library-${library.id}-popup" class="popup-arrow" style="display: none;">▼</a>
+ <div popupmenu="library-${library.id}-popup">
+ %if not library.deleted:
+ %if ( cntrller == 'library_admin' or can_add ) and not library.info_association:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Add template</a>
+ %endif
+ %if cntrller == 'library_admin' or can_manage:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Edit permissions</a>
+ %endif
+ %if cntrller == 'library_admin':
+ <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">Delete this data library</a>
+ %endif
+ %elif cntrller == 'library_admin' and not library.purged:
+ <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( library.id ), item_type='library' )}">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 ), show_deleted=show_deleted )}">This data library has been purged</a>
+ %endif
+ </div>
+ </div>
+ %endif
+ <div class="toolFormBody">
+ %if not library.deleted and ( cntrller == 'library_admin' or can_modify ):
<form name="library" action="${h.url_for( controller='library_common', action='library_info', id=trans.security.encode_id( library.id ), cntrller=cntrller, show_deleted=show_deleted )}" method="post" >
<div class="form-row">
<label>Name:</label>
@@ -44,42 +65,7 @@
<input type="submit" name="rename_library_button" value="Save"/>
</div>
</form>
- </div>
- </div>
- <p/>
-%else:
- <div class="toolForm">
- <div class="toolFormTitle">
- %if cntrller == 'library_admin' or can_add or can_manage:
- <th style="padding-left: 42px;">
- <a href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}"><b>${library.name[:50]}</b></a>
- <a id="library-${library.id}-popup" class="popup-arrow" style="display: none;">▼</a>
- <div popupmenu="library-${library.id}-popup">
- %if not library.deleted:
- %if ( cntrller == 'library_admin' or can_add ) and not library.info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_info_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Add template</a>
- %endif
- %if cntrller == 'library_admin' and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_info_template', cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Delete template</a>
- %endif
- %if cntrller == 'library_admin' or can_manage:
- <a class="action-button" href="${h.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}">Edit permissions</a>
- %endif
- %if cntrller == 'library_admin':
- <a class="action-button" confirm="Click OK to delete the library named '${library.name}'." href="${h.url_for( controller='library_admin', action='delete_library_item', library_id=trans.security.encode_id( library.id ), library_item_id=trans.security.encode_id( library.id ), library_item_type='library' )}">Delete this data library and its contents</a>
- %endif
- %elif cntrller == 'library_admin' and not library.purged:
- <a class="action-button" href="${h.url_for( controller='library_admin', action='undelete_library_item', library_id=trans.security.encode_id( library.id ), library_item_id=trans.security.encode_id( library.id ), library_item_type='library' )}">Undelete this data library</a>
- %endif
- </div>
- </th>
- %else:
- <th style="padding-left: 42px;">
- <a href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=trans.security.encode_id( library.id ), show_deleted=show_deleted )}"><b>${library.name[:50]}</b></a>
- </th>
- %endif
- </div>
- <div class="toolFormBody">
+ %else:
<div class="form-row">
<label>Name:</label>
${library.name}
@@ -90,10 +76,10 @@
${library.description}
</div>
<div style="clear: both"></div>
- </div>
+ %endif
</div>
-%endif
+</div>
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), widgets=widgets )}
+ ${render_template_info( cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), widgets=widgets, info_association=info_association, inherited=inherited, editable=not( library.deleted ) )}
%endif
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/new_folder.mako
--- a/templates/library/common/new_folder.mako Thu Feb 11 09:25:29 2010 -0500
+++ b/templates/library/common/new_folder.mako Thu Feb 11 14:26:25 2010 -0500
@@ -1,5 +1,6 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/library/common/common.mako" import="render_template_info" />
<br/<br/>
<ul class="manage-table-actions">
@@ -31,12 +32,6 @@
<div style="clear: both"></div>
</div>
<div class="form-row">
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="hidden" name="new" value="submitted" size="40"/>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
<input type="submit" name="new_folder_button" value="Create"/>
</div>
</form>
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/select_info_template.mako
--- a/templates/library/common/select_info_template.mako Thu Feb 11 09:25:29 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<script type="text/javascript">
-$( function() {
- $( "select[refresh_on_change='true']").change( function() {
- var refresh = false;
- var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
- if ( refresh_on_change_values ) {
- refresh_on_change_values = refresh_on_change_values.value.split( ',' );
- var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
- for( i= 0; i < refresh_on_change_values.length; i++ ) {
- if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
- refresh = true;
- break;
- }
- }
- }
- else {
- refresh = true;
- }
- if ( refresh ){
- $( "#select_info_template" ).submit();
- }
- });
-});
-</script>
-
-<br/><br/>
-<ul class="manage-table-actions">
- <li>
- <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=library_id, show_deleted=show_deleted )}"><span>Browse this data library</span></a>
- </li>
-</ul>
-
-%if msg:
- ${render_msg( msg, messagetype )}
-%endif
-
-<div class="toolForm">
- <div class="toolFormTitle">Select a template for the ${library_item_desc} '${library_item_name}'</div>
- <form id="select_info_template" name="select_info_template" action="${h.url_for( controller='library_common', action='add_info_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post" >
- <div class="toolFormBody">
- <table class="grid">
- <tr>
- <div class="form-row">
- <td>
- <input type="hidden" name="refresh" value="true" size="40"/>
- <label>Template:</label>
- ${template_select_list.get_html()}
- </td>
- <td>
- <input type="submit" name="add_info_template_button" value="Add template to ${library_item_desc}"/>
- </td>
- </div>
- </tr>
- </table>
- %if template_select_list.get_selected() != ('Select one', 'none'):
- <div style="clear: both"></div>
- <div class="form-row">
- %for i, field in enumerate( widgets ):
- <div class="form-row">
- <label>${field[ 'label' ]}</label>
- ${field[ 'widget' ].get_html()}
- <div class="toolParamHelp" style="clear: both;">
- ${field[ 'helptext' ]}
- </div>
- <div style="clear: both"></div>
- </div>
- %endfor
- </div>
- %endif
- </div>
- </form>
-</div>
diff -r 4a6bb3b64012 -r a3e6350ffc57 templates/library/common/select_template.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/library/common/select_template.mako Thu Feb 11 14:26:25 2010 -0500
@@ -0,0 +1,82 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<script type="text/javascript">
+$( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#select_template" ).submit();
+ }
+ });
+});
+</script>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller=cntrller, id=library_id, show_deleted=show_deleted )}"><span>Browse this data library</span></a>
+ </li>
+</ul>
+
+%if msg:
+ ${render_msg( msg, messagetype )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Select a template for the ${item_desc} '${item_name}'</div>
+ <div class="toolFormBody">
+ <form id="select_template" name="select_template" action="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post" >
+ <div class="form-row">
+ <input type="hidden" name="refresh" value="true" size="40"/>
+ <label>Template:</label>
+ ${template_select_list.get_html()}
+ </div>
+ % if item_type in [ 'library', 'folder' ]:
+ <div class="form-row">
+ <label>Inherit template to contained folders and datasets?</label>
+ %if inheritable_checked:
+ <input type="checkbox" name="inheritable" value="yes" checked/>Yes
+ %else:
+ <input type="checkbox" name="inheritable" value="yes"/>Yes
+ %endif
+ <div class="toolParamHelp" style="clear: both;">
+ Check if you want this template to be used by other folders and datasets contained within this ${item_desc}
+ </div>
+ </div>
+ %endif
+ <div class="form-row">
+ <input type="submit" name="add_template_button" value="Add template to ${item_desc}"/>
+ </div>
+ </form>
+ %if template_select_list.get_selected() != ('Select one', 'none'):
+ <div style="clear: both"></div>
+ <div class="form-row">
+ %for i, field in enumerate( widgets ):
+ <div class="form-row">
+ <label>${field[ 'label' ]}</label>
+ ${field[ 'widget' ].get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ ${field[ 'helptext' ]}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endfor
+ </div>
+ %endif
+ </div>
+</div>
diff -r 4a6bb3b64012 -r a3e6350ffc57 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Thu Feb 11 09:25:29 2010 -0500
+++ b/test/base/twilltestcase.py Thu Feb 11 14:26:25 2010 -0500
@@ -1384,7 +1384,7 @@
"""Rename a library"""
self.home()
self.visit_url( "%s/library_common/library_info?id=%s&cntrller=%s" % ( self.url, library_id, controller ) )
- self.check_page_for_string( 'Change library name and description' )
+ self.check_page_for_string( old_name )
# Since twill barfs on the form submisson, we ar forced to simulate it
url = "%s/library_common/library_info?id=%s&cntrller=%s&rename_library_button=Save&description=%s&name=%s" % \
( self.url, library_id, controller, description.replace( ' ', '+' ), name.replace( ' ', '+' ) )
@@ -1393,19 +1393,20 @@
check_str = "Library '%s' has been renamed to '%s'" % ( old_name, name )
self.check_page_for_string( check_str )
self.home()
- def add_info_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ):
+ def add_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ):
"""Add a new info template to a library item"""
self.home()
if item_type == 'library':
- url = "%s/library_common/add_info_template?cntrller=%s&item_type=%s&library_id=%s" % ( self.url, cntrller, item_type, library_id )
+ url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s" % ( self.url, cntrller, item_type, library_id )
elif item_type == 'folder':
- url = "%s/library_common/add_info_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s" % ( self.url, cntrller, item_type, library_id, folder_id )
+ url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s" % ( self.url, cntrller, item_type, library_id, folder_id )
elif item_type == 'ldda':
- url = "%s/library_common/add_info_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s&ldda_id=%s" % ( self.url, cntrller, item_type, library_id, folder_id, ldda_id )
+ url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s&ldda_id=%s" % ( self.url, cntrller, item_type, library_id, folder_id, ldda_id )
self.visit_url( url )
self.check_page_for_string ( "Select a template for the" )
tc.fv( '1', 'form_id', form_id )
- tc.submit( 'add_info_template_button' )
+ tc.fv( '1', 'inherit', '1' )
+ tc.submit( 'add_template_button' )
self.check_page_for_string = 'A template based on the form "%s" has been added to this' % form_name
self.home()
def library_info( self, library_id, library_name, ele_1_field_name, ele_1_contents, ele_2_field_name, ele_2_contents, controller='library_admin' ):
@@ -1670,28 +1671,28 @@
errmsg += 'Unpacked archive remains in: %s\n' % tmpd
raise AssertionError( errmsg )
shutil.rmtree( tmpd )
- def delete_library_item( self, library_id, library_item_id, library_item_name, library_item_type='library_dataset' ):
+ def delete_library_item( self, library_id, item_id, item_name, item_type='library_dataset' ):
"""Mark a library item as deleted"""
self.home()
- self.visit_url( "%s/library_admin/delete_library_item?library_id=%s&library_item_id=%s&library_item_type=%s" \
- % ( self.url, library_id, library_item_id, library_item_type ) )
- if library_item_type == 'library_dataset':
- library_item_desc = 'Dataset'
+ self.visit_url( "%s/library_admin/delete_library_item?library_id=%s&item_id=%s&item_type=%s" \
+ % ( self.url, library_id, item_id, item_type ) )
+ if item_type == 'library_dataset':
+ item_desc = 'Dataset'
else:
- library_item_desc = library_item_type.capitalize()
- check_str = "%s '%s' has been marked deleted" % ( library_item_desc, library_item_name )
+ item_desc = item_type.capitalize()
+ check_str = "%s '%s' has been marked deleted" % ( item_desc, item_name )
self.check_page_for_string( check_str )
self.home()
- def undelete_library_item( self, library_id, library_item_id, library_item_name, library_item_type='library_dataset' ):
+ def undelete_library_item( self, library_id, item_id, item_name, item_type='library_dataset' ):
"""Mark a library item as deleted"""
self.home()
- self.visit_url( "%s/library_admin/undelete_library_item?library_id=%s&library_item_id=%s&library_item_type=%s" \
- % ( self.url, library_id, library_item_id, library_item_type ) )
- if library_item_type == 'library_dataset':
- library_item_desc = 'Dataset'
+ self.visit_url( "%s/library_admin/undelete_library_item?library_id=%s&item_id=%s&item_type=%s" \
+ % ( self.url, library_id, item_id, item_type ) )
+ if item_type == 'library_dataset':
+ item_desc = 'Dataset'
else:
- library_item_desc = library_item_type.capitalize()
- check_str = "%s '%s' has been marked undeleted" % ( library_item_desc, library_item_name )
+ item_desc = item_type.capitalize()
+ check_str = "%s '%s' has been marked undeleted" % ( item_desc, item_name )
self.check_page_for_string( check_str )
self.home()
def purge_library( self, library_id, library_name ):
diff -r 4a6bb3b64012 -r a3e6350ffc57 test/functional/test_security_and_libraries.py
--- a/test/functional/test_security_and_libraries.py Thu Feb 11 09:25:29 2010 -0500
+++ b/test/functional/test_security_and_libraries.py Thu Feb 11 14:26:25 2010 -0500
@@ -579,11 +579,11 @@
assert form_one is not None, 'Problem retrieving form named (%s) from the database' % form_name
# Add a new information template to the library
template_name = 'Library Template 1'
- self.add_info_template( 'library_admin',
- 'library',
- self.security.encode_id( library_one.id ),
- self.security.encode_id( form_one.id ),
- form_one.name )
+ self.add_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( form_one.id ),
+ form_one.name )
# Make sure the template fields are displayed on the library information page
field_dict = form_one.fields[ 0 ]
global form_one_field_label
@@ -1327,7 +1327,7 @@
raise AssertionError( 'ldda.dataset "%s" actions "%s" != ldda.dataset "%s" actions "%s"' \
% ( ldda_six.name, str( ldda_six.dataset.actions ), ldda_six_version_two.name, str( ldda_six_version_two.dataset.actions ) ) )
# Check the previous version
- self.visit_url( "%s/library_common/ldda_display_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
+ self.visit_url( "%s/library_common/ldda_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
( self.url, self.security.encode_id( library_one.id ), self.security.encode_id( subfolder_one.id ), self.security.encode_id( ldda_six.id ) ) )
self.check_page_for_string( 'This is an expired version of this library dataset' )
self.home()
@@ -1378,7 +1378,7 @@
tc.submit( 'edit_info_button' )
self.check_page_for_string( 'The information has been updated.' )
self.check_page_for_string( template_contents )
- self.visit_url( "%s/library_common/ldda_display_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
+ self.visit_url( "%s/library_common/ldda_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
( self.url, self.security.encode_id( library_one.id ), self.security.encode_id( subfolder_one.id ), self.security.encode_id( ldda_six_version_five.id ) ) )
check_str = 'Expired versions of %s' % ldda_six_version_five.name
self.check_page_for_string( check_str )
@@ -1396,7 +1396,7 @@
raise AssertionError( 'ldda.dataset "%s" actions "%s" != ldda.dataset "%s" actions "%s"' \
% ( ldda_six.name, str( ldda_six.dataset.actions ), ldda_six_version_five.name, str( ldda_six_version_five.dataset.actions ) ) )
# Check the previous version
- self.visit_url( "%s/library_common/ldda_display_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
+ self.visit_url( "%s/library_common/ldda_info?cntrller=library_admin&library_id=%s&folder_id=%s&id=%s" % \
( self.url, self.security.encode_id( library_one.id ), self.security.encode_id( subfolder_one.id ), self.security.encode_id( ldda_six_version_two.id ) ) )
self.check_page_for_string( 'This is an expired version of this library dataset' )
self.home()
@@ -1631,7 +1631,7 @@
self.delete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( ldda_two.library_dataset.id ),
ldda_two.name,
- library_item_type='library_dataset' )
+ item_type='library_dataset' )
self.home()
self.visit_page( 'library_common/browse_library?cntrller=library_admin&id=%s' % ( self.security.encode_id( library_one.id ) ) )
try:
@@ -1668,7 +1668,7 @@
self.delete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( folder_two.id ),
folder_two.name,
- library_item_type='folder' )
+ item_type='folder' )
self.home()
self.visit_page( 'library_common/browse_library?cntrller=library_admin&id=%s' % ( self.security.encode_id( library_one.id ) ) )
try:
@@ -1684,7 +1684,7 @@
self.undelete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( folder_two.id ),
folder_two.name,
- library_item_type='folder' )
+ item_type='folder' )
self.home()
self.visit_page( 'library_common/browse_library?cntrller=library_admin&id=%s' % ( self.security.encode_id( library_one.id ) ) )
self.check_page_for_string( folder_two.name )
@@ -1704,11 +1704,11 @@
self.delete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( folder_two.id ),
folder_two.name,
- library_item_type='folder' )
+ item_type='folder' )
self.delete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( library_one.id ),
library_one.name,
- library_item_type='library' )
+ item_type='library' )
self.home()
self.visit_page( 'library_admin/browse_libraries?sort=name&f-description=All&f-name=All&f-deleted=False' )
try:
@@ -1727,7 +1727,7 @@
self.undelete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( library_one.id ),
library_one.name,
- library_item_type='library' )
+ item_type='library' )
self.home()
self.visit_page( 'library_admin/browse_libraries?sort=name&f-description=All&f-name=All&f-deleted=False' )
self.check_page_for_string( library_one.name )
@@ -1854,7 +1854,7 @@
self.delete_library_item( self.security.encode_id( library_one.id ),
self.security.encode_id( library_one.id ),
library_one.name,
- library_item_type='library' )
+ item_type='library' )
self.purge_library( self.security.encode_id( library_one.id ), library_one.name )
# Make sure the library was purged
sa_session.refresh( library_one )
@@ -1928,7 +1928,7 @@
self.delete_library_item( self.security.encode_id( library_two.id ),
self.security.encode_id( library_two.id ),
library_two.name,
- library_item_type='library' )
+ item_type='library' )
self.purge_library( self.security.encode_id( library_two.id ), library_two.name )
self.home()
def test_260_library_permissions( self ):
@@ -1995,12 +1995,12 @@
.first()
# Add an information template to the folder
template_name = 'Folder Template 1'
- self.add_info_template( 'library',
- 'folder',
- self.security.encode_id( library_one.id ),
- self.security.encode_id( form_one.id ),
- form_one.name,
- folder_id=self.security.encode_id( folder_x.id ) )
+ self.add_template( 'library',
+ 'folder',
+ self.security.encode_id( library_one.id ),
+ self.security.encode_id( form_one.id ),
+ form_one.name,
+ folder_id=self.security.encode_id( folder_x.id ) )
# Modify the folder's information
contents = '%s folder contents' % form_one_field_label
new_name = "Root Folder's Folder Y"
@@ -2038,11 +2038,11 @@
assert ldda_x is not None, 'Problem retrieving ldda_x from the database'
# Add an information template to the library
template_name = 'Library Template 3'
- self.add_info_template( 'library',
- 'library',
- self.security.encode_id( library_three.id ),
- self.security.encode_id( form_one.id ),
- form_one.name )
+ self.add_template( 'library',
+ 'library',
+ self.security.encode_id( library_three.id ),
+ self.security.encode_id( form_one.id ),
+ form_one.name )
# Add information to the library using the template
contents = '%s library contents' % form_one_field_label
self.visit_url( '%s/library_common/library_info?cntrller=library&id=%s' % ( self.url, self.security.encode_id( library_three.id ) ) )
@@ -2069,7 +2069,7 @@
self.delete_library_item( self.security.encode_id( library_three.id ),
self.security.encode_id( library_three.id ),
library_three.name,
- library_item_type='library' )
+ item_type='library' )
self.purge_library( self.security.encode_id( library_three.id ), library_three.name )
##################
# Eliminate all non-private roles
1
0
11 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/4a6bb3b64012
changeset: 3372:4a6bb3b64012
user: rc
date: Thu Feb 11 09:25:29 2010 -0500
description:
fixed the 0037_sample_library migration script to work with sqlite
diffstat:
lib/galaxy/model/migrate/versions/0037_samples_library.py | 89 +++++++++-----
scripts/galaxy_messaging/server/data_transfer.py | 4 +-
2 files changed, 59 insertions(+), 34 deletions(-)
diffs (149 lines):
diff -r 29ece93d429c -r 4a6bb3b64012 lib/galaxy/model/migrate/versions/0037_samples_library.py
--- a/lib/galaxy/model/migrate/versions/0037_samples_library.py Wed Feb 10 18:25:32 2010 -0500
+++ b/lib/galaxy/model/migrate/versions/0037_samples_library.py Thu Feb 11 09:25:29 2010 -0500
@@ -11,6 +11,8 @@
import sys, logging
from galaxy.model.custom_types import *
from sqlalchemy.exc import *
+import datetime
+now = datetime.datetime.utcnow
log = logging.getLogger( __name__ )
log.setLevel(logging.DEBUG)
@@ -21,7 +23,7 @@
log.addHandler( handler )
metadata = MetaData( migrate_engine )
-
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
def upgrade():
print __doc__
@@ -48,16 +50,58 @@
Request_table = None
log.debug( "Failed loading table request" )
if Request_table:
- # Delete the library_id column in 'request' table
- try:
- Request_table.c.library_id.drop()
- except Exception, e:
- log.debug( "Deleting column 'library_id' to request table failed: %s" % ( str( e ) ) )
- # Delete the folder_id column in 'request' table
- try:
- Request_table.c.folder_id.drop()
- except Exception, e:
- log.debug( "Deleting column 'folder_id' to request table failed: %s" % ( str( e ) ) )
+ # Delete library_id & folder_id columns in the table 'request'.
+ # if Galaxy is running on sqlite, the delete/recreate the table
+ # otherwise remove the specific columns
+ if migrate_engine.name == 'sqlite':
+ # create a temporary table
+ RequestTemp_table = Table( 'request_temp', metadata,
+ Column( "id", Integer, primary_key=True),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "name", TrimmedString( 255 ), nullable=False ),
+ Column( "desc", TEXT ),
+ Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
+ Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+ try:
+ RequestTemp_table.create()
+ except Exception, e:
+ log.debug( "Creating request_temp table failed: %s" % str( e ) )
+ # insert all the rows from the request table to the request_temp table
+ cmd = \
+ "INSERT INTO request_temp " + \
+ "SELECT id," + \
+ "create_time," + \
+ "update_time," + \
+ "name," + \
+ "desc," + \
+ "form_values_id," + \
+ "request_type_id," + \
+ "user_id," + \
+ "deleted " + \
+ "FROM request;"
+ db_session.execute( cmd )
+ # delete the 'request' table
+ try:
+ Request_table.drop()
+ except Exception, e:
+ log.debug( "Dropping request table failed: %s" % str( e ) )
+ # rename table request_temp to request
+ cmd = "ALTER TABLE request_temp RENAME TO request"
+ db_session.execute( cmd )
+ else:
+ # Delete the library_id column in 'request' table
+ try:
+ Request_table.c.library_id.drop()
+ except Exception, e:
+ log.debug( "Deleting column 'library_id' to request table failed: %s" % ( str( e ) ) )
+ # Delete the folder_id column in 'request' table
+ try:
+ Request_table.c.folder_id.drop()
+ except Exception, e:
+ log.debug( "Deleting column 'folder_id' to request table failed: %s" % ( str( e ) ) )
# sample table
try:
Sample_table = Table( "sample", metadata, autoload=True )
@@ -81,20 +125,11 @@
if Library_table:
# Add the library_id column in 'sample' table
try:
- col = Column( "library_id", Integer, index=True )
+ col = Column( "library_id", Integer, ForeignKey( "library.id" ), index=True )
col.create( Sample_table )
assert col is Sample_table.c.library_id
except Exception, e:
log.debug( "Adding column 'library_id' to sample table failed: %s" % ( str( e ) ) )
- # add the foreign key constraint
- try:
- cons = ForeignKeyConstraint( [Sample_table.c.library_id],
- [Library_table.c.id],
- name='sample_library_id_fk' )
- # Create the constraint
- cons.create()
- except Exception, e:
- log.debug( "Adding foreign key constraint 'sample_library_id_fk' to table 'library' failed: %s" % ( str( e ) ) )
# library_folder table
try:
LibraryFolder_table = Table( "library_folder", metadata, autoload=True )
@@ -104,21 +139,11 @@
if LibraryFolder_table:
# Add the library_id column in 'sample' table
try:
- col = Column( "folder_id", Integer, index=True )
+ col = Column( "folder_id", Integer, ForeignKey( "library_folder.id" ), index=True )
col.create( Sample_table )
assert col is Sample_table.c.folder_id
except Exception, e:
log.debug( "Adding column 'folder_id' to sample table failed: %s" % ( str( e ) ) )
- # add the foreign key constraint
- try:
- cons = ForeignKeyConstraint( [Sample_table.c.folder_id],
- [LibraryFolder_table.c.id],
- name='sample_folder_id_fk' )
- # Create the constraint
- cons.create()
- except Exception, e:
- log.debug( "Adding foreign key constraint 'sample_folder_id_fk' to table 'library_folder' failed: %s" % ( str( e ) ) )
-
def downgrade():
pass
diff -r 29ece93d429c -r 4a6bb3b64012 scripts/galaxy_messaging/server/data_transfer.py
--- a/scripts/galaxy_messaging/server/data_transfer.py Wed Feb 10 18:25:32 2010 -0500
+++ b/scripts/galaxy_messaging/server/data_transfer.py Thu Feb 11 09:25:29 2010 -0500
@@ -40,8 +40,8 @@
import simplejson
curr_dir = os.getcwd()
-logfile = os.path.join(curr_dir, 'data_transfer.log')
-logging.basicConfig(filename=sys.stdout, level=logging.DEBUG,
+logfile = os.path.join('/Users/rc/tmp', 'data_transfer.log')
+logging.basicConfig(filename=logfile, level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s")
class DataTransferException(Exception):
1
0
11 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/29ece93d429c
changeset: 3371:29ece93d429c
user: Kanwei Li <kanwei(a)gmail.com>
date: Wed Feb 10 18:25:32 2010 -0500
description:
- Fix Safari crashing bug for async in-place editing
- Refactor galaxy.base.js
- Escape history name in renaming template
diffstat:
static/scripts/galaxy.base.js | 290 +++++++++++++++-----------------
static/scripts/packed/galaxy.base.js | 2 +-
static/scripts/packed/galaxy.panels.js | 2 +-
static/scripts/packed/trackster.js | 2 +-
templates/history/rename.mako | 5 +-
5 files changed, 145 insertions(+), 156 deletions(-)
diffs (452 lines):
diff -r 6dff2f938898 -r 29ece93d429c static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Wed Feb 10 16:02:11 2010 -0500
+++ b/static/scripts/galaxy.base.js Wed Feb 10 18:25:32 2010 -0500
@@ -12,53 +12,11 @@
el.remove().appendTo("body");
}
});
-}
-
-$(document).ready( function() {
- // Links with confirmation
- $( "a[confirm]" ).click( function() {
- return confirm( $(this).attr( "confirm" ) )
- });
- // Tooltips
- if ( $.fn.tipsy ) {
- $(".tooltip").tipsy( { gravity: 's' } );
- }
- // Make popup menus.
- make_popup_menus();
-});
-
-function make_popup_menus()
-{
- jQuery( "div[popupmenu]" ).each( function() {
- var options = {};
- $(this).find( "a" ).each( function() {
- var confirmtext = $(this).attr( "confirm" ),
- href = $(this).attr( "href" ),
- target = $(this).attr( "target" );
- options[ $(this).text() ] = function() {
- if ( !confirmtext || confirm( confirmtext ) ) {
- var f = window;
- if ( target == "_parent" ) {
- f = window.parent;
- }
- else if
- ( target == "_top" ) {
- f = window.top;
- }
- f.location = href;
- }
- };
- });
- var b = $( "#" + $(this).attr( 'popupmenu' ) );
- make_popupmenu( b, options );
- $(this).remove();
- b.addClass( "popup" ).show();
- });
-}
+};
function ensure_popup_helper() {
// And the helper below the popup menus
- if ( $( "#popup-helper" ).length == 0 ) {
+ if ( $( "#popup-helper" ).length === 0 ) {
$( "<div id='popup-helper'/>" ).css( {
background: 'white', opacity: 0, zIndex: 15000,
position: 'absolute', top: 0, left: 0, width: '100%', height: '100%'
@@ -66,13 +24,41 @@
}
}
+function attach_popupmenu( button_element, wrapper ) {
+ var clean = function() {
+ wrapper.unbind().hide();
+ $("#popup-helper").unbind( "click.popupmenu" ).hide();
+ // $(document).unbind( "click.popupmenu" );
+ };
+ var click = function( e ) {
+ // var o = $(button_element).offset();
+ $("#popup-helper").bind( "click.popupmenu", clean ).show();
+ // $(document).bind( "click.popupmenu", clean );
+ // Show off screen to get size right
+ wrapper.click( clean ).css( { left: 0, top: -1000 } ).show();
+ // console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
+ var x = e.pageX - wrapper.width() / 2 ;
+ x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 20 );
+ x = Math.max( x, $(document).scrollLeft() + 20 );
+ // console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
+
+
+ wrapper.css( {
+ top: e.pageY - 5,
+ left: x
+ } );
+ return false;
+ };
+ $( button_element ).click( click );
+}
+
function make_popupmenu( button_element, options ) {
ensure_popup_helper();
- var container_element = $(button_element);
+ // var container_element = $(button_element);
// if ( container_element.parent().hasClass( "combo-button" ) ) {
// container_element = container_element.parent();
// }
- // ontainer_element).css( "position", "relative" );
+ // container_element).css( "position", "relative" );
var menu_element = $( "<ul id='" + button_element.attr('id') + "-menu'></ul>" );
$.each( options, function( k, v ) {
if ( v ) {
@@ -88,96 +74,90 @@
.appendTo( "body" )
.hide();
attach_popupmenu( button_element, wrapper );
-};
+}
-function attach_popupmenu( button_element, wrapper ) {
- var clean = function() {
- wrapper.unbind().hide();
- $("#popup-helper").unbind( "click.popupmenu" ).hide();
- // $(document).unbind( "click.popupmenu" );
- };
- var click = function( e ) {
- var o = $(button_element).offset();
- $("#popup-helper").bind( "click.popupmenu", clean ).show();
- // $(document).bind( "click.popupmenu", clean );
- // Show off screen to get size right
- wrapper.click( clean ).css( { left: 0, top: -1000 } ).show();
- // console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
- var x = e.pageX - wrapper.width() / 2
- x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 20 );
- x = Math.max( x, $(document).scrollLeft() + 20 );
- // console.log( e.pageX, $(document).scrollLeft() + $(window).width(), $(menu_element).width() );
-
-
- wrapper.css( {
- top: e.pageY - 5,
- left: x
- } );
- return false;
- };
- $( button_element ).click( click );
-};
+function make_popup_menus() {
+ jQuery( "div[popupmenu]" ).each( function() {
+ var options = {};
+ $(this).find( "a" ).each( function() {
+ var confirmtext = $(this).attr( "confirm" ),
+ href = $(this).attr( "href" ),
+ target = $(this).attr( "target" );
+ options[ $(this).text() ] = function() {
+ if ( !confirmtext || confirm( confirmtext ) ) {
+ var f = window;
+ if ( target == "_parent" ) {
+ f = window.parent;
+ } else if ( target == "_top" ) {
+ f = window.top;
+ }
+ f.location = href;
+ }
+ };
+ });
+ var b = $( "#" + $(this).attr( 'popupmenu' ) );
+ make_popupmenu( b, options );
+ $(this).remove();
+ b.addClass( "popup" ).show();
+ });
+}
// Returns the number of keys (elements) in an array/dictionary.
-var array_length = function(an_array)
-{
- if (an_array.length)
+function array_length(an_array) {
+ if (an_array.length) {
return an_array.length;
+ }
var count = 0;
- for (element in an_array)
+ for (var element in an_array) {
count++;
+ }
return count;
-};
+}
-//
// Replace dbkey select box with text input box & autocomplete.
-//
-var replace_dbkey_select = function()
-{
+function replace_dbkey_select() {
var select_elt = $('select[name=dbkey]');
var start_value = select_elt.attr('value');
- if (select_elt.length != 0)
- {
- //
+ if (select_elt.length !== 0) {
// Set up text input + autocomplete element.
- //
var text_input_elt = $("<input id='dbkey-input' type='text'></input>");
text_input_elt.attr('size', 40);
text_input_elt.attr('name', select_elt.attr('name'));
- text_input_elt.click( function()
- {
- // Show all. Also provide note that load is happening since this can be slow.
- var cur_value = $(this).attr('value');
- $(this).attr('value', 'Loading...');
- $(this).showAllInCache();
- $(this).attr('value', cur_value);
- $(this).select();
+ text_input_elt.click( function() {
+ // Show all. Also provide note that load is happening since this can be slow.
+ var cur_value = $(this).attr('value');
+ $(this).attr('value', 'Loading...');
+ $(this).showAllInCache();
+ $(this).attr('value', cur_value);
+ $(this).select();
});
// Get options for dbkey for autocomplete.
- var dbkey_options = new Array();
- var dbkey_mapping = new Object();
- select_elt.children('option').each( function()
- {
+ var dbkey_options = [];
+ var dbkey_mapping = {};
+ select_elt.children('option').each( function() {
// Get text, value for option.
var text = $(this).text();
var value = $(this).attr('value');
// Ignore values that are '?'
- if (value == '?')
+ if (value == '?') {
return;
+ }
// Set options and mapping.
dbkey_options.push( text );
dbkey_mapping[ text ] = value;
// If this is the start value, set value of input element.
- if ( value == start_value )
+ if ( value == start_value ) {
text_input_elt.attr('value', text);
+ }
});
- if ( text_input_elt.attr('value') == '' )
+ if ( text_input_elt.attr('value') == '' ) {
text_input_elt.attr('value', 'Click to Search or Select Build');
+ }
// Do autocomplete.
var autocomplete_options = { selectFirst: false, autoFill: false, mustMatch: false, matchContains: true, max: 1000, minChars : 0, hideForLessThanMinChars : false };
@@ -186,70 +166,70 @@
// Replace select with text input.
select_elt.replaceWith(text_input_elt);
- //
// When form is submitted, change the text entered into the input to the corresponding value. If text doesn't correspond to value, remove it.
- //
- $('form').submit( function()
- {
+ $('form').submit( function() {
var dbkey_text_input = $('#dbkey-input');
- if (dbkey_text_input.length != 0)
- {
+ if (dbkey_text_input.length !== 0) {
// Try to convert text to value.
var cur_value = dbkey_text_input.attr('value');
var new_value = dbkey_mapping[cur_value];
- if (new_value != null && new_value != undefined)
+ if (new_value !== null && new_value !== undefined) {
dbkey_text_input.attr('value', new_value);
- else
- {
+ } else {
// If there is a non-empty start value, use that; otherwise unknown.
- if (start_value != "")
+ if (start_value != "") {
dbkey_text_input.attr('value', start_value);
- else
+ } else {
dbkey_text_input.attr('value', '?');
+ }
}
}
});
}
-} // end replace_dbkey_select()
+}
-//
// Edit and save text asynchronously.
-//
-function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, num_cols, use_textarea, num_rows, on_start, on_finish)
-{
+function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, num_cols, use_textarea, num_rows, on_start, on_finish) {
// Set defaults if necessary.
- if (num_cols == null)
+ if (num_cols === undefined) {
num_cols = 30;
- if (num_rows == null)
- num_rows = 4
+ }
+ if (num_rows === undefined) {
+ num_rows = 4;
+ }
// Set up input element.
- $("#" + click_to_edit_elt).click( function() {
- var old_text = $("#" + text_elt_id).text()
- if (use_textarea)
- var t = $("<textarea rows='" + num_rows + "' cols='" + num_cols + "'>" + old_text + "</textarea>" );
- else
- var t = $("<input type='text' value='" + old_text + "' size='" + num_cols + "'></input>" );
+ $("#" + click_to_edit_elt).live( "click", function() {
+ // Check if this is already active
+ if ( $("#renaming-active").length > 0) {
+ return;
+ }
+ var text_elt = $("#" + text_elt_id),
+ old_text = text_elt.text(),
+ t;
+
+ if (use_textarea) {
+ t = $("<textarea></textarea>").attr({ rows: num_rows, cols: num_cols }).text( old_text );
+ } else {
+ t = $("<input type='text'></input>").attr({ value: old_text, size: num_cols });
+ }
+ t.attr("id", "renaming-active");
t.blur( function() {
$(this).remove();
- $("#" + text_elt_id).show();
- if (has_tooltip)
- tooltip_elt.addClass("tooltip");
- if (on_finish != null)
+ text_elt.show();
+ if (on_finish) {
on_finish(t);
+ }
});
- var has_tooltip = $(this).hasClass("tooltip");
- var tooltip_elt = $(this);
t.keyup( function( e ) {
- if ( e.keyCode == 27 ) {
+ if ( e.keyCode === 27 ) {
// Escape key
$(this).trigger( "blur" );
- } else if ( e.keyCode == 13 ) {
- // Enter key
- new_text = this.value;
+ } else if ( e.keyCode === 13 ) {
+ // Enter key submits
+ var ajax_data = {};
+ ajax_data[text_parm_name] = $(this).val();
$(this).trigger( "blur" );
- var ajax_data = new Object();
- ajax_data[text_parm_name] = new_text;
$.ajax({
url: save_url,
data: ajax_data,
@@ -259,27 +239,37 @@
},
success: function(processed_text) {
// Set new text and call finish method.
- $("#" + text_elt_id).text( processed_text );
- if (on_finish != null)
+ text_elt.text( processed_text );
+ if (on_finish) {
on_finish(t);
+ }
}
});
}
});
- // Call onstart method if it exists.
- if (on_start != null)
+ if (on_start) {
on_start(t);
-
+ }
// Replace text with input object and focus & select.
- $("#" + text_elt_id).hide();
- t.insertAfter( $("#" + text_elt_id) );
+ text_elt.hide();
+ t.insertAfter( text_elt );
t.focus();
t.select();
- // Remove tooltip so that it doesn't show during editing.
- $(this).removeClass("tooltip");
- return false;
+ return;
});
-
}
+
+$(document).ready( function() {
+ // Links with confirmation
+ $( "a[confirm]" ).click( function() {
+ return confirm( $(this).attr("confirm") );
+ });
+ // Tooltips
+ if ( $.fn.tipsy ) {
+ $(".tooltip").tipsy( { gravity: 's' } );
+ }
+ // Make popup menus.
+ make_popup_menus();
+});
diff -r 6dff2f938898 -r 29ece93d429c static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js Wed Feb 10 16:02:11 2010 -0500
+++ b/static/scripts/packed/galaxy.base.js Wed Feb 10 18:25:32 2010 -0500
@@ -1,1 +1,1 @@
-$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function ensure_popup_helper(){if($("#popup-helper").length==0){$("<div id='popup-helper'/>").css({background:"white",opacity:0
,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_popupmenu(d,c){ensure_popup_helper();var a=$(d);var b=$("<ul id='"+d.attr("id")+"-menu'></ul>");$.each(c,function(g,f){if(f){$("<li/>").html(g).click(f).appendTo(b)}else{$("<li class='head'/>").html(g).appendTo(b)}});var e=$("<div class='popmenu-wrapper'>");e.append(b).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(d,e)}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){var h=$(b).offset();$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}var array_length=function(a){if(a.length){
return a.length}var b=0;for(element in a){b++}return b};var replace_dbkey_select=function(){var c=$("select[name=dbkey]");var d=c.attr("value");if(c.length!=0){var e=$("<input id='dbkey-input' type='text'></input>");e.attr("size",40);e.attr("name",c.attr("name"));e.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var b=new Array();var a=new Object();c.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}b.push(h);a[h]=g;if(g==d){e.attr("value",h)}});if(e.attr("value")==""){e.attr("value","Click to Search or Select Build")}var f={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};e.autocomplete(b,f);c.replaceWith(e);$("form").submit(function(){var i=$("#dbkey-input");if(i.length!=0){var h=i.attr("value");var g=a[h];if(g!=null&&g!=undefined){i.attr("value",g)}else{
if(d!=""){i.attr("value",d)}else{i.attr("value","?")}}}})}};function async_save_text(d,f,e,a,c,h,i,g,b){if(c==null){c=30}if(i==null){i=4}$("#"+d).click(function(){var l=$("#"+f).text();if(h){var j=$("<textarea rows='"+i+"' cols='"+c+"'>"+l+"</textarea>")}else{var j=$("<input type='text' value='"+l+"' size='"+c+"'></input>")}j.blur(function(){$(this).remove();$("#"+f).show();if(m){k.addClass("tooltip")}if(b!=null){b(j)}});var m=$(this).hasClass("tooltip");var k=$(this);j.keyup(function(o){if(o.keyCode==27){$(this).trigger("blur")}else{if(o.keyCode==13){new_text=this.value;$(this).trigger("blur");var n=new Object();n[a]=new_text;$.ajax({url:e,data:n,error:function(){alert("Text editing for elt "+f+" failed")},success:function(p){$("#"+f).text(p);if(b!=null){b(j)}}})}}});if(g!=null){g(j)}$("#"+f).hide();j.insertAfter($("#"+f));j.focus();j.select();$(this).removeClass("tooltip");return false})};
\ No newline at end of file
+$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function ensure_popup_helper(){if($("#popup-helper").length===0){$("<div id='popup-helper'/>").css({background:"white",opacity:0,zIndex:15000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function attach_popupmenu(b,d){var a=function(){d.unbind().hide();$("#popup-helper").unbind("click.popupmenu").hide()};var c=function(g){$("#popup-helper").bind("click.popupmenu",a).show();d.click(a).css({left:0,top:-1000}).show();var f=g.pageX-d.width()/2;f=Math.min(f,$(document).scrollLeft()+$(window).width()-$(d).width()-20);f=Math.max(f,$(document).scrollLeft()+20);d.css({top:g.pageY-5,left:f});return false};$(b).click(c)}function make_popupmenu(c,b){ensure_popup_helper();var a=$("<ul id='"+c.attr("id")
+"-menu'></ul>");$.each(b,function(f,e){if(e){$("<li/>").html(f).click(e).appendTo(a)}else{$("<li class='head'/>").html(f).appendTo(a)}});var d=$("<div class='popmenu-wrapper'>");d.append(a).append("<div class='overlay-border'>").css("position","absolute").appendTo("body").hide();attach_popupmenu(c,d)}function make_popup_menus(){jQuery("div[popupmenu]").each(function(){var c={};$(this).find("a").each(function(){var b=$(this).attr("confirm"),d=$(this).attr("href"),e=$(this).attr("target");c[$(this).text()]=function(){if(!b||confirm(b)){var g=window;if(e=="_parent"){g=window.parent}else{if(e=="_top"){g=window.top}}g.location=d}}});var a=$("#"+$(this).attr("popupmenu"));make_popupmenu(a,c);$(this).remove();a.addClass("popup").show()})}function array_length(b){if(b.length){return b.length}var c=0;for(var a in b){c++}return c}function replace_dbkey_select(){var c=$("select[name=dbkey]");var d=c.attr("value");if(c.length!==0){var e=$("<input id='dbkey-input' type='text'></input>")
;e.attr("size",40);e.attr("name",c.attr("name"));e.click(function(){var g=$(this).attr("value");$(this).attr("value","Loading...");$(this).showAllInCache();$(this).attr("value",g);$(this).select()});var b=[];var a={};c.children("option").each(function(){var h=$(this).text();var g=$(this).attr("value");if(g=="?"){return}b.push(h);a[h]=g;if(g==d){e.attr("value",h)}});if(e.attr("value")==""){e.attr("value","Click to Search or Select Build")}var f={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:1000,minChars:0,hideForLessThanMinChars:false};e.autocomplete(b,f);c.replaceWith(e);$("form").submit(function(){var i=$("#dbkey-input");if(i.length!==0){var h=i.attr("value");var g=a[h];if(g!==null&&g!==undefined){i.attr("value",g)}else{if(d!=""){i.attr("value",d)}else{i.attr("value","?")}}}})}}function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$(
"#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text(k)}else{j=$("<input type='text'></input>").attr({value:k,size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){l.text(o);if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}$(document).ready(function(){$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tipsy){$(".tooltip").tipsy({gravity:"s"})}make_popup_menus()});
\ No newline at end of file
diff -r 6dff2f938898 -r 29ece93d429c static/scripts/packed/galaxy.panels.js
--- a/static/scripts/packed/galaxy.panels.js Wed Feb 10 16:02:11 2010 -0500
+++ b/static/scripts/packed/galaxy.panels.js Wed Feb 10 18:25:32 2010 -0500
@@ -1,1 +1,1 @@
-function ensure_dd_helper(){if($("#DD-helper").length==0){$("<div id='DD-helper'/>").css({background:"white",opacity:0,zIndex:9000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_left_panel(h,c,e){var g=false;var f=null;var d=function(i){var j=i;if(i<0){i=0}$(h).css("width",i);$(e).css("left",j);$(c).css("left",i+7);if(document.recalc){document.recalc()}};var a=function(){if(g){$(e).removeClass("hover");$(e).animate({left:f},"fast");$(h).css("left",-f).show().animate({left:0},"fast",function(){d(f);$(e).removeClass("hidden")});g=false}else{f=$(e).position().left;$(c).css("left",$(e).innerWidth());if(document.recalc){document.recalc()}$(e).removeClass("hover");$(h).animate({left:-f},"fast");$(e).animate({left:-1},"fast",function(){$(this).addClass("hidden")});g=true}};$(e).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(i){$("#DD-helper").show()}).bind("dragend
",function(i){$("#DD-helper").hide()}).bind("drag",function(i){x=i.offsetX;x=Math.min(400,Math.max(100,x));if(g){$(h).css("left",0);$(e).removeClass("hidden");g=false}d(x)}).bind("dragclickonly",function(i){a()}).find("div").show();var b=function(i){if((g&&i=="show")||(!g&&i=="hide")){a()}};return{force_panel:b}}function make_right_panel(a,e,h){var j=false;var g=false;var c=null;var d=function(k){$(a).css("width",k);$(e).css("right",k+9);$(h).css("right",k).css("left","");if(document.recalc){document.recalc()}};var i=function(){if(j){$(h).removeClass("hover");$(h).animate({right:c},"fast");$(a).css("right",-c).show().animate({right:0},"fast",function(){d(c);$(h).removeClass("hidden")});j=false}else{c=$(document).width()-$(h).position().left-$(h).outerWidth();$(e).css("right",$(h).innerWidth()+1);if(document.recalc){document.recalc()}$(h).removeClass("hover");$(a).animate({right:-c},"fast");$(h).animate({right:-1},"fast",function(){$(this).addClass("hidden")});j=true}g=false}
;var b=function(k){var l=$(e).width()-(j?c:0);if(l<k){if(!j){i();g=true}}else{if(g){i();g=false}}};$(h).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(k){$("#DD-helper").show()}).bind("dragend",function(k){$("#DD-helper").hide()}).bind("drag",function(k){x=k.offsetX;w=$(window).width();x=Math.min(w-100,x);x=Math.max(w-400,x);if(j){$(a).css("right",0);$(h).removeClass("hidden");j=false}d(w-x-$(this).outerWidth())}).bind("dragclickonly",function(k){i()}).find("div").show();var f=function(k){if((j&&k=="show")||(!j&&k=="hide")){i()}};return{handle_minwidth_hint:b,force_panel:f}}function hide_modal(){$(".dialog-box-container").fadeOut(function(){$("#overlay").hide();$(".dialog-box").find(".body").children().remove()})}function show_modal(f,c,e,d){if(f){$(".dialog-box").find(".title").html(f);$(".dialog-box").find(".unified-panel-header").show()}else{$(".dialog-box").find(".unified-panel-header").hide()}var a=$(".dia
log-box").find(".buttons").html("");if(e){$.each(e,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}var a=$(".dialog-box").find(".extra_buttons").html("");if(d){$.each(d,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}if(c=="progress"){c=$("<img src='../images/yui/rel_interstitial_loading.gif')' />")}$(".dialog-box").find(".body").html(c);if(!$(".dialog-box-container").is(":visible")){$("#overlay").show();$(".dialog-box-container").fadeIn()}}function show_in_overlay(c){var d=c.width||"600";var b=c.height||"400";var a=c.scroll||"auto";$("#overlay-background").bind("click.overlay",function(){hide_modal();$("#overlay-background").unbind("click.overlay")});show_modal(null,$("<div style='margin: -5px;'><img id='close_button' style='position:absolute;right:-12px;top:-12px;' src='../images/delete_icon.png'><iframe style='margin: 0; padding: 0;' src='"+c.url+"' width='"+d+"' height='"+b+"' s
crolling='"+a+"' frameborder='0'></iframe></div>"));$("#close_button").bind("click",function(){hide_modal()})}$(function(){$(".tab").each(function(){var a=$(this).children(".submenu");if(a.length>0){if($.browser.msie){a.prepend("<iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; filter:Alpha(Opacity='0');\"></iframe>")}$(this).hover(function(){a.show()},function(){a.hide()});a.click(function(){a.hide()})}})});function user_changed(a,b){if(a){$(".loggedin-only").show();$(".loggedout-only").hide();$("#user-email").text(a);if(b){$(".admin-only").show()}}else{$(".loggedin-only").hide();$(".loggedout-only").show();$(".admin-only").hide()}};
\ No newline at end of file
+function ensure_dd_helper(){if($("#DD-helper").length==0){$("<div id='DD-helper'/>").css({background:"white",opacity:0,zIndex:9000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_left_panel(h,c,e){var g=false;var f=null;var d=function(i){var j=i;if(i<0){i=0}$(h).css("width",i);$(e).css("left",j);$(c).css("left",i+7);if(document.recalc){document.recalc()}};var a=function(){if(g){$(e).removeClass("hover");$(e).animate({left:f},"fast");$(h).css("left",-f).show().animate({left:0},"fast",function(){d(f);$(e).removeClass("hidden")});g=false}else{f=$(e).position().left;$(c).css("left",$(e).innerWidth());if(document.recalc){document.recalc()}$(e).removeClass("hover");$(h).animate({left:-f},"fast");$(e).animate({left:-1},"fast",function(){$(this).addClass("hidden")});g=true}};$(e).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(i){$("#DD-helper").show()}).bind("dragend
",function(i){$("#DD-helper").hide()}).bind("drag",function(i){x=i.offsetX;x=Math.min(400,Math.max(100,x));if(g){$(h).css("left",0);$(e).removeClass("hidden");g=false}d(x)}).bind("dragclickonly",function(i){a()}).find("div").show();var b=function(i){if((g&&i=="show")||(!g&&i=="hide")){a()}};return{force_panel:b}}function make_right_panel(a,e,h){var j=false;var g=false;var c=null;var d=function(k){$(a).css("width",k);$(e).css("right",k+9);$(h).css("right",k).css("left","");if(document.recalc){document.recalc()}};var i=function(){if(j){$(h).removeClass("hover");$(h).animate({right:c},"fast");$(a).css("right",-c).show().animate({right:0},"fast",function(){d(c);$(h).removeClass("hidden")});j=false}else{c=$(document).width()-$(h).position().left-$(h).outerWidth();$(e).css("right",$(h).innerWidth()+1);if(document.recalc){document.recalc()}$(h).removeClass("hover");$(a).animate({right:-c},"fast");$(h).animate({right:-1},"fast",function(){$(this).addClass("hidden")});j=true}g=false}
;var b=function(k){var l=$(e).width()-(j?c:0);if(l<k){if(!j){i();g=true}}else{if(g){i();g=false}}};$(h).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(k){$("#DD-helper").show()}).bind("dragend",function(k){$("#DD-helper").hide()}).bind("drag",function(k){x=k.offsetX;w=$(window).width();x=Math.min(w-100,x);x=Math.max(w-400,x);if(j){$(a).css("right",0);$(h).removeClass("hidden");j=false}d(w-x-$(this).outerWidth())}).bind("dragclickonly",function(k){i()}).find("div").show();var f=function(k){if((j&&k=="show")||(!j&&k=="hide")){i()}};return{handle_minwidth_hint:b,force_panel:f}}function hide_modal(){$(".dialog-box-container").fadeOut(function(){$("#overlay").hide();$(".dialog-box").find(".body").children().remove()})}function show_modal(f,c,e,d){if(f){$(".dialog-box").find(".title").html(f);$(".dialog-box").find(".unified-panel-header").show()}else{$(".dialog-box").find(".unified-panel-header").hide()}var a=$(".dia
log-box").find(".buttons").html("");if(e){$.each(e,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}var a=$(".dialog-box").find(".extra_buttons").html("");if(d){$.each(d,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}if(c=="progress"){c=$("<img src='../images/yui/rel_interstitial_loading.gif')' />")}$(".dialog-box").find(".body").html(c);if(!$(".dialog-box-container").is(":visible")){$("#overlay").show();$(".dialog-box-container").fadeIn()}}function show_in_overlay(c){var d=c.width||"600";var b=c.height||"400";var a=c.scroll||"auto";$("#overlay-background").bind("click.overlay",function(){hide_modal();$("#overlay-background").unbind("click.overlay")});show_modal(null,$("<div style='margin: -5px;'><img id='close_button' style='position:absolute;right:-17px;top:-15px;' src='../images/closebox.png'><iframe style='margin: 0; padding: 0;' src='"+c.url+"' width='"+d+"' height='"+b+"' scro
lling='"+a+"' frameborder='0'></iframe></div>"));$("#close_button").bind("click",function(){hide_modal()})}$(function(){$(".tab").each(function(){var a=$(this).children(".submenu");if(a.length>0){if($.browser.msie){a.prepend("<iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; filter:Alpha(Opacity='0');\"></iframe>")}$(this).hover(function(){a.show()},function(){a.hide()});a.click(function(){a.hide()})}})});function user_changed(a,b){if(a){$(".loggedin-only").show();$(".loggedout-only").hide();$("#user-email").text(a);if(b){$(".admin-only").show()}}else{$(".loggedin-only").hide();$(".loggedout-only").show();$(".admin-only").hide()}};
\ No newline at end of file
diff -r 6dff2f938898 -r 29ece93d429c static/scripts/packed/trackster.js
--- a/static/scripts/packed/trackster.js Wed Feb 10 16:02:11 2010 -0500
+++ b/static/scripts/packed/trackster.js Wed Feb 10 18:25:32 2010 -0500
@@ -1,1 +1,1 @@
-var DEBUG=false;var DENSITY=1000,FEATURE_LEVELS=10,DATA_ERROR="There was an error in indexing this dataset.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=20,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src="../images/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src="../images/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src="../images/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src="../images/visualization/strand_left_inv.png";left_i
mg_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(b,d,c,a){this.vis_id=c;this.dbkey=a;this.title=d;this.chrom=b;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.center=(this.max_high-this.max_low)/2;this.zoom_factor=3;this.zoom_level=0};$.extend(View.prototype,{add_track:function(a){a.view=this;this.tracks.push(a);if(a.init){a.init()}},add_label_track:function
(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){delete this.tracks[a]},update_options:function(){for(var b in view.tracks){var a=view.tracks[b];if(a.update_options){a.update_options(b)}}},redraw:function(f){this.span=this.max_high-this.max_low;var d=this.span/Math.pow(this.zoom_factor,this.zoom_level),b=this.center-(d/2),e=b+d;if(b<0){b=0;e=b+d}else{if(e>this.max_high){e=this.max_high;b=e-d}}this.low=Math.floor(b);this.high=Math.ceil(e);this.center=Math.round(this.low+(this.high-this.low)/2);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/DENSITY)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));$("#overview-box").css({left:(this.low/this.span)*$("#overview-viewport").width(),width:Math.max(12,((this.high-this.low)/this.span)*$("#overview-viewport").width())}).show();$("#low").val(commatize(this.low));$("#high").val(commatize(this.high));if(!f){f
or(var c=0,a=this.tracks.length;c<a;c++){this.tracks[c].draw()}for(var c=0,a=this.label_tracks.length;c<a;c++){this.label_tracks[c].draw()}}},zoom_in:function(a){if(this.max_high===0||this.high-this.low<30){return}if(a){this.center=a/$(document).width()*(this.high-this.low)+this.low}this.zoom_level+=1;this.redraw()},zoom_out:function(){if(this.max_high===0){return}if(this.zoom_level<=0){this.zoom_level=0;return}this.zoom_level-=1;this.redraw()}});var Track=function(a,b){this.name=a;this.parent_element=b;this.make_container()};$.extend(Track.prototype,{make_container:function(){this.header_div=$("<div class='track-header'>").text(this.name);this.content_div=$("<div class='track-content'>");this.container_div=$("<div class='track'></div>").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)}});var TiledTrack=function(){};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var i=this.view.low,e=this.view.high,f=e-i,d=this.v
iew.resolution;if(DEBUG){$("#debug").text(d+" "+this.view.zoom_res)}var k=$("<div style='position: relative;'></div>");this.content_div.children(":first").remove();this.content_div.append(k);var l=this.content_div.width()/f;var h;var a=Math.floor(i/d/DENSITY);while((a*DENSITY*d)<e){var j=this.content_div.width()+"_"+this.view.zoom_level+"_"+a;var c=this.tile_cache.get(j);if(c){var g=a*DENSITY*d;var b=(g-i)*l;if(this.left_offset){b-=this.left_offset}c.css({left:b});k.append(c);this.max_height=Math.max(this.max_height,c.height())}else{this.delayed_draw(this,j,i,e,a,d,k,l)}a+=1}},delayed_draw:function(c,e,a,f,b,d,g,h){setTimeout(function(){if(!(a>c.view.high||f<c.view.low)){tile_element=c.draw_tile(d,b,g,h);if(tile_element){c.tile_cache.set(e,tile_element);c.max_height=Math.max(c.max_height,tile_element.height());c.content_div.css("height",c.max_height)}}},50)}});var LabelTrack=function(a){Track.call(this,null,a);this.track_type="LabelTrack";this.hidden=true;this.container_div.
addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var LineTrack=function(c,a,d,b){this.track_type="LineTrack";this.tile_cache=new Cache(CACHED_TILES_LINE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.indexer=d;this.height_px=100;this.container_div.addClass("line-track");this.dataset_id=a;this.prefs={min_value:undefined,max_value:undefined};if(b.min_value!==undefined){this.prefs.min_value=b.min_value}if(b.max_value!==undefined){this.prefs.max_value=b.max_value}};$.extend(LineTrack.prototype,TiledTrack.prototype,{i
nit:function(){this.data_queue={};this.data_cache=new Cache(CACHED_DATA);var a=this,b=a.view.tracks.indexOf(a);a.content_div.text(DATA_LOADING);a.container_div.removeClass("nodata error pending");$.getJSON(data_url,{stats:true,indexer:a.indexer,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(d){if(!d||d=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(d.length===0||d=="no data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d=="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");if(a.prefs.min_value===undefined||a.prefs.max_value===undefined){a.prefs.min_value=d.min;a.prefs.max_value=d.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;if($("#linetrack_"+b
+"_minval").length===0){var e=$("<div></div>").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(a.prefs.min_value);var c=$("<div></div>").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(a.prefs.max_value);c.css({position:"relative",top:"25px"});c.prependTo(a.container_div);e.css({position:"relative",top:a.height_px+55+"px"});e.prependTo(a.container_div)}a.draw()}}}})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.getJSON(data_url,{indexer:this.indexer,chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()})}},draw_tile:function(n,p,c,e){if(this.vertical_range===undefined){return}var q=p*DENSITY*n,a=DENSITY*n,b=$("<canvas class='tile'></canvas>"),s=n+"_"+p;if(!this.data_cache.get(s)){this.get_data(n,p);return}var r=this.data_cache.get(s);b.css({position:"absolute",top:
0,left:(q-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var m=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,f=this.prefs.max_value,l=this.vertical_range,d=this.height_px;m.beginPath();for(var o=0;o<r.length-1;o++){var h=r[o][0]-q;var g=r[o][1];if(isNaN(g)){j=false}else{h=h*e;if(g<=k){g=k}else{if(g>=f){g=f}}g=Math.round(d-(g-k)/l*d);if(j){m.lineTo(h,g)}else{m.moveTo(h,g);j=true}}}m.stroke();c.append(b);return b},gen_options:function(j){var a=$("<div></div>").addClass("form-row");var e="track_"+j+"_minval",g="track_"+j+"_maxval",h=$("<label></label>").attr("for",e).text("Min value:"),b=(this.prefs.min_value===undefined?"":this.prefs.min_value),i=$("<input></input>").attr("id",e).val(b),d=$("<label></label>").attr("for",g).text("Max value:"),f=(this.prefs.max_value===undefined?"":this.prefs.max_value),c=$("<input></input>").attr("id",g).val(f);return a.append(h).append(i).append(d).append(c)},update_options:function(c){var a=$("#trac
k_"+c+"_minval").val(),b=$("#track_"+c+"_maxval").val();if(a!==this.prefs.min_value||b!==this.prefs.max_value){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(b);this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+c+"_minval").text(this.prefs.min_value);$("#linetrack_"+c+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(c,a,d,b){this.track_type="FeatureTrack";this.tile_cache=new Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.indexer=d;this.height_px=100;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=3;this.default_font="9px Monaco, Lucida Console, monospace";this.left_offset=200;this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.data_cache=new Cache(20);this.prefs={block_color:"black",l
abel_color:"black"};if(b.block_color!==undefined){this.prefs.block_color=b.block_color}if(b.label_color!==undefined){this.prefs.label_color=b.label_color}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this;a.content_div.text(DATA_LOADING);a.container_div.removeClass("nodata error pending");$.getJSON(data_url,{indexer:a.indexer,low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(b=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(b.length===0||b=="no data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(b=="pending"){a.container_div.adClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.values=b;a.calc_slots();a.slots=a.zo_slots;a.draw()}}}})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.get
JSON(data_url,{indexer:b.indexer,chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,include_blocks:true},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},calc_slots:function(){var b=[],a=this.content_div.width()/(this.view.high-this.view.low),d=this.view.max_low;for(var e=0,f=this.values.length;e<f;e++){var g,h,k=this.values[e];g=Math.floor((k.start-d)*a);h=Math.ceil((k.end-d)*a);var c=0;while(true){if(b[c]===undefined||b[c]<g){b[c]=h;this.zo_slots[k.uid]=c;break}c++}}this.height_px=b.length*this.vertical_nodetail_px+15;this.content_div.css("height",this.height_px+"px")},incremental_slots:function(a,f){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=1/a;this.s_e_by_tile[a]={}}var h=this.inc_slots[a].w_scale,s=[],g=0,b=$("<canvas></canvas>").get(0).getContext("2d"),l=this.view.max_low;var c,e,u=[];for(var p=0,q=f.length;p<q;p++){var d=f[p];if(this.inc_slots[a][d.uid]!==undefined){g=Math.max(g,this.inc_slots[a][d.uid]);u.push(thi
s.inc_slots[a][d.uid])}else{s.push(p)}}for(var p=0,q=s.length;p<q;p++){var d=f[s[p]];c=Math.floor((d.start-l)*h);c-=b.measureText(d.name).width;e=Math.ceil((d.end-l)*h);var o=0;while(true){var m=true;if(this.s_e_by_tile[a][o]!==undefined){for(var n=0,t=this.s_e_by_tile[a][o].length;n<t;n++){var r=this.s_e_by_tile[a][o][n];if(e>r[0]&&c<r[1]){m=false;break}}}if(m){if(this.s_e_by_tile[a][o]===undefined){this.s_e_by_tile[a][o]=[]}this.s_e_by_tile[a][o].push([c,e]);this.inc_slots[a][d.uid]=o;g=Math.max(g,o);break}o++}}return g},draw_tile:function(B,f,g,M){if(!this.values){return}var s=f*DENSITY*B,G=(f+1)*DENSITY*B,r=DENSITY*B;var K,L,m;if(M>this.show_labels_scale){if(!this.showing_details){this.showing_details=true}for(var H in this.data_cache.obj_cache){var C=H.split("_"),z=C[0],c=C[1];if(z<=s&&c>=G){K=this.data_cache.get(H);break}}if(!K){this.data_queue[[s,G]]=true;this.get_data(s,G);return}m=this.incremental_slots(this.view.zoom_res,K)*this.vertical_detail_px+15;L=this.inc_slo
ts[this.view.zoom_res]}else{if(this.showing_details){this.showing_details=false}m=this.height_px;L=this.zo_slots;K=this.values}var a=Math.ceil(r*M),u=$("<canvas class='tile'></canvas>"),D=this.prefs.label_color,e=this.prefs.block_color,x=this.left_offset,N=this.showing_details,O=(this.showing_details?this.vertical_detail_px:this.vertical_nodetail_px);u.css({position:"absolute",top:0,left:(s-this.view.low)*M-x});u.get(0).width=a+x;u.get(0).height=m;var p=u.get(0).getContext("2d");p.fillStyle=this.prefs.block_color;p.font=this.default_font;p.textAlign="right";var I=0;for(var J=0,o=K.length;J<o;J++){var v=K[J];if(v.start<=G&&v.end>=s){var A=Math.floor(Math.max(0,(v.start-s)*M)),q=Math.ceil(Math.min(a,(v.end-s)*M)),y=L[v.uid]*O;var n,E,t=null,P=null;if(v.thick_start&&v.thick_end){t=Math.floor(Math.max(0,(v.thick_start-s)*M));P=Math.ceil(Math.min(a,(v.thick_end-s)*M))}if(!N){p.fillRect(A+x,y+5,q-A,1)}else{if(v.start>s){p.fillStyle=D;p.fillText(v.name,A-1+x,y+8);p.fillStyle=e}var
Q=v.blocks;if(Q){if(v.strand){if(v.strand=="+"){p.fillStyle=RIGHT_STRAND}else{if(v.strand=="-"){p.fillStyle=LEFT_STRAND}}p.fillRect(A+x,y,q-A,10);p.fillStyle=e}for(var H=0,d=Q.length;H<d;H++){var h=Q[H],b=Math.floor(Math.max(0,(h[0]-s)*M)),w=Math.ceil(Math.min(a,(h[1]-s)*M));if(b>w){continue}n=5;E=3;p.fillRect(b+x,y+E,w-b,n);if(t!==undefined&&!(b>P||w<t)){n=9;E=1;var F=Math.max(b,t),l=Math.min(w,P);p.fillRect(F+x,y+E,l-F,n)}}}else{n=9;E=1;p.fillRect(A+x,y+E,q-A,n);if(v.strand){if(v.strand=="+"){p.fillStyle=RIGHT_STRAND_INV}else{if(v.strand=="-"){p.fillStyle=LEFT_STRAND_INV}}p.fillRect(A+x,y,q-A,10);p.fillStyle=prefs.block_color}}}I++}}g.append(u);return u},gen_options:function(g){var a=$("<div></div>").addClass("form-row");var d="track_"+g+"_block_color",c=$("<label></label>").attr("for",d).text("Block color:"),b=$("<input></input>").attr("id",d).attr("name",d).val(this.prefs.block_color),f="track_"+g+"_label_color",h=$("<label></label>").attr("for",f).text("Label color:"),e
=$("<input></input>").attr("id",f).attr("name",f).val(this.prefs.label_color);return a.append(c).append(b).append(h).append(e)},update_options:function(c){var a=$("#track_"+c+"_block_color").val(),b=$("#track_"+c+"_label_color").val();if(a!==this.prefs.block_color||b!==this.prefs.label_color){this.prefs.block_color=a;this.prefs.label_color=b;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(c,a,d,b){this.track_type="ReadTrack";this.tile_cache=new Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);FeatureTrack.call(this,c,a,d,b)};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{draw_tile:function(v,z,m,n){if(!this.values){return}var A=z*DENSITY*v,e=(z+1)*DENSITY*v,q=DENSITY*v;var D,p,h;h=this.height_px;p=this.zo_slots;D=this.values;var t=Math.ceil(q*n),r=$("<canvas class='tile'></canvas>");r.css({position:"absolute",top:0,left:(A-this.view.low)*n-this.left_offset});r.get(0).width=t+this.left_offset;r.get(0
).height=h;var u=r.get(0).getContext("2d");u.fillStyle=this.prefs.block_color;u.font=this.default_font;u.textAlign="right";var s=u.measureText("A").width;var w=0;for(var x=0,y=D.length;x<y;x++){var l=D[x];if(l.start<=e&&l.end>=A){var g=Math.floor(Math.max(0,(l.start-A)*n)),k=Math.ceil(Math.min(t,(l.end-A)*n)),f=p[l.uid]*this.vertical_detail_px;var a,E,d=null,o=null;if(n>s){for(var B=0,b=l.name.length;B<b;B++){var C=Math.floor(Math.max(0,(l.start+B-A)*n));u.fillText(l.name[B],C+this.left_offset,f+8)}}else{u.fillRect(g+this.left_offset,f+4,k-g,3)}}}m.append(r);return r}});
\ No newline at end of file
+var DEBUG=false;var DENSITY=1000,FEATURE_LEVELS=10,DATA_ERROR="There was an error in indexing this dataset.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=20,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src="../images/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src="../images/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src="../images/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src="../images/visualization/strand_left_inv.png";left_i
mg_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(b,d,c,a){this.vis_id=c;this.dbkey=a;this.title=d;this.chrom=b;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.center=(this.max_high-this.max_low)/2;this.zoom_factor=3;this.zoom_level=0;this.track_id_counter=0};$.extend(View.prototype,{add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.trac
ks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[a]},update_options:function(){var b=$("ul#sortable-ul").sortable("toArray");var d=[];var c=$("#viewport > div").sort(function(g,f){return b.indexOf($(g).attr("id"))>b.indexOf($(f).attr("id"))});$("#viewport > div").remove();$("#viewport").html(c);for(var e in view.tracks){var a=view.tracks[e];if(a.update_options){a.update_options(e)}}},redraw:function(f){this.span=this.max_high-this.max_low;var d=this.span/Math.pow(this.zoom_factor,this.zoom_level),b=this.center-(d/2),e=b+d;if(b<0){b=0;e=b+d}else{if(e>this.max_high){e=this.max_high;b=e-d}}this.low=Math.floor(b);this.high=Math.ceil(e);this.center=Math.round(this.low+(this.high-this.low)/2);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low
)/DENSITY)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));$("#overview-box").css({left:(this.low/this.span)*$("#overview-viewport").width(),width:Math.max(12,((this.high-this.low)/this.span)*$("#overview-viewport").width())}).show();$("#low").val(commatize(this.low));$("#high").val(commatize(this.high));if(!f){for(var c=0,a=this.tracks.length;c<a;c++){this.tracks[c].draw()}for(var c=0,a=this.label_tracks.length;c<a;c++){this.label_tracks[c].draw()}}},zoom_in:function(a){if(this.max_high===0||this.high-this.low<30){return}if(a){this.center=a/$(document).width()*(this.high-this.low)+this.low}this.zoom_level+=1;this.redraw()},zoom_out:function(){if(this.max_high===0){return}if(this.zoom_level<=0){this.zoom_level=0;return}this.zoom_level-=1;this.redraw()}});var Track=function(a,b){this.name=a;this.parent_element=b;this.init_global()};$.extend(Track.prototype,{init_global:function(){this.
header_div=$("<div class='track-header'>").text(this.name);this.content_div=$("<div class='track-content'>");this.container_div=$("<div></div>").addClass("track").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)}});var TiledTrack=function(){};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var i=this.view.low,e=this.view.high,f=e-i,d=this.view.resolution;if(DEBUG){$("#debug").text(d+" "+this.view.zoom_res)}var k=$("<div style='position: relative;'></div>");this.content_div.children(":first").remove();this.content_div.append(k);var l=this.content_div.width()/f;var h;var a=Math.floor(i/d/DENSITY);while((a*DENSITY*d)<e){var j=this.content_div.width()+"_"+this.view.zoom_level+"_"+a;var c=this.tile_cache.get(j);if(c){var g=a*DENSITY*d;var b=(g-i)*l;if(this.left_offset){b-=this.left_offset}c.css({left:b});k.append(c);this.max_height=Math.max(this.max_height,c.height())}else{this.delayed_draw(this,j,i,e,a,d,k,l)}a+=1}},d
elayed_draw:function(c,e,a,f,b,d,g,h){setTimeout(function(){if(!(a>c.view.high||f<c.view.low)){tile_element=c.draw_tile(d,b,g,h);if(tile_element){c.tile_cache.set(e,tile_element);c.max_height=Math.max(c.max_height,tile_element.height());c.content_div.css("height",c.max_height)}}},50)}});var LabelTrack=function(a){Track.call(this,null,a);this.track_type="LabelTrack";this.hidden=true;this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var LineTrack=function(c,a,d,b){this.track_type="LineTrack";this.tile_cache=new
Cache(CACHED_TILES_LINE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.indexer=d;this.height_px=100;this.container_div.addClass("line-track");this.dataset_id=a;this.prefs={min_value:undefined,max_value:undefined};if(b.min_value!==undefined){this.prefs.min_value=b.min_value}if(b.max_value!==undefined){this.prefs.max_value=b.max_value}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){this.data_queue={};this.data_cache=new Cache(CACHED_DATA);var a=this,b=a.view.tracks.indexOf(a);a.content_div.text(DATA_LOADING);a.container_div.removeClass("nodata error pending");$.getJSON(data_url,{stats:true,indexer:a.indexer,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(d){if(!d||d=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(d.length===0||d=="no data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d=="pending"){a.container_div.addClass("pending");a.content_div.text(DAT
A_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");if(a.prefs.min_value===undefined||a.prefs.max_value===undefined){a.prefs.min_value=d.min;a.prefs.max_value=d.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;if($("#linetrack_"+b+"_minval").length===0){var e=$("<div></div>").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(a.prefs.min_value);var c=$("<div></div>").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(a.prefs.max_value);c.css({position:"relative",top:"25px"});c.prependTo(a.container_div);e.css({position:"relative",top:a.height_px+55+"px"});e.prependTo(a.container_div)}a.draw()}}}})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.getJSON(data_url,{indexer:this.indexer,chrom:this.view.chrom,lo
w:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()})}},draw_tile:function(n,p,c,e){if(this.vertical_range===undefined){return}var q=p*DENSITY*n,a=DENSITY*n,b=$("<canvas class='tile'></canvas>"),s=n+"_"+p;if(!this.data_cache.get(s)){this.get_data(n,p);return}var r=this.data_cache.get(s);b.css({position:"absolute",top:0,left:(q-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var m=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,f=this.prefs.max_value,l=this.vertical_range,d=this.height_px;m.beginPath();for(var o=0;o<r.length-1;o++){var h=r[o][0]-q;var g=r[o][1];if(isNaN(g)){j=false}else{h=h*e;if(g<=k){g=k}else{if(g>=f){g=f}}g=Math.round(d-(g-k)/l*d);if(j){m.lineTo(h,g)}else{m.moveTo(h,g);j=true}}}m.stroke();c.append(b);return b},gen_options:function(j){var a=$("<div></div>").addClass("form-row");var e="track_"+j+"_minval",g="track_"+j+"_maxval",h=$("<l
abel></label>").attr("for",e).text("Min value:"),b=(this.prefs.min_value===undefined?"":this.prefs.min_value),i=$("<input></input>").attr("id",e).val(b),d=$("<label></label>").attr("for",g).text("Max value:"),f=(this.prefs.max_value===undefined?"":this.prefs.max_value),c=$("<input></input>").attr("id",g).val(f);return a.append(h).append(i).append(d).append(c)},update_options:function(c){var a=$("#track_"+c+"_minval").val(),b=$("#track_"+c+"_maxval").val();if(a!==this.prefs.min_value||b!==this.prefs.max_value){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(b);this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+c+"_minval").text(this.prefs.min_value);$("#linetrack_"+c+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(c,a,d,b){this.track_type="FeatureTrack";this.tile_cache=new Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.indexer=d;this.
height_px=100;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=3;this.default_font="9px Monaco, Lucida Console, monospace";this.left_offset=200;this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.data_cache=new Cache(20);this.prefs={block_color:"black",label_color:"black"};if(b.block_color!==undefined){this.prefs.block_color=b.block_color}if(b.label_color!==undefined){this.prefs.label_color=b.label_color}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this;a.content_div.text(DATA_LOADING);a.container_div.removeClass("nodata error pending");$.getJSON(data_url,{indexer:a.indexer,low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(b=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(b.length===0||b=="no data"){a.container_d
iv.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(b=="pending"){a.container_div.adClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.values=b;a.calc_slots();a.slots=a.zo_slots;a.draw()}}}})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{indexer:b.indexer,chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,include_blocks:true},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},calc_slots:function(){var b=[],a=this.content_div.width()/(this.view.high-this.view.low),d=this.view.max_low;for(var e=0,f=this.values.length;e<f;e++){var g,h,k=this.values[e];g=Math.floor((k.start-d)*a);h=Math.ceil((k.end-d)*a);var c=0;while(true){if(b[c]===undefined||b[c]<g){b[c]=h;this.zo_slots[k.uid]=c;break}c++}}this.height_px=b.length*this.vertical_nodetail_px+15;this.content_div.css("height",thi
s.height_px+"px")},incremental_slots:function(a,f){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=1/a;this.s_e_by_tile[a]={}}var h=this.inc_slots[a].w_scale,s=[],g=0,b=$("<canvas></canvas>").get(0).getContext("2d"),l=this.view.max_low;var c,e,u=[];for(var p=0,q=f.length;p<q;p++){var d=f[p];if(this.inc_slots[a][d.uid]!==undefined){g=Math.max(g,this.inc_slots[a][d.uid]);u.push(this.inc_slots[a][d.uid])}else{s.push(p)}}for(var p=0,q=s.length;p<q;p++){var d=f[s[p]];c=Math.floor((d.start-l)*h);c-=b.measureText(d.name).width;e=Math.ceil((d.end-l)*h);var o=0;while(true){var m=true;if(this.s_e_by_tile[a][o]!==undefined){for(var n=0,t=this.s_e_by_tile[a][o].length;n<t;n++){var r=this.s_e_by_tile[a][o][n];if(e>r[0]&&c<r[1]){m=false;break}}}if(m){if(this.s_e_by_tile[a][o]===undefined){this.s_e_by_tile[a][o]=[]}this.s_e_by_tile[a][o].push([c,e]);this.inc_slots[a][d.uid]=o;g=Math.max(g,o);break}o++}}return g},draw_tile:function(B,f,g,M){if(!this.values){return}var
s=f*DENSITY*B,G=(f+1)*DENSITY*B,r=DENSITY*B;var K,L,m;if(M>this.show_labels_scale){if(!this.showing_details){this.showing_details=true}for(var H in this.data_cache.obj_cache){var C=H.split("_"),z=C[0],c=C[1];if(z<=s&&c>=G){K=this.data_cache.get(H);break}}if(!K){this.data_queue[[s,G]]=true;this.get_data(s,G);return}m=this.incremental_slots(this.view.zoom_res,K)*this.vertical_detail_px+15;L=this.inc_slots[this.view.zoom_res]}else{if(this.showing_details){this.showing_details=false}m=this.height_px;L=this.zo_slots;K=this.values}var a=Math.ceil(r*M),u=$("<canvas class='tile'></canvas>"),D=this.prefs.label_color,e=this.prefs.block_color,x=this.left_offset,N=this.showing_details,O=(this.showing_details?this.vertical_detail_px:this.vertical_nodetail_px);u.css({position:"absolute",top:0,left:(s-this.view.low)*M-x});u.get(0).width=a+x;u.get(0).height=m;var p=u.get(0).getContext("2d");p.fillStyle=this.prefs.block_color;p.font=this.default_font;p.textAlign="right";var I=0;for(var J=0,o
=K.length;J<o;J++){var v=K[J];if(v.start<=G&&v.end>=s){var A=Math.floor(Math.max(0,(v.start-s)*M)),q=Math.ceil(Math.min(a,(v.end-s)*M)),y=L[v.uid]*O;var n,E,t=null,P=null;if(v.thick_start&&v.thick_end){t=Math.floor(Math.max(0,(v.thick_start-s)*M));P=Math.ceil(Math.min(a,(v.thick_end-s)*M))}if(!N){p.fillRect(A+x,y+5,q-A,1)}else{if(v.start>s){p.fillStyle=D;p.fillText(v.name,A-1+x,y+8);p.fillStyle=e}var Q=v.blocks;if(Q){if(v.strand){if(v.strand=="+"){p.fillStyle=RIGHT_STRAND}else{if(v.strand=="-"){p.fillStyle=LEFT_STRAND}}p.fillRect(A+x,y,q-A,10);p.fillStyle=e}for(var H=0,d=Q.length;H<d;H++){var h=Q[H],b=Math.floor(Math.max(0,(h[0]-s)*M)),w=Math.ceil(Math.min(a,(h[1]-s)*M));if(b>w){continue}n=5;E=3;p.fillRect(b+x,y+E,w-b,n);if(t!==undefined&&!(b>P||w<t)){n=9;E=1;var F=Math.max(b,t),l=Math.min(w,P);p.fillRect(F+x,y+E,l-F,n)}}}else{n=9;E=1;p.fillRect(A+x,y+E,q-A,n);if(v.strand){if(v.strand=="+"){p.fillStyle=RIGHT_STRAND_INV}else{if(v.strand=="-"){p.fillStyle=LEFT_STRAND_INV}}p.fi
llRect(A+x,y,q-A,10);p.fillStyle=prefs.block_color}}}I++}}g.append(u);return u},gen_options:function(g){var a=$("<div></div>").addClass("form-row");var d="track_"+g+"_block_color",c=$("<label></label>").attr("for",d).text("Block color:"),b=$("<input></input>").attr("id",d).attr("name",d).val(this.prefs.block_color),f="track_"+g+"_label_color",h=$("<label></label>").attr("for",f).text("Label color:"),e=$("<input></input>").attr("id",f).attr("name",f).val(this.prefs.label_color);return a.append(c).append(b).append(h).append(e)},update_options:function(c){var a=$("#track_"+c+"_block_color").val(),b=$("#track_"+c+"_label_color").val();if(a!==this.prefs.block_color||b!==this.prefs.label_color){this.prefs.block_color=a;this.prefs.label_color=b;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(c,a,d,b){this.track_type="ReadTrack";this.tile_cache=new Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);FeatureTrack.call(this,c,a,d,b)};$.ex
tend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{draw_tile:function(v,z,m,n){if(!this.values){return}var A=z*DENSITY*v,e=(z+1)*DENSITY*v,q=DENSITY*v;var D,p,h;h=this.height_px;p=this.zo_slots;D=this.values;var t=Math.ceil(q*n),r=$("<canvas class='tile'></canvas>");r.css({position:"absolute",top:0,left:(A-this.view.low)*n-this.left_offset});r.get(0).width=t+this.left_offset;r.get(0).height=h;var u=r.get(0).getContext("2d");u.fillStyle=this.prefs.block_color;u.font=this.default_font;u.textAlign="right";var s=u.measureText("A").width;var w=0;for(var x=0,y=D.length;x<y;x++){var l=D[x];if(l.start<=e&&l.end>=A){var g=Math.floor(Math.max(0,(l.start-A)*n)),k=Math.ceil(Math.min(t,(l.end-A)*n)),f=p[l.uid]*this.vertical_detail_px;var a,E,d=null,o=null;if(n>s){for(var B=0,b=l.name.length;B<b;B++){var C=Math.floor(Math.max(0,(l.start+B-A)*n));u.fillText(l.name[B],C+this.left_offset,f+8)}}else{u.fillRect(g+this.left_offset,f+4,k-g,3)}}}m.append(r);return r}});
\ No newline at end of file
diff -r 6dff2f938898 -r 29ece93d429c templates/history/rename.mako
--- a/templates/history/rename.mako Wed Feb 10 16:02:11 2010 -0500
+++ b/templates/history/rename.mako Wed Feb 10 18:25:32 2010 -0500
@@ -1,4 +1,3 @@
-<% _=n_ %>
<%inherit file="/base.mako"/>
<%def name="title()">${_('Rename History')}</%def>
@@ -19,10 +18,10 @@
<tr>
<td>
<input type="hidden" name="id" value="${trans.security.encode_id( history.id )}">
- ${history.get_display_name()}
+ ${history.get_display_name() | h}
</td>
<td>
- <input type="text" name="name" value="${history.get_display_name()}" size="40">
+ <input type="text" name="name" value="${history.get_display_name() | h}" size="40">
</td>
</tr>
%endfor
1
0
11 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/6dff2f938898
changeset: 3370:6dff2f938898
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Wed Feb 10 16:02:11 2010 -0500
description:
Typo bug fix in tool_runner, should once again be able to upload a new version of a library_dataset.
diffstat:
lib/galaxy/web/controllers/tool_runner.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (12 lines):
diff -r 44cada534e33 -r 6dff2f938898 lib/galaxy/web/controllers/tool_runner.py
--- a/lib/galaxy/web/controllers/tool_runner.py Wed Feb 10 15:27:58 2010 -0500
+++ b/lib/galaxy/web/controllers/tool_runner.py Wed Feb 10 16:02:11 2010 -0500
@@ -160,7 +160,7 @@
if nonfile_params.get( 'folder_id', False ):
replace_id = nonfile_params.get( 'replace_id', None )
if replace_id not in [ None, 'None' ]:
- replace_dataset = trans.sa_session.query( l.LibraryDataset ).get( trans.security.decode_id( replace_id ) )
+ replace_dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( trans.security.decode_id( replace_id ) )
else:
replace_dataset = None
library_bunch = upload_common.handle_library_params( trans, nonfile_params, nonfile_params.folder_id, replace_dataset )
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/44cada534e33
changeset: 3369:44cada534e33
user: Kanwei Li <kanwei(a)gmail.com>
date: Wed Feb 10 15:27:58 2010 -0500
description:
unpublish typo
diffstat:
lib/galaxy/web/controllers/history.py | 2 +-
lib/galaxy/web/controllers/page.py | 2 +-
lib/galaxy/web/controllers/workflow.py | 4 ++--
templates/sharing_base.mako | 2 +-
templates/workflow/sharing.mako | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)
diffs (69 lines):
diff -r 773273b96ff4 -r 44cada534e33 lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Wed Feb 10 15:13:46 2010 -0500
+++ b/lib/galaxy/web/controllers/history.py Wed Feb 10 15:27:58 2010 -0500
@@ -563,7 +563,7 @@
history.importable = False
elif 'unpublish' in kwargs:
history.published = False
- elif 'disable_link_access_and_unpubish' in kwargs:
+ elif 'disable_link_access_and_unpublish' in kwargs:
history.importable = history.published = False
elif 'unshare_user' in kwargs:
user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( kwargs[ 'unshare_user' ] ) )
diff -r 773273b96ff4 -r 44cada534e33 lib/galaxy/web/controllers/page.py
--- a/lib/galaxy/web/controllers/page.py Wed Feb 10 15:13:46 2010 -0500
+++ b/lib/galaxy/web/controllers/page.py Wed Feb 10 15:27:58 2010 -0500
@@ -394,7 +394,7 @@
page.importable = False
elif 'unpublish' in kwargs:
page.published = False
- elif 'disable_link_access_and_unpubish' in kwargs:
+ elif 'disable_link_access_and_unpublish' in kwargs:
page.importable = page.published = False
elif 'unshare_user' in kwargs:
user = session.query( model.User ).get( trans.security.decode_id( kwargs['unshare_user' ] ) )
diff -r 773273b96ff4 -r 44cada534e33 lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py Wed Feb 10 15:13:46 2010 -0500
+++ b/lib/galaxy/web/controllers/workflow.py Wed Feb 10 15:27:58 2010 -0500
@@ -262,7 +262,7 @@
stored.importable = False
elif 'unpublish' in kwargs:
stored.published = False
- elif 'disable_link_access_and_unpubish' in kwargs:
+ elif 'disable_link_access_and_unpublish' in kwargs:
stored.importable = stored.published = False
elif 'unshare_user' in kwargs:
user = session.query( model.User ).get( trans.security.decode_id( kwargs['unshare_user' ] ) )
@@ -477,7 +477,7 @@
def editor( self, trans, id=None ):
"""
Render the main workflow editor interface. The canvas is embedded as
- an iframe (neccesary for scrolling to work properly), which is
+ an iframe (necessary for scrolling to work properly), which is
rendered by `editor_canvas`.
"""
if not id:
diff -r 773273b96ff4 -r 44cada534e33 templates/sharing_base.mako
--- a/templates/sharing_base.mako Wed Feb 10 15:13:46 2010 -0500
+++ b/templates/sharing_base.mako Wed Feb 10 15:27:58 2010 -0500
@@ -153,7 +153,7 @@
<input class="action-button" type="submit" name="unpublish" value="Unpublish ${item_class_name}">
<div class="toolParamHelp">Removes ${item_class_name_lc} from Galaxy's <a href='${h.url_for( action='list_published' )}' target="_top">Published ${item_class_plural_name}</a> section so that it is not publicly listed or searchable.</div>
<br>
- <input class="action-button" type="submit" name="disable_link_access_and_unpubish" value="Disable Access to ${item_class_name} via Link and Unpublish">
+ <input class="action-button" type="submit" name="disable_link_access_and_unpublish" value="Disable Access to ${item_class_name} via Link and Unpublish">
<div class="toolParamHelp">Disables ${item_class_name_lc}'s link so that it is not accessible and removes ${item_class_name_lc} from Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published ${item_class_plural_name}</a> section so that it is not publicly listed or searchable.</div>
%endif
diff -r 773273b96ff4 -r 44cada534e33 templates/workflow/sharing.mako
--- a/templates/workflow/sharing.mako Wed Feb 10 15:13:46 2010 -0500
+++ b/templates/workflow/sharing.mako Wed Feb 10 15:27:58 2010 -0500
@@ -82,7 +82,7 @@
<input class="action-button" type="submit" name="unpublish" value="Unpublish Workflow">
<div class="toolParamHelp">Removes workflow from Galaxy's <a href='${h.url_for( action='list_published' )}'>Published Workflows</a> section so that it is not publicly listed or searchable.</div>
<br>
- <input class="action-button" type="submit" name="disable_link_access_and_unpubish" value="Disable Access to Workflow via Link and Unpublish">
+ <input class="action-button" type="submit" name="disable_link_access_and_unpublish" value="Disable Access to Workflow via Link and Unpublish">
<div class="toolParamHelp">Disables workflow's link so that it is not accessible and removes workflow from Galaxy's <a href='${h.url_for( action='list_published' )}' target='_top'>Published Workflows</a> section so that it is not publicly listed or searchable.</div>
%endif
1
0