galaxy-commits
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
March 2014
- 1 participants
- 170 discussions
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/18fa1f7340b3/
Changeset: 18fa1f7340b3
Branch: stable
User: natefoo
Date: 2014-03-06 22:58:22
Summary: Fix incorrect example of remote_user_header in sample config.
Affected #: 1 file
diff -r ccfb1805efd075ebb2ab56f4b75509e7d6d99ebb -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -606,7 +606,7 @@
# by WSGI). This option allows you to change the header. Note, you still need
# to prepend 'HTTP_' to the header in this option, but your proxy server should
# *not* include 'HTTP_' at the beginning of the header name.
-#remote_user_header = 'HTTP_REMOTE_USER'
+#remote_user_header = HTTP_REMOTE_USER
# If use_remote_user is enabled, you can set this to a URL that will log your
# users out.
https://bitbucket.org/galaxy/galaxy-central/commits/c58e14ae86d1/
Changeset: c58e14ae86d1
User: natefoo
Date: 2014-03-06 22:59:19
Summary: merge stable.
Affected #: 1 file
diff -r d2ba52e5ec11909a058c698d625aa139aa3c78d4 -r c58e14ae86d182f8152edbfe2569857da54ccb49 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -616,7 +616,7 @@
# by WSGI). This option allows you to change the header. Note, you still need
# to prepend 'HTTP_' to the header in this option, but your proxy server should
# *not* include 'HTTP_' at the beginning of the header name.
-#remote_user_header = 'HTTP_REMOTE_USER'
+#remote_user_header = HTTP_REMOTE_USER
# If use_remote_user is enabled, you can set this to a URL that will log your
# users out.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: davebgx: Pass raw strings to handle_command so that python won't automatically unescape the double quotes being sent on to subprocess.Popen.
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d2ba52e5ec11/
Changeset: d2ba52e5ec11
User: davebgx
Date: 2014-03-06 22:03:49
Summary: Pass raw strings to handle_command so that python won't automatically unescape the double quotes being sent on to subprocess.Popen.
Affected #: 1 file
diff -r 03f935bb636e0f4fa63782ce5d6a551ac508144a -r d2ba52e5ec11909a058c698d625aa139aa3c78d4 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -604,7 +604,7 @@
return tool_dependency
else:
install_environment.add_env_shell_file_paths( env_shell_file_paths )
- log.debug( 'Handling setup_r_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s"' % \
+ log.debug( 'Handling setup_r_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \
( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) )
tarball_names = []
for url in action_dict[ 'r_packages' ]:
@@ -616,8 +616,10 @@
with lcd( current_dir ):
with settings( warn_only=True ):
for tarball_name in tarball_names:
- cmd = '''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
- Rscript -e \\"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\\"''' % \
+ # Use raw strings so that python won't automatically unescape the \", needed because handle_command wraps
+ # the provided command in /bin/sh -c "<command>".
+ cmd = r'''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
+ Rscript -e \"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\"''' % \
( str( tarball_name ) )
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
return_code = handle_command( app, tool_dependency, install_dir, cmd )
@@ -649,7 +651,7 @@
return tool_dependency
else:
install_environment.add_env_shell_file_paths( env_shell_file_paths )
- log.debug( 'Handling setup_ruby_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s"' % \
+ log.debug( 'Handling setup_ruby_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \
( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) )
dir = os.path.curdir
current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
@@ -672,9 +674,11 @@
else:
# gem file from rubygems.org with or without version number
if gem_version:
- # version number was specified
- cmd = '''PATH=$PATH:$RUBY_HOME/bin; export PATH; GEM_HOME=$INSTALL_DIR; export GEM_HOME;
- gem install %s --version "=%s"''' % ( gem, gem_version)
+ # Specific ruby gem version was requested.
+ # Use raw strings so that python won't automatically unescape the \", needed because handle_command wraps
+ # the provided command in /bin/sh -c "<command>".
+ cmd = r'''PATH=$PATH:$RUBY_HOME/bin; export PATH; GEM_HOME=$INSTALL_DIR; export GEM_HOME;
+ gem install %s --version \"=%s\"''' % ( gem, gem_version)
else:
# no version number given
cmd = '''PATH=$PATH:$RUBY_HOME/bin; export PATH; GEM_HOME=$INSTALL_DIR; export GEM_HOME;
@@ -708,7 +712,7 @@
return tool_dependency
else:
install_environment.add_env_shell_file_paths( env_shell_file_paths )
- log.debug( 'Handling setup_perl_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s"' % \
+ log.debug( 'Handling setup_perl_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \
( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) )
dir = os.path.curdir
current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
@@ -831,7 +835,9 @@
return_code = handle_command( app, tool_dependency, install_dir, full_setup_command )
if return_code:
return tool_dependency
- site_packages_command = "%s -c 'import os, sys; print os.path.join(sys.prefix, \"lib\", \"python\" + sys.version[:3], \"site-packages\")'" % os.path.join( venv_directory, "bin", "python" )
+ # Use raw strings so that python won't automatically unescape the \", needed because handle_command wraps
+ # the provided command in /bin/sh -c "<command>".
+ site_packages_command = r"%s -c 'import os, sys; print os.path.join(sys.prefix, \"lib\", \"python\" + sys.version[:3], \"site-packages\")'" % os.path.join( venv_directory, "bin", "python" )
output = handle_command( app, tool_dependency, install_dir, site_packages_command, return_output=True )
if output.return_code:
return tool_dependency
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Charts: Add job cleanup procedure, handle multiple job requests
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/03f935bb636e/
Changeset: 03f935bb636e
User: guerler
Date: 2014-03-06 22:02:55
Summary: Charts: Add job cleanup procedure, handle multiple job requests
Affected #: 5 files
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/charts/histogram.js
--- a/config/plugins/visualizations/charts/static/charts/histogram.js
+++ b/config/plugins/visualizations/charts/static/charts/histogram.js
@@ -29,6 +29,7 @@
// send request
var self = this;
this.app.datasets.request(request_dictionary, function(data) {
+ chart.set('state', 'ok');
nv.addGraph(function() {
self.d3_chart = nv.models.multiBarChart();
@@ -39,8 +40,6 @@
.call(self.d3_chart);
nv.utils.windowResize(self.d3_chart.update);
-
- chart.set('state', 'ok');
});
});
}
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/library/jobs.js
--- a/config/plugins/visualizations/charts/static/library/jobs.js
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -28,24 +28,29 @@
// configure tool
data = {
'tool_id' : 'rkit',
- 'history_id' : chart.history_id,
+ 'history_id' : chart.get('history_id'),
'inputs' : {
- 'input' : chart.dataset_hid,
+ 'input' : chart.get('dataset_hid'),
'module' : chart_type,
'options' : request_string
}
}
+ // cleanup previous dataset file
+ var previous = chart.get('dataset_id_job');
+ if (previous) {
+ Utils.request('PUT', config.root + 'api/histories/' + chart.get('history_id') + '/contents/' + previous, { deleted: true });
+ }
+
// set chart state
chart.state('submit', 'Sending job request...');
-
+
// post job
Utils.request('POST', config.root + 'api/tools', data,
// success handler
function(response) {
if (!response.outputs || response.outputs.length == 0) {
chart.state('failed', 'Job submission failed. No response.');
- self.app.log('handle::load()', 'Job submission failed.');
} else {
// update galaxy history
if (Galaxy && Galaxy.currHistoryPanel) {
@@ -65,7 +70,7 @@
self._loop(job.id, function(job) {
switch (job.state) {
case 'ok':
- chart.state('ok', 'Job completed successfully...');
+ chart.state('success', 'Job completed successfully...');
callback(job);
return true;
case 'error':
@@ -80,8 +85,7 @@
},
// error handler
function(response) {
- chart.state('failed', 'Job submission failed.');
- self.app.log('handle::load()', 'Job submission failed.');
+ chart.state('failed', 'Job submission failed. Please make sure that \'R-kit\' is installed.');
}
);
},
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -11,7 +11,7 @@
title : '',
type : '',
date : null,
- state : '',
+ state : 'ok',
state_info : ''
},
@@ -44,6 +44,10 @@
state: function(value, info) {
this.set('state_info', info);
this.set('state', value);
+ },
+
+ ready: function() {
+ return (this.get('state') == 'ok') || (this.get('state') == 'failed');
}
});
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -286,7 +286,7 @@
}
// trigger redraw
- current.set('state', 'redraw');
+ current.trigger('redraw', current);
}
});
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/views/viewport.js
--- a/config/plugins/visualizations/charts/static/views/viewport.js
+++ b/config/plugins/visualizations/charts/static/views/viewport.js
@@ -48,10 +48,18 @@
self._removeChart(chart.id);
});
- // replace
- this.app.charts.on('change', function(chart) {
- if (chart.get('state') == 'redraw') {
+ // redraw
+ this.app.charts.on('redraw', function(chart) {
+ // redraw if chart is not currently processed
+ if (chart.ready()) {
self._refreshChart(chart);
+ } else {
+ // redraw once current drawing process has finished
+ chart.on('change:state', function() {
+ if (chart.ready()) {
+ self._refreshChart(chart);
+ }
+ });
}
});
},
@@ -111,6 +119,12 @@
// link this
var self = this;
+ // check
+ if (!chart.ready()) {
+ self.app.log('viewport:_refreshChart()', 'Invalid attempt to refresh chart before completion.');
+ return;
+ }
+
// backup chart details
var chart_id = chart.id;
@@ -138,6 +152,9 @@
// show chart from list
this.showChart(chart_id);
+ // clear all previous handlers (including redraw listeners)
+ chart.off('change:state');
+
// link status handler
chart.on('change:state', function() {
// get info element
@@ -185,10 +202,10 @@
var mode = chart_settings.mode;
if (mode == 'execute') {
self.app.jobs.submit(chart, self._defaultRequestString(chart), function() {
- view.plot(chart, self._defaultRequestDictionary(chart))
+ view.plot(chart, self._defaultRequestDictionary(chart));
});
} else {
- view.plot(chart, self._defaultRequestDictionary(chart))
+ view.plot(chart, self._defaultRequestDictionary(chart));
}
});
},
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Enhance Tools Verified grid column in the tool shed to be useful for Tool dependency definitions repositories as well as Unrestricted repositories that contain tools.
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7f4aa510ab2c/
Changeset: 7f4aa510ab2c
User: greg
Date: 2014-03-06 21:26:02
Summary: Enhance Tools Verified grid column in the tool shed to be useful for Tool dependency definitions repositories as well as Unrestricted repositories that contain tools.
Affected #: 1 file
diff -r ac45b47a15693c9cc71050c9dd16a4ed6738d1a9 -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -5,8 +5,10 @@
from galaxy.model.orm import and_
from galaxy.model.orm import or_
from galaxy.util import json
+from galaxy.util import listify
import tool_shed.util.shed_util_common as suc
import tool_shed.grids.util as grids_util
+import tool_shed.repository_types.util as rt_util
from tool_shed.util import metadata_util
from galaxy import eggs
@@ -159,16 +161,41 @@
def get_value( self, trans, grid, repository ):
# This column will display the value associated with the currently displayed metadata revision.
- try:
- displayed_metadata_revision = repository.metadata_revisions[ -1 ]
- if displayed_metadata_revision.includes_tools:
- if displayed_metadata_revision.tools_functionally_correct:
- return 'yes'
+ if repository.type == rt_util.UNRESTRICTED:
+ try:
+ displayed_metadata_revision = repository.metadata_revisions[ -1 ]
+ if displayed_metadata_revision.includes_tools:
+ if displayed_metadata_revision.tools_functionally_correct:
+ return 'yes'
+ else:
+ return 'no'
+ return 'n/a'
+ except Exception, e:
+ log.exception( str( e ) )
+ return 'unknown'
+ else:
+ # Here repository.type must be rt_util.TOOL_DEPENDENCY_DEFINITION.
+ try:
+ displayed_metadata_revision = repository.metadata_revisions[ -1 ]
+ if displayed_metadata_revision.test_install_error:
+ return 'no'
+ tool_test_results = listify( displayed_metadata_revision.tool_test_results )
+ if len( tool_test_results ) > 0:
+ last_tool_test_result = tool_test_results[ 0 ]
+ installation_error_dict = last_tool_test_result.get( 'installation_errors', {} )
+ if len( installation_error_dict ) > 0:
+ current_repository_installation_error_dicts = installation_error_dict.get( 'current_repository', [] )
+ if len( current_repository_installation_error_dicts ) > 0:
+ return 'no'
+ else:
+ return 'yes'
+ else:
+ return 'yes'
else:
return 'no'
- return 'n/a'
- except:
- return 'n/a'
+ except Exception, e:
+ log.exception( str( e ) )
+ return 'unknown'
class DescriptionColumn( grids.TextColumn ):
@@ -247,7 +274,7 @@
attach_popup=False ),
TypeColumn( "Type" ),
MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
@@ -404,7 +431,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
@@ -452,7 +479,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.CategoryColumn( "Category",
model_class=model.Category,
key="Category.name",
@@ -489,7 +516,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( controller="repository", operation="repositories_by_user", id=item.id ) ),
@@ -538,7 +565,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.DeprecatedColumn( "Deprecated" )
]
columns.append( grids.MulticolFilterColumn( "Search repository name",
@@ -566,7 +593,7 @@
attach_popup=False ),
RepositoryGrid.UserColumn( "Owner" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.DeprecatedColumn( "Deprecated" )
]
columns.append( grids.MulticolFilterColumn( "Search repository name",
@@ -874,7 +901,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoriesIOwnGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoriesIOwnGrid.CategoryColumn( "Category",
model_class=model.Category,
key="Category.name",
@@ -1697,7 +1724,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
InstallableRevisionColumn( "Installable Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.UserColumn( "Owner",
model_class=model.User,
attach_popup=False ),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: martenson: API libraries improvements, easier prefixing to folders, some refactoring
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ac45b47a1569/
Changeset: ac45b47a1569
User: martenson
Date: 2014-03-06 20:20:21
Summary: API libraries improvements, easier prefixing to folders, some refactoring
Affected #: 1 file
diff -r f5a119ac52a957204ab968a78638fe2a942c6893 -r ac45b47a15693c9cc71050c9dd16a4ed6738d1a9 lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -35,27 +35,23 @@
query = trans.sa_session.query( trans.app.model.Library )
deleted = util.string_as_bool( deleted )
if deleted:
- route = 'deleted_library'
query = query.filter( trans.app.model.Library.table.c.deleted == True )
else:
- route = 'library'
query = query.filter( trans.app.model.Library.table.c.deleted == False )
current_user_role_ids = [ role.id for role in trans.get_current_user_roles() ]
library_access_action = trans.app.security_agent.permitted_actions.LIBRARY_ACCESS.action
- restricted_library_ids = [ lp.library_id for lp in trans.sa_session.query( trans.model.LibraryPermissions ) \
- .filter( trans.model.LibraryPermissions.table.c.action == library_access_action ) \
- .distinct() ]
- accessible_restricted_library_ids = [ lp.library_id for lp in trans.sa_session.query( trans.model.LibraryPermissions ) \
+ restricted_library_ids = [ lp.library_id for lp in ( trans.sa_session.query( trans.model.LibraryPermissions )
+ .filter( trans.model.LibraryPermissions.table.c.action == library_access_action )
+ .distinct() ) ]
+ accessible_restricted_library_ids = [ lp.library_id for lp in ( trans.sa_session.query( trans.model.LibraryPermissions )
.filter( and_( trans.model.LibraryPermissions.table.c.action == library_access_action,
- trans.model.LibraryPermissions.table.c.role_id.in_( current_user_role_ids ) ) ) ]
+ trans.model.LibraryPermissions.table.c.role_id.in_( current_user_role_ids ) ) ) ) ]
query = query.filter( or_( not_( trans.model.Library.table.c.id.in_( restricted_library_ids ) ),
trans.model.Library.table.c.id.in_( accessible_restricted_library_ids ) ) )
libraries = []
for library in query:
- item = library.to_dict( view='element' )
- item[ 'url' ] = url_for( route, id=trans.security.encode_id( library.id ) )
- item[ 'id' ] = trans.security.encode_id( item[ 'id' ] )
- item[ 'root_folder_id' ] = 'F' + trans.security.encode_id( item[ 'root_folder_id' ] )
+ item = self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
libraries.append( item )
return libraries
@@ -91,7 +87,8 @@
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
@expose_api
def create( self, trans, payload, **kwd ):
@@ -126,7 +123,8 @@
library.root_folder = root_folder
trans.sa_session.add_all( ( library, root_folder ) )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
@expose_api
def update( self, trans, id, **kwd ):
@@ -134,7 +132,7 @@
* PATCH /api/libraries/{encoded_id}
Updates the library defined by an ``encoded_id`` with the data in the payload.
- .. note:: Currently, only admin users can update libraries.
+ .. note:: Currently, only admin users can update libraries. Also the library must not be `deleted`.
:param payload: (required) dictionary structure containing::
'name': new library's name, cannot be empty
@@ -159,7 +157,8 @@
library = None
if not library:
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
-
+ if library.deleted:
+ raise exceptions.RequestParameterInvalidException( 'You cannot modify a deleted library. Undelete it first.' )
payload = kwd.get( 'payload', None )
if payload:
name = payload.get( 'name', None )
@@ -174,7 +173,8 @@
raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
@expose_api
def delete( self, trans, id, **kwd ):
@@ -217,4 +217,24 @@
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
+
+ def _prepend_folder_prefix (self, dictionary, type='library' ):
+ """
+ In Galaxy folders have 'F' as a prefix to the encoded id to distinguish between folders and libraries
+ """
+ if not ( type in [ 'library', 'folder' ] ):
+ raise TypeError( 'Prepending is not implemented for given type of dictionary.' )
+ return_dict = dictionary
+ if type == 'library':
+ if return_dict[ 'root_folder_id' ]:
+ return_dict[ 'root_folder_id' ] = 'F' + return_dict[ 'root_folder_id' ]
+ else:
+ raise ValueError( 'Given library does not contain root_folder_id to prepend to.' )
+ elif type == 'folder':
+ if return_dict[ 'id' ]:
+ return_dict[ 'id' ] = 'F' + return_dict[ 'id' ]
+ else:
+ raise ValueError( 'Given folder does not contain id to prepend to.' )
+ return return_dict
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f5a119ac52a9/
Changeset: f5a119ac52a9
User: greg
Date: 2014-03-06 17:39:48
Summary: Fixes to handle case where a tool dependency recipe defines an <actions_group> tag set for installing pre-compiled binaries which fail to install, so the fall back recipe for installing and compileing from souce is used. Prior to this change set, the recipe from source would not work, but the install process would finish in such a way that the recipe seemed to work.
Affected #: 5 files
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -1111,10 +1111,12 @@
no_changes_checked = CheckboxField.is_checked( no_changes )
install_repository_dependencies = CheckboxField.is_checked( kwd.get( 'install_repository_dependencies', '' ) )
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
- shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
+ shed_tool_conf, tool_path, relative_install_dir = \
+ suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
repository_clone_url = suc.generate_clone_url_for_installed_repository( trans.app, tool_shed_repository )
- clone_dir = os.path.join( tool_path, suc.generate_tool_shed_repository_install_dir( repository_clone_url,
- tool_shed_repository.installed_changeset_revision ) )
+ clone_dir = os.path.join( tool_path,
+ suc.generate_tool_shed_repository_install_dir( repository_clone_url,
+ tool_shed_repository.installed_changeset_revision ) )
relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name )
tool_shed_url = suc.get_url_from_tool_shed( trans.app, tool_shed_repository.tool_shed )
tool_section = None
@@ -1123,7 +1125,8 @@
tool_panel_section_key = None
tool_panel_section_keys = []
metadata = tool_shed_repository.metadata
- # Keep track of tool dependencies defined for the current repository or those defined for any of it's repository dependencies.
+ # Keep track of tool dependencies defined for the current repository or those defined for any of
+ # it's repository dependencies.
includes_tool_dependencies = tool_shed_repository.includes_tool_dependencies
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle the selected tool panel location for loading tools included in the tool shed repository.
@@ -1137,7 +1140,8 @@
# Just in case the tool_section.id differs from tool_panel_section_id, which it shouldn't...
tool_panel_section_id = str( tool_section.id )
if tool_shed_repository.status == trans.install_model.ToolShedRepository.installation_status.UNINSTALLED:
- # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall so the repository_installation_updater will function.
+ # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall
+ # so the repository_installation_updater will function.
tool_shed_repository = suc.create_or_update_tool_shed_repository( trans.app,
tool_shed_repository.name,
tool_shed_repository.description,
@@ -1163,7 +1167,8 @@
# Entering this else block occurs only if the tool_shed_repository does not include any valid tools.
if install_repository_dependencies:
repository_dependencies = \
- repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans, tool_shed_repository )
+ repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans,
+ tool_shed_repository )
else:
repository_dependencies = None
if metadata:
@@ -1220,7 +1225,8 @@
clause_list = []
for tsr_id in tsr_ids:
clause_list.append( trans.install_model.ToolShedRepository.table.c.id == tsr_id )
- query = trans.install_model.context.current.query( trans.install_model.ToolShedRepository ).filter( or_( *clause_list ) )
+ query = trans.install_model.context.current.query( trans.install_model.ToolShedRepository ) \
+ .filter( or_( *clause_list ) )
return trans.fill_template( 'admin/tool_shed_repository/initiate_repository_installation.mako',
encoded_kwd=encoded_kwd,
query=query,
@@ -1378,7 +1384,9 @@
raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
readme_files_dict = json.from_json_string( raw_text )
tool_dependencies = metadata.get( 'tool_dependencies', None )
- repository_dependencies = repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans, tool_shed_repository )
+ repository_dependencies = \
+ repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans,
+ tool_shed_repository )
repo_info_dict = repository_util.create_repo_info_dict( trans=trans,
repository_clone_url=repository_clone_url,
changeset_revision=tool_shed_repository.installed_changeset_revision,
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -30,36 +30,43 @@
log = logging.getLogger( __name__ )
-def create_repo_info_dict( trans, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None, repository=None,
- repository_metadata=None, tool_dependencies=None, repository_dependencies=None ):
+def create_repo_info_dict( trans, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None,
+ repository=None, repository_metadata=None, tool_dependencies=None, repository_dependencies=None ):
"""
- Return a dictionary that includes all of the information needed to install a repository into a local Galaxy instance. The dictionary will also
- contain the recursive list of repository dependencies defined for the repository, as well as the defined tool dependencies.
+ Return a dictionary that includes all of the information needed to install a repository into a local
+ Galaxy instance. The dictionary will also contain the recursive list of repository dependencies defined
+ for the repository, as well as the defined tool dependencies.
This method is called from Galaxy under three scenarios:
- 1. During the tool shed repository installation process via the tool shed's get_repository_information() method. In this case both the received
- repository and repository_metadata will be objects., but tool_dependencies and repository_dependencies will be None
- 2. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with no updates available. In this case, both
- repository and repository_metadata will be None, but tool_dependencies and repository_dependencies will be objects previously retrieved from the
- tool shed if the repository includes definitions for them.
- 3. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with updates available. In this case, this
- method is reached via the tool shed's get_updated_repository_information() method, and both repository and repository_metadata will be objects
- but tool_dependencies and repository_dependencies will be None.
+ 1. During the tool shed repository installation process via the tool shed's get_repository_information()
+ method. In this case both the received repository and repository_metadata will be objects., but
+ tool_dependencies and repository_dependencies will be None.
+ 2. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with no
+ updates available. In this case, both repository and repository_metadata will be None, but tool_dependencies
+ and repository_dependencies will be objects previously retrieved from the tool shed if the repository includes
+ definitions for them.
+ 3. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with updates
+ available. In this case, this method is reached via the tool shed's get_updated_repository_information()
+ method, and both repository and repository_metadata will be objects but tool_dependencies and
+ repository_dependencies will be None.
"""
repo_info_dict = {}
repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
if trans.webapp.name == 'tool_shed':
# We're in the tool shed.
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
+ trans.security.encode_id( repository.id ),
+ changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
if metadata:
+ toolshed_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
# Get a dictionary of all repositories upon which the contents of the received repository depends.
repository_dependencies = \
repository_dependency_util.get_repository_dependencies_for_changeset_revision( trans=trans,
repository=repository,
repository_metadata=repository_metadata,
- toolshed_base_url=str( web.url_for( '/', qualified=True ) ).rstrip( '/' ),
+ toolshed_base_url=toolshed_url,
key_rd_dicts_to_be_processed=None,
all_repository_dependencies=None,
handled_key_rd_dicts=None,
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -228,24 +228,23 @@
if make_executable:
# Explicitly set the file's executable bits.
try:
- os.chmod( file_path, int( '111', base=8) | os.stat( file_path )[ stat.ST_MODE ] )
+ os.chmod( file_path, int( '111', base=8 ) | os.stat( file_path )[ stat.ST_MODE ] )
except Exception, e:
log.exception( str( e ) )
return 1
- return_code = 0
# Convert the received text to a list, in order to support adding one or more lines to the file.
if isinstance( text, basestring ):
text = [ text ]
for line in text:
line = line.rstrip()
- if line not in env_file_contents:
+ if line and line not in env_file_contents:
env_file_contents.append( line )
try:
file( file_path, 'w' ).write( '\n'.join( env_file_contents ) )
except Exception, e:
log.exception( str( e ) )
return 1
- return return_code
+ return 0
def filter_actions_after_binary_installation( actions ):
'''Filter out actions that should not be processed if a binary download succeeded.'''
@@ -262,8 +261,13 @@
env_file_builder.append_line( action="source", value=shell_file_path )
def handle_command( app, tool_dependency, install_dir, cmd, return_output=False ):
+ """
+ Handle a command by determining if it is "simple" or "complex" and redirecting appropriately and then
+ logging the results.
+ """
context = app.install_model.context
- output = handle_complex_command( cmd )
+ command = str( cmd )
+ output = handle_complex_command( command )
log_results( cmd, output, os.path.join( install_dir, INSTALLATION_LOG ) )
stdout = output.stdout
stderr = output.stderr
@@ -381,13 +385,15 @@
def handle_environment_variables( app, tool_dependency, install_dir, env_var_dict, set_prior_environment_commands ):
"""
- This method works with with a combination of three tool dependency definition tag sets, which are defined in the tool_dependencies.xml file in the
- order discussed here. The example for this discussion is the tool_dependencies.xml file contained in the osra repository, which is available at:
+ This method works with with a combination of three tool dependency definition tag sets, which are defined
+ in the tool_dependencies.xml file in the order discussed here. The example for this discussion is the
+ tool_dependencies.xml file contained in the osra repository, which is available at:
http://testtoolshed.g2.bx.psu.edu/view/bgruening/osra
- The first tag set defines a complex repository dependency like this. This tag set ensures that changeset revision XXX of the repository named
- package_graphicsmagick_1_3 owned by YYY in the tool shed ZZZ has been previously installed.
+ The first tag set defines a complex repository dependency like this. This tag set ensures that changeset
+ revision XXX of the repository named package_graphicsmagick_1_3 owned by YYY in the tool shed ZZZ has been
+ previously installed.
<tool_dependency><package name="graphicsmagick" version="1.3.18">
@@ -395,19 +401,21 @@
</package>
...
- * By the way, there is an env.sh file associated with version 1.3.18 of the graphicsmagick package which looks something like this (we'll reference
- this file later in this discussion.
+ * By the way, there is an env.sh file associated with version 1.3.18 of the graphicsmagick package which looks
+ something like this (we'll reference this file later in this discussion.
----
GRAPHICSMAGICK_ROOT_DIR=/<my configured tool dependency path>/graphicsmagick/1.3.18/YYY/package_graphicsmagick_1_3/XXX/gmagick;
export GRAPHICSMAGICK_ROOT_DIR
----
- The second tag set defines a specific package dependency that has been previously installed (guaranteed by the tag set discussed above) and compiled,
- where the compiled dependency is needed by the tool dependency currently being installed (osra version 2.0.0 in this case) and complied in order for
- it's installation and compilation to succeed. This tag set is contained within the <package name="osra" version="2.0.0"> tag set, which implies that
- version 2.0.0 of the osra package requires version 1.3.18 of the graphicsmagick package in order to successfully compile. When this tag set is handled,
- one of the effects is that the env.sh file associated with graphicsmagick version 1.3.18 is "sourced", which undoubtedly sets or alters certain environment
- variables (e.g. PATH, PYTHONPATH, etc).
+ The second tag set defines a specific package dependency that has been previously installed (guaranteed by the
+ tag set discussed above) and compiled, where the compiled dependency is needed by the tool dependency currently
+ being installed (osra version 2.0.0 in this case) and complied in order for it's installation and compilation to
+ succeed. This tag set is contained within the <package name="osra" version="2.0.0"> tag set, which implies that
+ version 2.0.0 of the osra package requires version 1.3.18 of the graphicsmagick package in order to successfully
+ compile. When this tag set is handled, one of the effects is that the env.sh file associated with graphicsmagick
+ version 1.3.18 is "sourced", which undoubtedly sets or alters certain environment variables (e.g. PATH, PYTHONPATH,
+ etc).
<!-- populate the environment variables from the dependent repositories --><action type="set_environment_for_install">
@@ -416,11 +424,12 @@
</repository></action>
- The third tag set enables discovery of the same required package dependency discussed above for correctly compiling the osra version 2.0.0 package, but
- in this case the package can be discovered at tool execution time. Using the $ENV[] option as shown in this example, the value of the environment
- variable named GRAPHICSMAGICK_ROOT_DIR (which was set in the environment using the second tag set described above) will be used to automatically alter
- the env.sh file associated with the osra version 2.0.0 tool dependency when it is installed into Galaxy. * Refer to where we discussed the env.sh file
- for version 1.3.18 of the graphicsmagick package above.
+ The third tag set enables discovery of the same required package dependency discussed above for correctly compiling
+ the osra version 2.0.0 package, but in this case the package can be discovered at tool execution time. Using the
+ $ENV[] option as shown in this example, the value of the environment variable named GRAPHICSMAGICK_ROOT_DIR (which
+ was set in the environment using the second tag set described above) will be used to automatically alter the env.sh
+ file associated with the osra version 2.0.0 tool dependency when it is installed into Galaxy. * Refer to where we
+ discussed the env.sh file for version 1.3.18 of the graphicsmagick package above.
<action type="set_environment"><environment_variable action="prepend_to" name="LD_LIBRARY_PATH">$ENV[GRAPHICSMAGICK_ROOT_DIR]/lib/</environment_variable>
@@ -430,8 +439,9 @@
<environment_variable action="set_to" name="OSRA_DATA_FILES">$INSTALL_DIR/share</environment_variable></action>
- The above tag will produce an env.sh file for version 2.0.0 of the osra package when it it installed into Galaxy that looks something like this. Notice
- that the path to the gmagick binary is included here since it expands the defined $ENV[GRAPHICSMAGICK_ROOT_DIR] value in the above tag set.
+ The above tag will produce an env.sh file for version 2.0.0 of the osra package when it it installed into Galaxy
+ that looks something like this. Notice that the path to the gmagick binary is included here since it expands the
+ defined $ENV[GRAPHICSMAGICK_ROOT_DIR] value in the above tag set.
----
LD_LIBRARY_PATH=/<my configured tool dependency path>/graphicsmagick/1.3.18/YYY/package_graphicsmagick_1_3/XXX/gmagick/lib/:$LD_LIBRARY_PATH;
@@ -607,7 +617,8 @@
with settings( warn_only=True ):
for tarball_name in tarball_names:
cmd = '''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
- Rscript -e \\"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\\"''' % ( str( tarball_name ) )
+ Rscript -e \\"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\\"''' % \
+ ( str( tarball_name ) )
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
return_code = handle_command( app, tool_dependency, install_dir, cmd )
if return_code:
@@ -720,7 +731,8 @@
elif os.path.exists( os.path.join( tmp_work_dir, 'Build.PL' ) ):
cmd += '''perl Build.PL --install_base $INSTALL_DIR && perl Build && perl Build install'''
else:
- log.debug( 'No Makefile.PL or Build.PL file found in %s. Skipping installation of %s.' % ( url, perl_package_name ) )
+ log.debug( 'No Makefile.PL or Build.PL file found in %s. Skipping installation of %s.' % \
+ ( url, perl_package_name ) )
return tool_dependency
with lcd( tmp_work_dir ):
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
@@ -920,9 +932,7 @@
return tool_dependency
def log_results( command, fabric_AttributeString, file_path ):
- """
- Write attributes of fabric.operations._AttributeString to a specified log file.
- """
+ """Write attributes of fabric.operations._AttributeString to a specified log file."""
if os.path.exists( file_path ):
logfile = open( file_path, 'ab' )
else:
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -300,7 +300,10 @@
return tool_dependency
def install_package( app, elem, tool_shed_repository, tool_dependencies=None, from_install_manager=False ):
- # The value of tool_dependencies is a partial or full list of ToolDependency records associated with the tool_shed_repository.
+ """
+ Install a tool dependency package defined by the XML element elem. The value of tool_dependencies is
+ a partial or full list of ToolDependency records associated with the tool_shed_repository.
+ """
sa_session = app.install_model.context
tool_dependency = None
# The value of package_name should match the value of the "package" type in the tool config's <requirements> tag set, but it's not required.
@@ -363,8 +366,8 @@
type='package',
status=app.install_model.ToolDependency.installation_status.INSTALLING,
set_status=True )
- # Get the information about the current platform in case the tool dependency definition includes tag sets for installing
- # compiled binaries.
+ # Get the information about the current platform in case the tool dependency definition includes tag sets
+ # for installing compiled binaries.
platform_info_dict = tool_dependency_util.get_platform_info_dict()
if package_install_version == '1.0':
# Handle tool dependency installation using a fabric method included in the Galaxy framework.
@@ -372,24 +375,29 @@
platform_info_dict=platform_info_dict,
include_after_install_actions=True )
if actions_elem_tuples:
- # At this point we have a list of <actions> elems that are either defined within an <actions_group> tag set with <actions>
- # sub-elements that contains os and architecture attributes filtered by the platform into which the appropriate compiled
- # binary will be installed, or not defined within an <actions_group> tag set and not filtered.
+ # At this point we have a list of <actions> elems that are either defined within an <actions_group>
+ # tag set with <actions> sub-elements that contains os and architecture attributes filtered by the
+ # platform into which the appropriate compiled binary will be installed, or not defined within an
+ # <actions_group> tag set and not filtered. Here is an example actions_elem_tuple.
+ # [(True, [<Element 'actions' at 0x109293d10>)]
binary_installed = False
- for in_actions_group, actions_elems in actions_elem_tuples:
+ for actions_elem_tuple in actions_elem_tuples:
+ in_actions_group, actions_elems = actions_elem_tuple
if in_actions_group:
- # Platform matching is only performed inside <actions_group> tag sets, os and architecture attributes are otherwise
- # ignored.
+ # Platform matching is only performed inside <actions_group> tag sets, os and architecture
+ # attributes are otherwise ignored.
+ can_install_from_source = False
for actions_elem in actions_elems:
system = actions_elem.get( 'os' )
architecture = actions_elem.get( 'architecture' )
- # If this <actions> element has the os and architecture attributes defined, then we only want to process until a
- # successful installation is achieved.
+ # If this <actions> element has the os and architecture attributes defined, then we only
+ # want to process until a successful installation is achieved.
if system and architecture:
- # If an <actions> tag has been defined that matches our current platform, and the recipe specified within
- # that <actions> tag has been successfully processed, skip any remaining platform-specific <actions> tags.
- # We cannot break out of the look here because there may be <action> tags at the end of the <actions_group>
- # tag set that must be processed.
+ # If an <actions> tag has been defined that matches our current platform, and the
+ # recipe specified within that <actions> tag has been successfully processed, skip
+ # any remaining platform-specific <actions> tags. We cannot break out of the loop
+ # here because there may be <action> tags at the end of the <actions_group> tag set
+ # that must be processed.
if binary_installed:
continue
# No platform-specific <actions> recipe has yet resulted in a successful installation.
@@ -400,41 +408,50 @@
actions_elem=actions_elem,
action_elem=None )
if tool_dependency.status == app.install_model.ToolDependency.installation_status.INSTALLED:
- # If an <actions> tag was found that matches the current platform, and the install_via_fabric method
- # did not result in an error state, set binary_installed to True in order to skip any remaining
- # platform-specific <actions> tags.
+ # If an <actions> tag was found that matches the current platform, and the
+ # install_via_fabric method did not result in an error state, set binary_installed
+ # to True in order to skip any remaining platform-specific <actions> tags.
binary_installed = True
else:
- # Process the next matching <actions> tag, or any defined <actions> tags that do not contain platform
- # dependent recipes.
+ # Process the next matching <actions> tag, or any defined <actions> tags that do not
+ # contain platform dependent recipes.
log.debug( 'Error downloading binary for tool dependency %s version %s: %s' % \
( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
else:
- # If no <actions> tags have been defined that match our current platform, or none of the matching
- # <actions> tags resulted in a successful tool dependency status, proceed with one and only one
- # <actions> tag that is not defined to be platform-specific.
- if not binary_installed:
- log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % str( tool_dependency.name ) )
- # Make sure to reset for installation if attempt at binary installation resulted in an error.
- can_install = True
- if tool_dependency.status != app.install_model.ToolDependency.installation_status.NEVER_INSTALLED:
- removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
- if not removed:
- log.debug( 'Error removing old files from installation directory %s: %s' % \
- ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
- can_install = False
- if can_install:
+ if actions_elem.tag == 'actions':
+ # We've reached an <actions> tag that defines the recipe for installing and compiling from
+ # source. If binary installation failed, we proceed with the recipe.
+ if not binary_installed:
+ installation_directory = tool_dependency.installation_directory( app )
+ if os.path.exists( installation_directory ):
+ # Delete contents of installation directory if attempt at binary installation failed.
+ installation_directory_contents = os.listdir( installation_directory )
+ if installation_directory_contents:
+ removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
+ if removed:
+ can_install_from_source = True
+ else:
+ log.debug( 'Error removing old files from installation directory %s: %s' % \
+ ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
+ else:
+ can_install_from_source = True
+ else:
+ can_install_from_source = True
+ if can_install_from_source:
+ # We now know that binary installation was not successful, so proceed with the <actions>
+ # tag set that defines the recipe to install and compile from source.
+ log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % \
+ str( tool_dependency.name ) )
tool_dependency = install_via_fabric( app,
tool_dependency,
install_dir,
package_name=package_name,
actions_elem=actions_elem,
action_elem=None )
- # Perform any final actions that have been defined within the actions_group tag set, but outside of
- # an <actions> tag, such as a set_environment entry, or a download_file or download_by_url command to
- # retrieve extra data for this tool dependency. Only do this if the tool dependency is not in an error
- # state, otherwise skip this action.
if actions_elem.tag == 'action' and tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
+ # If the tool dependency is not in an error state, perform any final actions that have been
+ # defined within the actions_group tag set, but outside of an <actions> tag, which defines
+ # the recipe for installing and compiling from source.
tool_dependency = install_via_fabric( app,
tool_dependency,
install_dir,
@@ -442,9 +459,9 @@
actions_elem=None,
action_elem=actions_elem )
else:
- # <actions> tags outside of an <actions_group> tag shall not check os or architecture, and if the attributes are
- # defined, they will be ignored. All <actions> tags outside of an <actions_group> tag set shall always be processed.
- # This is the default and original behavior of the install_package method.
+ # Checks for "os" and "architecture" attributes are not made for any <actions> tag sets outside of
+ # an <actions_group> tag set. If the attributes are defined, they will be ignored. All <actions> tags
+ # outside of an <actions_group> tag set will always be processed.
tool_dependency = install_via_fabric( app,
tool_dependency,
install_dir,
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -227,18 +227,21 @@
return file_path
return None
-def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url, metadata_dict,
- status, current_changeset_revision=None, owner='', dist_to_shed=False ):
+def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url,
+ metadata_dict, status, current_changeset_revision=None, owner='', dist_to_shed=False ):
"""
- Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed,
- repository name and owner does not exist, create a new record with the received information.
+ Update a tool shed repository record in the Galaxy database with the new information received.
+ If a record defined by the received tool shed, repository name and owner does not exist, create
+ a new record with the received information.
"""
- # The received value for dist_to_shed will be True if the InstallManager is installing a repository that contains tools or datatypes that used
- # to be in the Galaxy distribution, but have been moved to the main Galaxy tool shed.
+ # The received value for dist_to_shed will be True if the InstallManager is installing a repository
+ # that contains tools or datatypes that used to be in the Galaxy distribution, but have been moved
+ # to the main Galaxy tool shed.
if current_changeset_revision is None:
- # The current_changeset_revision is not passed if a repository is being installed for the first time. If a previously installed repository
- # was later uninstalled, this value should be received as the value of that change set to which the repository had been updated just prior
- # to it being uninstalled.
+ # The current_changeset_revision is not passed if a repository is being installed for the first
+ # time. If a previously installed repository was later uninstalled, this value should be received
+ # as the value of that change set to which the repository had been updated just prior to it being
+ # uninstalled.
current_changeset_revision = installed_changeset_revision
context = app.install_model.context
tool_shed = get_tool_shed_from_clone_url( repository_clone_url )
@@ -255,9 +258,14 @@
deleted = False
uninstalled = False
tool_shed_repository = \
- get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app, tool_shed, name, owner, installed_changeset_revision )
+ get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app,
+ tool_shed,
+ name,
+ owner,
+ installed_changeset_revision )
if tool_shed_repository:
- log.debug( "Updating an existing row for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
+ log.debug( "Updating an existing row for repository '%s' in the tool_shed_repository table, status set to '%s'." % \
+ ( str( name ), str( status ) ) )
tool_shed_repository.description = description
tool_shed_repository.changeset_revision = current_changeset_revision
tool_shed_repository.ctx_rev = ctx_rev
@@ -267,7 +275,8 @@
tool_shed_repository.uninstalled = uninstalled
tool_shed_repository.status = status
else:
- log.debug( "Adding new row for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
+ log.debug( "Adding new row for repository '%s' in the tool_shed_repository table, status set to '%s'." % \
+ ( str( name ), str( status ) ) )
tool_shed_repository = \
app.install_model.ToolShedRepository( tool_shed=tool_shed,
name=name,
@@ -1028,8 +1037,8 @@
owner=owner,
changeset_revision=changeset_revision )
if not repository:
- # The received changeset_revision is no longer installable, so get the next changeset_revision in the repository's changelog in the
- # tool shed that is associated with repository_metadata.
+ # The received changeset_revision is no longer installable, so get the next changeset_revision
+ # in the repository's changelog in the tool shed that is associated with repository_metadata.
tool_shed_url = get_url_from_tool_shed( app, tool_shed )
url = url_join( tool_shed_url,
'repository/next_installable_changeset_revision?name=%s&owner=%s&changeset_revision=%s' % \
@@ -1305,7 +1314,10 @@
.first()
def get_tool_shed_repository_by_shed_name_owner_changeset_revision( app, tool_shed, name, owner, changeset_revision ):
- """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and current changeet_revision."""
+ """
+ Return a tool shed repository database record defined by the combination of a tool_shed, repository name,
+ repository owner and current changeet_revision.
+ """
# This method is used only in Galaxy, not the tool shed.
repository_query = __repository_query( app )
if tool_shed.find( '//' ) > 0:
@@ -1319,7 +1331,10 @@
.first()
def get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app, tool_shed, name, owner, installed_changeset_revision ):
- """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and installed_changeet_revision."""
+ """
+ Return a tool shed repository database record defined by the combination of a tool_shed,
+ repository name, repository owner and installed_changeet_revision.
+ """
# This method is used only in Galaxy, not the tool shed.
repository_query = __repository_query( app )
if tool_shed.find( '//' ) > 0:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d339a00374b9/
Changeset: d339a00374b9
User: martenson
Date: 2014-03-05 21:07:42
Summary: library API improvements - DELETE and PATCH; addition of http error codes and exceptions; slight refator; small bugfix
Affected #: 4 files
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/exceptions/__init__.py
--- a/lib/galaxy/exceptions/__init__.py
+++ b/lib/galaxy/exceptions/__init__.py
@@ -31,42 +31,68 @@
pass
-class ItemAccessibilityException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+class ObjectInvalid( Exception ):
+ """ Accessed object store ID is invalid """
+ pass
+# Please keep the exceptions ordered by status code
-class ItemOwnershipException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_DOES_NOT_OWN_ITEM
+class ActionInputError( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+ def __init__( self, err_msg, type="error" ):
+ super( ActionInputError, self ).__init__( err_msg, type )
class DuplicatedSlugException( MessageException ):
status_code = 400
err_code = error_codes.USER_SLUG_DUPLICATE
-
class ObjectAttributeInvalidException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_INVALID
-
class ObjectAttributeMissingException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_MISSING
+class MalformedId( MessageException ):
+ status_code = 400
+ err_code = error_codes.MALFORMED_ID
-class ActionInputError( MessageException ):
- def __init__( self, err_msg, type="error" ):
- super( ActionInputError, self ).__init__( err_msg, type )
+class RequestParameterMissingException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_MISSING_PARAMETER
+class RequestParameterInvalidException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+
+class ItemAccessibilityException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+
+class ItemOwnershipException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_DOES_NOT_OWN_ITEM
class ObjectNotFound( MessageException ):
""" Accessed object was not found """
status_code = 404
err_code = error_codes.USER_OBJECT_NOT_FOUND
+class Conflict( MessageException ):
+ status_code = 409
+ err_code = error_codes.CONFLICT
-class ObjectInvalid( Exception ):
- """ Accessed object store ID is invalid """
- pass
+class InconsistentDatabase ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INCONSISTENT_DATABASE
+
+class InternalServerError ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INTERNAL_SERVER_ERROR
+
+class NotImplemented ( MessageException ):
+ status_code = 501
+ err_code = error_codes.NOT_IMPLEMENTED
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -3,7 +3,7 @@
"name": "UNKNOWN",
"code": 0,
"message": "Unknown error occurred while processing request."
- },
+ },
{
"name": "USER_CANNOT_RUN_AS",
"code": 400001,
@@ -35,6 +35,21 @@
"message": "Slug must be unique per user."
},
{
+ "name": "USER_REQUEST_MISSING_PARAMETER",
+ "code": 400007,
+ "message": "Request is missing parameter required to complete desired action."
+ },
+ {
+ "name": "USER_REQUEST_INVALID_PARAMETER",
+ "code": 400008,
+ "message": "Request contained invalid parameter, action could not be completed."
+ },
+ {
+ "name": "MALFORMED_ID",
+ "code": 400009,
+ "message": "The id of the resource is malformed."
+ },
+ {
"name": "USER_NO_API_KEY",
"code": 403001,
"message": "API Authentication Required for this request"
@@ -53,5 +68,25 @@
"name": "USER_OBJECT_NOT_FOUND",
"code": 404001,
"message": "No such object found."
+ },
+ {
+ "name": "CONFLICT",
+ "code": 409001,
+ "message": "Database conflict prevented fulfilling the request."
+ },
+ {
+ "name": "INTERNAL_SERVER_ERROR",
+ "code": 500001,
+ "message": "Internal server error."
+ },
+ {
+ "name": "INCONSISTENT_DATABASE",
+ "code": 500001,
+ "message": "Inconsistent database prevented fulfilling the request."
+ },
+ {
+ "name": "NOT_IMPLEMENTED",
+ "code": 501001,
+ "message": "Method is not implemented."
}
]
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -2,10 +2,12 @@
API operations on a data library.
"""
from galaxy import util
+from galaxy.util import string_as_bool
from galaxy import web
+from galaxy import exceptions
+from galaxy.web import _future_expose_api as expose_api
from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController, url_for
-from paste.httpexceptions import HTTPBadRequest, HTTPForbidden
import logging
log = logging.getLogger( __name__ )
@@ -13,7 +15,7 @@
class LibrariesController( BaseAPIController ):
- @web.expose_api
+ @expose_api
def index( self, trans, deleted='False', **kwd ):
"""
index( self, trans, deleted='False', **kwd )
@@ -22,11 +24,12 @@
* GET /api/libraries/deleted:
Returns a list of summary data for ``deleted`` libraries.
- :param deleted: if True, show only deleted libraries, if False, ``non-deleted``
+ :param deleted: if True, show only ``deleted`` libraries, if False or nonpresent show only ``non-deleted``
:type deleted: boolean
+ :returns: list of dictionaries containing library information
:rtype: list
- :returns: list of dictionaries containing library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_collection_visible_keys`
"""
query = trans.sa_session.query( trans.app.model.Library )
@@ -50,13 +53,13 @@
libraries = []
for library in query:
item = library.to_dict( view='element' )
- item['url'] = url_for( route, id=trans.security.encode_id( library.id ) )
- item['id'] = trans.security.encode_id( item['id'] )
- item['root_folder_id'] = 'F' + trans.security.encode_id( item['root_folder_id'] )
+ item[ 'url' ] = url_for( route, id=trans.security.encode_id( library.id ) )
+ item[ 'id' ] = trans.security.encode_id( item[ 'id' ] )
+ item[ 'root_folder_id' ] = 'F' + trans.security.encode_id( item[ 'root_folder_id' ] )
libraries.append( item )
return libraries
- @web.expose_api
+ @expose_api
def show( self, trans, id, deleted='False', **kwd ):
"""
show( self, trans, id, deleted='False', **kwd )
@@ -70,50 +73,50 @@
:param deleted: if True, allow information on a ``deleted`` library
:type deleted: boolean
+ :returns: detailed library information
:rtype: dictionary
- :returns: detailed library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
library_id = id
deleted = util.string_as_bool( deleted )
try:
decoded_library_id = trans.security.decode_id( library_id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
assert library.deleted == deleted
except:
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- item = library.to_dict( view='element' )
- item['contents_url'] = url_for( 'library_contents', library_id=library_id )
- return item
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- @web.expose_api
+ @expose_api
def create( self, trans, payload, **kwd ):
"""
create( self, trans, payload, **kwd )
* POST /api/libraries:
Creates a new library. Only ``name`` parameter is required.
+
.. note:: Currently, only admin users can create libraries.
- :param payload: (optional) dictionary structure containing::
- 'name': the new library's name
- 'description': the new library's description
- 'synopsis': the new library's synopsis
+ :param payload: dictionary structure containing::
+ 'name': the new library's name (required)
+ 'description': the new library's description (optional)
+ 'synopsis': the new library's synopsis (optional)
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the new library
"""
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to create a new library.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can create libraries.' )
params = util.Params( payload )
name = util.restore_text( params.get( 'name', None ) )
if not name:
- raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
description = util.restore_text( params.get( 'description', '' ) )
synopsis = util.restore_text( params.get( 'synopsis', '' ) )
if synopsis in [ 'None', None ]:
@@ -123,63 +126,95 @@
library.root_folder = root_folder
trans.sa_session.add_all( ( library, root_folder ) )
trans.sa_session.flush()
- encoded_id = trans.security.encode_id( library.id )
- new_library = {}
- new_library['url'] = url_for( 'library', id=encoded_id )
- new_library['name'] = name
- new_library['description'] = description
- new_library['synopsis'] = synopsis
- new_library['id'] = encoded_id
- new_library['root_folder_id'] = trans.security.encode_id( root_folder.id )
- return new_library
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- def edit( self, trans, encoded_id, payload, **kwd ):
+ @expose_api
+ def update( self, trans, id, **kwd ):
"""
- * PUT /api/libraries/{encoded_id}
+ * PATCH /api/libraries/{encoded_id}
Updates the library defined by an ``encoded_id`` with the data in the payload.
- .. note:: Currently, only admin users can edit libraries.
+ .. note:: Currently, only admin users can update libraries.
:param payload: (required) dictionary structure containing::
- 'name': new library's name
+ 'name': new library's name, cannot be empty
'description': new library's description
'synopsis': new library's synopsis
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the updated library
- """
- return "Not implemented yet"
-
- @web.expose_api
- def delete( self, trans, id, **kwd ):
- """
- delete( self, trans, id, **kwd )
- * DELETE /api/histories/{id}
- mark the library with the given ``id`` as deleted
-
- .. note:: Currently, only admin users can delete libraries.
-
- :param id: the encoded id of the library to delete
- :type id: str
-
- :rtype: dictionary
- :returns: detailed library information
- .. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to delete libraries.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can update libraries.' )
+
try:
decoded_id = trans.security.decode_id( id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
+ library = None
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
except:
library = None
if not library:
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- library.deleted = True
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ payload = kwd.get( 'payload', None )
+ if payload:
+ name = payload.get( 'name', None )
+ if name == '':
+ raise exceptions.RequestParameterMissingException( "Parameter 'name' of library is required. You cannot remove it." )
+ library.name = name
+ if payload.get( 'description', None ) or payload.get( 'description', None ) == '':
+ library.description = payload.get( 'description', None )
+ if payload.get( 'synopsis', None ) or payload.get( 'synopsis', None ) == '':
+ library.synopsis = payload.get( 'synopsis', None )
+ else:
+ raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id } )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+
+ @expose_api
+ def delete( self, trans, id, **kwd ):
+ """
+ delete( self, trans, id, **kwd )
+ * DELETE /api/libraries/{id}
+ marks the library with the given ``id`` as `deleted` (or removes the `deleted` mark if the `undelete` param is true)
+
+ .. note:: Currently, only admin users can un/delete libraries.
+
+ :param id: the encoded id of the library to un/delete
+ :type id: str
+
+ :param undelete: flag specifying whether the item should be deleted or undeleted, defaults to false:
+ :type undelete: bool
+
+ :returns: detailed library information
+ :rtype: dictionary
+
+ .. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
+ """
+ undelete = string_as_bool( kwd.get( 'undelete', False ) )
+ if not trans.user_is_admin():
+ raise exceptions.ItemAccessibilityException( 'Only administrators can delete and undelete libraries.' )
+ try:
+ decoded_id = trans.security.decode_id( id )
+ except:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
+ except:
+ library = None
+ if not library:
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ if undelete:
+ library.deleted = False
+ else:
+ library.deleted = True
+
+ trans.sa_session.add( library )
+ trans.sa_session.flush()
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -135,7 +135,6 @@
path_prefix='/api/histories/:history_id/contents/:history_content_id' )
webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
- webapp.mapper.resource_with_deleted( 'library', 'libraries', path_prefix='/api' )
webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
@@ -206,6 +205,18 @@
# ===== LIBRARY API =====
# =======================
+ webapp.mapper.connect( 'delete_library',
+ '/api/libraries/:id',
+ controller='libraries',
+ action='delete',
+ conditions=dict( method=[ "DELETE" ] ) )
+
+ webapp.mapper.connect( 'update_library',
+ '/api/libraries/:id',
+ controller='libraries',
+ action='update',
+ conditions=dict( method=[ "PATCH" ] ) )
+
webapp.mapper.connect( 'show_lda_item',
'/api/libraries/datasets/:id',
controller='lda_datasets',
https://bitbucket.org/galaxy/galaxy-central/commits/03dd71b129e5/
Changeset: 03dd71b129e5
User: martenson
Date: 2014-03-06 16:49:36
Summary: API libraries exceptions improvement, unnecessary endpoint removal
Affected #: 3 files
diff -r d339a00374b9fea91e659256be9db20ed226e9fe -r 03dd71b129e5dd19b0687ef56f75a270816433b0 lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -81,7 +81,7 @@
},
{
"name": "INCONSISTENT_DATABASE",
- "code": 500001,
+ "code": 500002,
"message": "Inconsistent database prevented fulfilling the request."
},
{
diff -r d339a00374b9fea91e659256be9db20ed226e9fe -r 03dd71b129e5dd19b0687ef56f75a270816433b0 lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -82,12 +82,12 @@
deleted = util.string_as_bool( deleted )
try:
decoded_library_id = trans.security.decode_id( library_id )
- except:
+ except Exception:
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
assert library.deleted == deleted
- except:
+ except Exception:
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
@@ -150,12 +150,12 @@
try:
decoded_id = trans.security.decode_id( id )
- except:
+ except Exception:
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
library = None
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
- except:
+ except Exception:
library = None
if not library:
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
@@ -201,11 +201,11 @@
raise exceptions.ItemAccessibilityException( 'Only administrators can delete and undelete libraries.' )
try:
decoded_id = trans.security.decode_id( id )
- except:
+ except Exception:
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
- except:
+ except Exception:
library = None
if not library:
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
diff -r d339a00374b9fea91e659256be9db20ed226e9fe -r 03dd71b129e5dd19b0687ef56f75a270816433b0 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -205,12 +205,6 @@
# ===== LIBRARY API =====
# =======================
- webapp.mapper.connect( 'delete_library',
- '/api/libraries/:id',
- controller='libraries',
- action='delete',
- conditions=dict( method=[ "DELETE" ] ) )
-
webapp.mapper.connect( 'update_library',
'/api/libraries/:id',
controller='libraries',
https://bitbucket.org/galaxy/galaxy-central/commits/8093e5f39efb/
Changeset: 8093e5f39efb
User: martenson
Date: 2014-03-06 17:07:40
Summary: Merged in martenson/galaxy-central-marten (pull request #344)
library API improvements - DELETE and PATCH; addition to John's http error codes and exceptions; slight refator; small bugfix
Affected #: 4 files
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/exceptions/__init__.py
--- a/lib/galaxy/exceptions/__init__.py
+++ b/lib/galaxy/exceptions/__init__.py
@@ -31,42 +31,68 @@
pass
-class ItemAccessibilityException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+class ObjectInvalid( Exception ):
+ """ Accessed object store ID is invalid """
+ pass
+# Please keep the exceptions ordered by status code
-class ItemOwnershipException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_DOES_NOT_OWN_ITEM
+class ActionInputError( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+ def __init__( self, err_msg, type="error" ):
+ super( ActionInputError, self ).__init__( err_msg, type )
class DuplicatedSlugException( MessageException ):
status_code = 400
err_code = error_codes.USER_SLUG_DUPLICATE
-
class ObjectAttributeInvalidException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_INVALID
-
class ObjectAttributeMissingException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_MISSING
+class MalformedId( MessageException ):
+ status_code = 400
+ err_code = error_codes.MALFORMED_ID
-class ActionInputError( MessageException ):
- def __init__( self, err_msg, type="error" ):
- super( ActionInputError, self ).__init__( err_msg, type )
+class RequestParameterMissingException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_MISSING_PARAMETER
+class RequestParameterInvalidException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+
+class ItemAccessibilityException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+
+class ItemOwnershipException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_DOES_NOT_OWN_ITEM
class ObjectNotFound( MessageException ):
""" Accessed object was not found """
status_code = 404
err_code = error_codes.USER_OBJECT_NOT_FOUND
+class Conflict( MessageException ):
+ status_code = 409
+ err_code = error_codes.CONFLICT
-class ObjectInvalid( Exception ):
- """ Accessed object store ID is invalid """
- pass
+class InconsistentDatabase ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INCONSISTENT_DATABASE
+
+class InternalServerError ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INTERNAL_SERVER_ERROR
+
+class NotImplemented ( MessageException ):
+ status_code = 501
+ err_code = error_codes.NOT_IMPLEMENTED
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -3,7 +3,7 @@
"name": "UNKNOWN",
"code": 0,
"message": "Unknown error occurred while processing request."
- },
+ },
{
"name": "USER_CANNOT_RUN_AS",
"code": 400001,
@@ -35,6 +35,21 @@
"message": "Slug must be unique per user."
},
{
+ "name": "USER_REQUEST_MISSING_PARAMETER",
+ "code": 400007,
+ "message": "Request is missing parameter required to complete desired action."
+ },
+ {
+ "name": "USER_REQUEST_INVALID_PARAMETER",
+ "code": 400008,
+ "message": "Request contained invalid parameter, action could not be completed."
+ },
+ {
+ "name": "MALFORMED_ID",
+ "code": 400009,
+ "message": "The id of the resource is malformed."
+ },
+ {
"name": "USER_NO_API_KEY",
"code": 403001,
"message": "API Authentication Required for this request"
@@ -53,5 +68,25 @@
"name": "USER_OBJECT_NOT_FOUND",
"code": 404001,
"message": "No such object found."
+ },
+ {
+ "name": "CONFLICT",
+ "code": 409001,
+ "message": "Database conflict prevented fulfilling the request."
+ },
+ {
+ "name": "INTERNAL_SERVER_ERROR",
+ "code": 500001,
+ "message": "Internal server error."
+ },
+ {
+ "name": "INCONSISTENT_DATABASE",
+ "code": 500002,
+ "message": "Inconsistent database prevented fulfilling the request."
+ },
+ {
+ "name": "NOT_IMPLEMENTED",
+ "code": 501001,
+ "message": "Method is not implemented."
}
]
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -2,10 +2,12 @@
API operations on a data library.
"""
from galaxy import util
+from galaxy.util import string_as_bool
from galaxy import web
+from galaxy import exceptions
+from galaxy.web import _future_expose_api as expose_api
from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController, url_for
-from paste.httpexceptions import HTTPBadRequest, HTTPForbidden
import logging
log = logging.getLogger( __name__ )
@@ -13,7 +15,7 @@
class LibrariesController( BaseAPIController ):
- @web.expose_api
+ @expose_api
def index( self, trans, deleted='False', **kwd ):
"""
index( self, trans, deleted='False', **kwd )
@@ -22,11 +24,12 @@
* GET /api/libraries/deleted:
Returns a list of summary data for ``deleted`` libraries.
- :param deleted: if True, show only deleted libraries, if False, ``non-deleted``
+ :param deleted: if True, show only ``deleted`` libraries, if False or nonpresent show only ``non-deleted``
:type deleted: boolean
+ :returns: list of dictionaries containing library information
:rtype: list
- :returns: list of dictionaries containing library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_collection_visible_keys`
"""
query = trans.sa_session.query( trans.app.model.Library )
@@ -50,13 +53,13 @@
libraries = []
for library in query:
item = library.to_dict( view='element' )
- item['url'] = url_for( route, id=trans.security.encode_id( library.id ) )
- item['id'] = trans.security.encode_id( item['id'] )
- item['root_folder_id'] = 'F' + trans.security.encode_id( item['root_folder_id'] )
+ item[ 'url' ] = url_for( route, id=trans.security.encode_id( library.id ) )
+ item[ 'id' ] = trans.security.encode_id( item[ 'id' ] )
+ item[ 'root_folder_id' ] = 'F' + trans.security.encode_id( item[ 'root_folder_id' ] )
libraries.append( item )
return libraries
- @web.expose_api
+ @expose_api
def show( self, trans, id, deleted='False', **kwd ):
"""
show( self, trans, id, deleted='False', **kwd )
@@ -70,50 +73,50 @@
:param deleted: if True, allow information on a ``deleted`` library
:type deleted: boolean
+ :returns: detailed library information
:rtype: dictionary
- :returns: detailed library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
library_id = id
deleted = util.string_as_bool( deleted )
try:
decoded_library_id = trans.security.decode_id( library_id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except Exception:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
assert library.deleted == deleted
- except:
+ except Exception:
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- item = library.to_dict( view='element' )
- item['contents_url'] = url_for( 'library_contents', library_id=library_id )
- return item
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- @web.expose_api
+ @expose_api
def create( self, trans, payload, **kwd ):
"""
create( self, trans, payload, **kwd )
* POST /api/libraries:
Creates a new library. Only ``name`` parameter is required.
+
.. note:: Currently, only admin users can create libraries.
- :param payload: (optional) dictionary structure containing::
- 'name': the new library's name
- 'description': the new library's description
- 'synopsis': the new library's synopsis
+ :param payload: dictionary structure containing::
+ 'name': the new library's name (required)
+ 'description': the new library's description (optional)
+ 'synopsis': the new library's synopsis (optional)
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the new library
"""
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to create a new library.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can create libraries.' )
params = util.Params( payload )
name = util.restore_text( params.get( 'name', None ) )
if not name:
- raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
description = util.restore_text( params.get( 'description', '' ) )
synopsis = util.restore_text( params.get( 'synopsis', '' ) )
if synopsis in [ 'None', None ]:
@@ -123,63 +126,95 @@
library.root_folder = root_folder
trans.sa_session.add_all( ( library, root_folder ) )
trans.sa_session.flush()
- encoded_id = trans.security.encode_id( library.id )
- new_library = {}
- new_library['url'] = url_for( 'library', id=encoded_id )
- new_library['name'] = name
- new_library['description'] = description
- new_library['synopsis'] = synopsis
- new_library['id'] = encoded_id
- new_library['root_folder_id'] = trans.security.encode_id( root_folder.id )
- return new_library
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- def edit( self, trans, encoded_id, payload, **kwd ):
+ @expose_api
+ def update( self, trans, id, **kwd ):
"""
- * PUT /api/libraries/{encoded_id}
+ * PATCH /api/libraries/{encoded_id}
Updates the library defined by an ``encoded_id`` with the data in the payload.
- .. note:: Currently, only admin users can edit libraries.
+ .. note:: Currently, only admin users can update libraries.
:param payload: (required) dictionary structure containing::
- 'name': new library's name
+ 'name': new library's name, cannot be empty
'description': new library's description
'synopsis': new library's synopsis
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the updated library
"""
- return "Not implemented yet"
+ if not trans.user_is_admin():
+ raise exceptions.ItemAccessibilityException( 'Only administrators can update libraries.' )
- @web.expose_api
+ try:
+ decoded_id = trans.security.decode_id( id )
+ except Exception:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
+ library = None
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
+ except Exception:
+ library = None
+ if not library:
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ payload = kwd.get( 'payload', None )
+ if payload:
+ name = payload.get( 'name', None )
+ if name == '':
+ raise exceptions.RequestParameterMissingException( "Parameter 'name' of library is required. You cannot remove it." )
+ library.name = name
+ if payload.get( 'description', None ) or payload.get( 'description', None ) == '':
+ library.description = payload.get( 'description', None )
+ if payload.get( 'synopsis', None ) or payload.get( 'synopsis', None ) == '':
+ library.synopsis = payload.get( 'synopsis', None )
+ else:
+ raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
+ trans.sa_session.add( library )
+ trans.sa_session.flush()
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+
+ @expose_api
def delete( self, trans, id, **kwd ):
"""
delete( self, trans, id, **kwd )
- * DELETE /api/histories/{id}
- mark the library with the given ``id`` as deleted
+ * DELETE /api/libraries/{id}
+ marks the library with the given ``id`` as `deleted` (or removes the `deleted` mark if the `undelete` param is true)
- .. note:: Currently, only admin users can delete libraries.
+ .. note:: Currently, only admin users can un/delete libraries.
- :param id: the encoded id of the library to delete
+ :param id: the encoded id of the library to un/delete
:type id: str
+ :param undelete: flag specifying whether the item should be deleted or undeleted, defaults to false:
+ :type undelete: bool
+
+ :returns: detailed library information
:rtype: dictionary
- :returns: detailed library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
+ undelete = string_as_bool( kwd.get( 'undelete', False ) )
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to delete libraries.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can delete and undelete libraries.' )
try:
decoded_id = trans.security.decode_id( id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except Exception:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
- except:
+ except Exception:
library = None
if not library:
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- library.deleted = True
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ if undelete:
+ library.deleted = False
+ else:
+ library.deleted = True
+
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id } )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -135,7 +135,6 @@
path_prefix='/api/histories/:history_id/contents/:history_content_id' )
webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
- webapp.mapper.resource_with_deleted( 'library', 'libraries', path_prefix='/api' )
webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
@@ -206,6 +205,12 @@
# ===== LIBRARY API =====
# =======================
+ webapp.mapper.connect( 'update_library',
+ '/api/libraries/:id',
+ controller='libraries',
+ action='update',
+ conditions=dict( method=[ "PATCH" ] ) )
+
webapp.mapper.connect( 'show_lda_item',
'/api/libraries/datasets/:id',
controller='lda_datasets',
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: UI: Attach modal to body instead of #everything
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/52948dd567c8/
Changeset: 52948dd567c8
User: guerler
Date: 2014-03-06 07:41:16
Summary: UI: Attach modal to body instead of #everything
Affected #: 3 files
diff -r 310f5893da982d054b07de669f022dcfba4b1d3d -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,8 +1,8 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
+define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
'plugin/views/charts', 'plugin/views/chart',
'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
- function( Portlet, Ui, Utils, Jobs, Datasets,
+ function( Modal, Portlet, Ui, Utils, Jobs, Datasets,
ChartsView, ChartView,
Config, Chart, Charts, Types
) {
@@ -16,8 +16,12 @@
// link options
this.options = options;
- // link galaxy
- this.modal = Galaxy.modal;
+ // link galaxy modal or create one
+ if (Galaxy && Galaxy.modal) {
+ this.modal = Galaxy.modal;
+ } else {
+ this.modal = new Modal.View();
+ }
// create configuration model
this.config = new Config();
diff -r 310f5893da982d054b07de669f022dcfba4b1d3d -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 static/scripts/mvc/ui/ui-modal.js
--- a/static/scripts/mvc/ui/ui-modal.js
+++ b/static/scripts/mvc/ui/ui-modal.js
@@ -4,7 +4,7 @@
var View = Backbone.View.extend({
// base element
- elMain: '#everything',
+ elMain: 'body',
// defaults options
optionsDefault: {
diff -r 310f5893da982d054b07de669f022dcfba4b1d3d -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 static/scripts/packed/mvc/ui/ui-modal.js
--- a/static/scripts/packed/mvc/ui/ui-modal.js
+++ b/static/scripts/packed/mvc/ui/ui-modal.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove();$(document).off("keyup")}this.setElement(this._template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){d.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+c+'</h4></div><div class="modal-body" style="position: static;"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{View:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove();$(document).off("keyup")}this.setElement(this._template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){d.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+c+'</h4></div><div class="modal-body" style="position: static;"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{View:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: UI: Shift modal wrapper into mvc library
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/310f5893da98/
Changeset: 310f5893da98
User: guerler
Date: 2014-03-06 07:28:51
Summary: UI: Shift modal wrapper into mvc library
Affected #: 10 files
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d config/plugins/visualizations/charts/static/library/jobs.js
--- a/config/plugins/visualizations/charts/static/library/jobs.js
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -48,7 +48,9 @@
self.app.log('handle::load()', 'Job submission failed.');
} else {
// update galaxy history
- Galaxy.currHistoryPanel.refreshHdas();
+ if (Galaxy && Galaxy.currHistoryPanel) {
+ Galaxy.currHistoryPanel.refreshHdas();
+ }
// get dataset
var job = response.outputs[0];
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -9,10 +9,9 @@
// dependencies
define([
- "galaxy.modal",
"galaxy.masthead",
"utils/utils",
- "libs/toastr"], function(mod_modal, mod_masthead, mod_utils, mod_toastr) {
+ "libs/toastr"], function(mod_masthead, mod_utils, mod_toastr) {
// MMMMMMMMMMMMMMM
// === Models ====
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/galaxy.modal.js
--- a/static/scripts/galaxy.modal.js
+++ /dev/null
@@ -1,198 +0,0 @@
-// dependencies
-define([], function() {
-
-// modal
-var GalaxyModal = Backbone.View.extend(
-{
- // base element
- elMain: '#everything',
-
- // defaults options
- optionsDefault: {
- title : "galaxy-modal",
- body : "",
- backdrop : true,
- height : null,
- width : null,
- closing_events : false
- },
-
- // button list
- buttonList: {},
-
- // initialize
- initialize : function(options) {
- if (options){
- this._create(options);
- }
- },
-
- // adds and displays a new frame/window
- show: function(options) {
- // create
- this.initialize(options);
-
- // fix height
- if (this.options.height){
- this.$body.css('height', this.options.height);
- this.$body.css('overflow', 'hidden');
- } else{
- this.$body.css('max-height', $(window).height() / 2);
- }
-
- // fix width
- if (this.options.width){
- this.$dialog.css('width', this.options.width);
- }
-
- // show
- if (this.visible) {
- this.$el.show();
- } else {
- this.$el.fadeIn('fast');
- }
-
- // set visible flag
- this.visible = true;
- },
-
- // hide
- hide: function() {
- this.visible = false;
- this.$el.fadeOut('fast');
- },
-
- // enable buttons
- enableButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).prop('disabled', false);
- },
-
- // disable buttons
- disableButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).prop('disabled', true);
- },
-
- // show buttons
- showButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).show();
- },
-
- // hide buttons
- hideButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).hide();
- },
-
- // get button
- getButton: function(name) {
- var button_id = this.buttonList[name];
- return this.$buttons.find('#' + button_id);
- },
-
- // returns scroll top for body element
- scrollTop: function() {
- return this.$body.scrollTop();
- },
-
- // create
- _create: function(options) {
- // link this
- var self = this;
-
- // configure options
- this.options = _.defaults(options, this.optionsDefault);
-
- // check for progress bar request
- if (this.options.body == 'progress'){
- this.options.body = $('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>');
- }
-
- // remove former element
- if (this.$el) {
- // remove element
- this.$el.remove();
-
- // remove escape event
- $(document).off('keyup');
- }
-
- // create new element
- this.setElement(this._template(this.options.title));
-
- // link elements
- this.$dialog = (this.$el).find('.modal-dialog');
- this.$body = (this.$el).find('.modal-body');
- this.$footer = (this.$el).find('.modal-footer');
- this.$buttons = (this.$el).find('.buttons');
- this.$backdrop = (this.$el).find('.modal-backdrop');
-
- // append body
- this.$body.html(this.options.body);
-
- // configure background
- if (!this.options.backdrop){
- this.$backdrop.removeClass('in');
- }
-
- // append buttons
- if (this.options.buttons) {
- // reset button list
- this.buttonList = {};
- var counter = 0;
- $.each(this.options.buttons, function(name, value) {
- var button_id = 'button-' + counter++;
- self.$buttons.append($('<button id="' + button_id + '"></button>').text(name).click(value)).append(" ");
- self.buttonList[name] = button_id;
- });
- } else {
- // hide footer
- this.$footer.hide();
- }
-
- // append to main element
- $(this.elMain).append($(this.el));
-
- // bind additional closing events
- if (this.options.closing_events) {
- // bind the ESC key to hide() function
- if (!this.options.buttons.Pause){ // don't bind for the upload modal because of the side effects with system modal for file choosing
- $(document).on('keyup', function(e) {
- if (e.keyCode == 27) {
- self.hide();
- }
- });
- }
-
- // hide modal if background is clicked
- this.$el.find('.modal-backdrop').on('click', function() { self.hide(); });
- }
- },
-
- // fill regular modal template
- _template: function(title) {
- return '<div class="modal">' +
- '<div class="modal-backdrop fade in" style="z-index: -1;"></div>' +
- '<div class="modal-dialog">' +
- '<div class="modal-content">' +
- '<div class="modal-header">' +
- '<button type="button" class="close" style="display: none;">×</button>' +
- '<h4 class="title">' + title + '</h4>' +
- '</div>' +
- '<div class="modal-body" style="position: static;"></div>' +
- '<div class="modal-footer">' +
- '<div class="buttons" style="float: right;"></div>' +
- '</div>' +
- '</div' +
- '</div>' +
- '</div>';
- }
-});
-
-return {
- GalaxyModal : GalaxyModal
-}
-
-});
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/mvc/ui/ui-modal.js
--- /dev/null
+++ b/static/scripts/mvc/ui/ui-modal.js
@@ -0,0 +1,197 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+var View = Backbone.View.extend({
+
+ // base element
+ elMain: '#everything',
+
+ // defaults options
+ optionsDefault: {
+ title : 'ui-modal',
+ body : '',
+ backdrop : true,
+ height : null,
+ width : null,
+ closing_events : false
+ },
+
+ // button list
+ buttonList: {},
+
+ // initialize
+ initialize : function(options) {
+ if (options){
+ this._create(options);
+ }
+ },
+
+ // adds and displays a new frame/window
+ show: function(options) {
+ // create
+ this.initialize(options);
+
+ // fix height
+ if (this.options.height){
+ this.$body.css('height', this.options.height);
+ this.$body.css('overflow', 'hidden');
+ } else{
+ this.$body.css('max-height', $(window).height() / 2);
+ }
+
+ // fix width
+ if (this.options.width){
+ this.$dialog.css('width', this.options.width);
+ }
+
+ // show
+ if (this.visible) {
+ this.$el.show();
+ } else {
+ this.$el.fadeIn('fast');
+ }
+
+ // set visible flag
+ this.visible = true;
+ },
+
+ // hide
+ hide: function() {
+ this.visible = false;
+ this.$el.fadeOut('fast');
+ },
+
+ // enable buttons
+ enableButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).prop('disabled', false);
+ },
+
+ // disable buttons
+ disableButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).prop('disabled', true);
+ },
+
+ // show buttons
+ showButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).show();
+ },
+
+ // hide buttons
+ hideButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).hide();
+ },
+
+ // get button
+ getButton: function(name) {
+ var button_id = this.buttonList[name];
+ return this.$buttons.find('#' + button_id);
+ },
+
+ // returns scroll top for body element
+ scrollTop: function() {
+ return this.$body.scrollTop();
+ },
+
+ // create
+ _create: function(options) {
+ // link this
+ var self = this;
+
+ // configure options
+ this.options = _.defaults(options, this.optionsDefault);
+
+ // check for progress bar request
+ if (this.options.body == 'progress'){
+ this.options.body = $('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>');
+ }
+
+ // remove former element
+ if (this.$el) {
+ // remove element
+ this.$el.remove();
+
+ // remove escape event
+ $(document).off('keyup');
+ }
+
+ // create new element
+ this.setElement(this._template(this.options.title));
+
+ // link elements
+ this.$dialog = (this.$el).find('.modal-dialog');
+ this.$body = (this.$el).find('.modal-body');
+ this.$footer = (this.$el).find('.modal-footer');
+ this.$buttons = (this.$el).find('.buttons');
+ this.$backdrop = (this.$el).find('.modal-backdrop');
+
+ // append body
+ this.$body.html(this.options.body);
+
+ // configure background
+ if (!this.options.backdrop){
+ this.$backdrop.removeClass('in');
+ }
+
+ // append buttons
+ if (this.options.buttons) {
+ // reset button list
+ this.buttonList = {};
+ var counter = 0;
+ $.each(this.options.buttons, function(name, value) {
+ var button_id = 'button-' + counter++;
+ self.$buttons.append($('<button id="' + button_id + '"></button>').text(name).click(value)).append(" ");
+ self.buttonList[name] = button_id;
+ });
+ } else {
+ // hide footer
+ this.$footer.hide();
+ }
+
+ // append to main element
+ $(this.elMain).append($(this.el));
+
+ // bind additional closing events
+ if (this.options.closing_events) {
+ // bind the ESC key to hide() function
+ if (!this.options.buttons.Pause){ // don't bind for the upload modal because of the side effects with system modal for file choosing
+ $(document).on('keyup', function(e) {
+ if (e.keyCode == 27) {
+ self.hide();
+ }
+ });
+ }
+
+ // hide modal if background is clicked
+ this.$el.find('.modal-backdrop').on('click', function() { self.hide(); });
+ }
+ },
+
+ // fill regular modal template
+ _template: function(title) {
+ return '<div class="modal">' +
+ '<div class="modal-backdrop fade in" style="z-index: -1;"></div>' +
+ '<div class="modal-dialog">' +
+ '<div class="modal-content">' +
+ '<div class="modal-header">' +
+ '<button type="button" class="close" style="display: none;">×</button>' +
+ '<h4 class="title">' + title + '</h4>' +
+ '</div>' +
+ '<div class="modal-body" style="position: static;"></div>' +
+ '<div class="modal-footer">' +
+ '<div class="buttons" style="float: right;"></div>' +
+ '</div>' +
+ '</div' +
+ '</div>' +
+ '</div>';
+ }
+});
+
+return {
+ View : View
+}
+
+});
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -1,21 +1,21 @@
// dependencies
-define(["galaxy.modal",
- "utils/utils",
+define(["utils/utils",
"mvc/upload/upload-button",
"mvc/upload/upload-model",
"mvc/upload/upload-row",
"mvc/upload/upload-ftp",
"mvc/ui/ui-popover",
+ "mvc/ui/ui-modal",
"mvc/ui",
"utils/uploadbox"],
- function( Modal,
- Utils,
+ function( Utils,
UploadButton,
UploadModel,
UploadItem,
UploadFtp,
- Popover
+ Popover,
+ Modal
) {
// galaxy upload
@@ -177,7 +177,7 @@
if (!this.modal) {
// make modal
var self = this;
- this.modal = new Modal.GalaxyModal({
+ this.modal = new Modal.View({
title : 'Download data directly from web or upload files from your disk',
body : this._template('upload-box', 'upload-info'),
buttons : {
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/galaxy.library.js
--- a/static/scripts/packed/galaxy.library.js
+++ b/static/scripts/packed/galaxy.library.js
@@ -1,1 +1,1 @@
-var view=null;var library_router=null;var responses=[];define(["galaxy.modal","galaxy.masthead","utils/utils","libs/toastr"],function(k,l,h,n){var f=Backbone.Model.extend({urlRoot:"/api/libraries"});var c=Backbone.Model.extend({urlRoot:"/api/folders"});var o=Backbone.Collection.extend({url:"/api/libraries",model:f,sort_key:"name",sort_order:null,});var i=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var d=Backbone.Collection.extend({model:i});var e=Backbone.Model.extend({defaults:{folder:new d(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(r){this.full_path=r[0].full_path;this.get("folder").reset(r[1].folder_contents);return r}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var j=Backbone.Model.extend({url:"/api/histories/"});var p=Backbone.Collection.extend({url:"/api/histories",model:j});var m=Backbone.View.extend({el:"#center",progress:0,progressStep:1,lastSelectedHistory:"",modal:null,folders:null,initialize:function(){this.folders=[];this.queue=jQuery.Deferred();this.queue.resolve()},templateFolder:function(){var r=[];r.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; ">');r.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');r.push('<div id="library_folder_toolbar" >');r.push(' <button title="Create New Folder" id="toolbtn_create_folder" class="btn btn-primary" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder-close"></span> folder</button>');r.push(' <button title="Import selected datasets into history" id="toolbtn_bulk_import" class="btn btn-primary" style="display: none; margin-left: 0.5em;" type="button"><span class="fa fa-external-link"></span> to history</button>');r.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display: none; ">');r.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">');r.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');r.push(" </button>");r.push(' <ul class="dropdown-menu" role="menu">');r.push(' <li><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');r.push(' <li><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');r.push(' <li><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');r.push(" </ul>");r.push(" </div>");r.push("</div>");r.push('<ol class="breadcrumb">');r.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');r.push(" <% _.each(path, function(path_item) { %>");r.push(" <% if (path_item[0] != id) { %>");r.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');r.push("<% } else { %>");r.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');r.push(" <% } %>");r.push(" <% }); %>");r.push("</ol>");r.push('<table id="folder_table" class="library_table table table-condensed">');r.push(" <thead>");r.push(' <th class="button_heading"></th>');r.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');r.push(" <th>name</th>");r.push(" <th>data type</th>");r.push(" <th>size</th>");r.push(" <th>date (UTC)</th>");r.push(" </thead>");r.push(" <tbody>");r.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');r.push(" <td></td>");r.push(" <td></td>");r.push(" <td></td>");r.push(" <td></td>");r.push(" <td></td>");r.push(" </tr>");r.push(" <% _.each(items, function(content_item) { %>");r.push(' <% if (content_item.get("type") === "folder") { %>');r.push(' <tr class="folder_row light" id="<%- content_item.id %>">');r.push(" <td>");r.push(' <span title="Folder" class="fa fa-folder-o"></span>');r.push(" </td>");r.push(" <td></td>");r.push(" <td>");r.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');r.push(' <% if (content_item.get("item_count") === 0) { %>');r.push(' <span class="muted">(empty folder)</span>');r.push(" <% } %>");r.push(" </td>");r.push(" <td>folder</td>");r.push(' <td><%= _.escape(content_item.get("item_count")) %> item(s)</td>');r.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');r.push(" </tr>");r.push(" <% } else { %>");r.push(' <tr class="dataset_row light" id="<%- content_item.id %>">');r.push(" <td>");r.push(' <span title="Dataset" class="fa fa-file-o"></span>');r.push(" </td>");r.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');r.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');r.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');r.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');r.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');r.push(" </tr>");r.push(" <% } %> ");r.push(" <% }); %>");r.push(" ");r.push(" </tbody>");r.push("</table>");r.push("</div>");return r.join("")},templateDatasetModal:function(){var r=[];r.push('<div class="modal_table">');r.push(' <table class="table table-striped table-condensed">');r.push(" <tr>");r.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');r.push(' <td><%= _.escape(item.get("name")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Data type</th>');r.push(' <td><%= _.escape(item.get("data_type")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Genome build</th>');r.push(' <td><%= _.escape(item.get("genome_build")) %></td>');r.push(" </tr>");r.push(' <th scope="row">Size</th>');r.push(" <td><%= _.escape(size) %></td>");r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Date uploaded (UTC)</th>');r.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Uploaded by</th>');r.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');r.push(" </tr>");r.push(' <tr scope="row">');r.push(' <th scope="row">Data Lines</th>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');r.push(" </tr>");r.push(' <th scope="row">Comment Lines</th>');r.push(' <% if (item.get("metadata_comment_lines") === "") { %>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');r.push(" <% } else { %>");r.push(' <td scope="row">unknown</td>');r.push(" <% } %>");r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Number of Columns</th>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Column Types</th>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Miscellaneous information</th>');r.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');r.push(" </tr>");r.push(" </table>");r.push(' <pre class="peek">');r.push(" </pre>");r.push("</div>");return r.join("")},templateHistorySelectInModal:function(){var r=[];r.push('<span id="history_modal_combo" style="width:90%; margin-left: 1em; margin-right: 1em; ">');r.push("Select history: ");r.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');r.push(" <% _.each(histories, function(history) { %>");r.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');r.push(" <% }); %>");r.push("</select>");r.push("</span>");return r.join("")},templateBulkImportInModal:function(){var r=[];r.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');r.push("Select history: ");r.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');r.push(" <% _.each(histories, function(history) { %>");r.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');r.push(" <% }); %>");r.push("</select>");r.push("</span>");return r.join("")},templateProgressBar:function(){var r=[];r.push('<div class="import_text">');r.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");r.push("</div>");r.push('<div class="progress">');r.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');r.push(' <span class="completion_span">0% Complete</span>');r.push(" </div>");r.push("</div>");r.push("");return r.join("")},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_modal">');tmpl_array.push("<form>");tmpl_array.push('<input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push('<input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push("</form>");tmpl_array.push("</div>");return tmpl_array.join("")},events:{"click #select-all-checkboxes":"selectAll","click #toolbtn_bulk_import":"modalBulkImport","click #toolbtn_dl":"bulkDownload","click #toolbtn_create_folder":"createFolderFromModal","click .library-dataset":"showDatasetDetails","click .dataset_row":"selectClickedRow"},render:function(r){$("#center").css("overflow","auto");view=this;var t=this;var s=new e({id:r.id});s.url=s.attributes.urlRoot+r.id+"/contents";s.fetch({success:function(u){for(var w=0;w<s.attributes.folder.models.length;w++){var v=s.attributes.folder.models[w];if(v.get("type")==="file"){v.set("readable_size",t.size_to_string(v.get("file_size")))}}var y=s.full_path;var z;if(y.length===1){z=0}else{z=y[y.length-2][0]}var x=_.template(t.templateFolder(),{path:s.full_path,items:s.attributes.folder.models,id:r.id,upper_folder_id:z});t.$el.html(x)},error:function(){n.error("An error occured :(")}})},size_to_string:function(r){var s="";if(r>=100000000000){r=r/100000000000;s="TB"}else{if(r>=100000000){r=r/100000000;s="GB"}else{if(r>=100000){r=r/100000;s="MB"}else{if(r>=100){r=r/100;s="KB"}else{r=r*10;s="b"}}}}return(Math.round(r)/10)+s},showDatasetDetails:function(u){u.preventDefault();var v=$(u.target).parent().parent().parent().attr("id");if(typeof v==="undefined"){v=$(u.target).parent().attr("id")}if(typeof v==="undefined"){v=$(u.target).parent().parent().attr("id")}var t=new i();var s=new p();t.id=v;var r=this;t.fetch({success:function(w){s.fetch({success:function(x){r.renderModalAfterFetch(w,x)},error:function(){n.error("An error occured during fetching histories:(");r.renderModalAfterFetch(w)}})},error:function(){n.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(w,t){var u=this.size_to_string(w.get("file_size"));var v=_.template(this.templateDatasetModal(),{item:w,size:u});var s=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:v,buttons:{Import:function(){s.importCurrentIntoHistory()},Download:function(){s.downloadCurrent()},Close:function(){s.modal.hide()}}});$(".peek").html(w.get("peek"));if(typeof history.models!==undefined){var r=_.template(this.templateHistorySelectInModal(),{histories:t.models});$(this.modal.elMain).find(".buttons").prepend(r);if(s.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(s.lastSelectedHistory)}}},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var r=[];r.push($("#id_row").attr("data-id"));var s="/api/libraries/datasets/download/uncompressed";var t={ldda_ids:r};folderContentView.processDownload(s,t);this.modal.enableButton("Import");this.modal.enableButton("Download")},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var t=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=t;var r=$("#id_row").attr("data-id");var u=new b();var s=this;u.url=u.urlRoot+t+"/contents";u.save({content:r,source:"library"},{success:function(){n.success("Dataset imported");s.modal.enableButton("Import");s.modal.enableButton("Download")},error:function(){n.error("An error occured! Dataset not imported. Please try again.");s.modal.enableButton("Import");s.modal.enableButton("Download")}})},selectAll:function(s){var r=s.target.checked;that=this;$(":checkbox").each(function(){this.checked=r;$row=$(this.parentElement.parentElement);(r)?that.makeDarkRow($row):that.makeWhiteRow($row)});this.checkTools()},selectClickedRow:function(s){var u="";var r;var t;if(s.target.localName==="input"){u=s.target;r=$(s.target.parentElement.parentElement);t="input"}else{if(s.target.localName==="td"){u=$("#"+s.target.parentElement.id).find(":checkbox")[0];r=$(s.target.parentElement);t="td"}}if(u.checked){if(t==="td"){u.checked="";this.makeWhiteRow(r)}else{if(t==="input"){this.makeDarkRow(r)}}}else{if(t==="td"){u.checked="selected";this.makeDarkRow(r)}else{if(t==="input"){this.makeWhiteRow(r)}}}this.checkTools()},makeDarkRow:function(r){r.removeClass("light");r.find("a").removeClass("light");r.addClass("dark");r.find("a").addClass("dark");r.find("span").removeClass("fa-file-o");r.find("span").addClass("fa-file")},makeWhiteRow:function(r){r.removeClass("dark");r.find("a").removeClass("dark");r.addClass("light");r.find("a").addClass("light");r.find("span").addClass("fa-file-o");r.find("span").removeClass("fa-file")},checkTools:function(){var r=$("#folder_table").find(":checked");if(r.length>0){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}else{$("#toolbtn_bulk_import").hide();$("#toolbtn_dl").hide()}},modalBulkImport:function(){var s=this;var r=new p();r.fetch({success:function(t){var u=_.template(s.templateBulkImportInModal(),{histories:t.models});s.modal=Galaxy.modal;s.modal.show({closing_events:true,title:"Import into History",body:u,buttons:{Import:function(){s.importAllIntoHistory()},Close:function(){s.modal.hide()}}})},error:function(){n.error("An error occured :(")}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var t=$("select[name=dataset_import_bulk] option:selected").val();var x=$("select[name=dataset_import_bulk] option:selected").text();var z=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){z.push(this.parentElement.parentElement.id)}});var y=_.template(this.templateProgressBar(),{history_name:x});$(this.modal.elMain).find(".modal-body").html(y);var u=100/z.length;this.initProgress(u);var r=[];for(var s=z.length-1;s>=0;s--){library_dataset_id=z[s];var v=new b();var w=this;v.url=v.urlRoot+t+"/contents";v.content=library_dataset_id;v.source="library";r.push(v)}this.chainCall(r)},chainCall:function(s){var r=this;var t=s.pop();if(typeof t==="undefined"){n.success("All datasets imported");this.modal.hide();return}var u=$.when(t.save({content:t.content,source:t.source})).done(function(v){r.updateProgress();responses.push(v);r.chainCall(s)})},initProgress:function(r){this.progress=0;this.progressStep=r},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(r,v){var t=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){t.push(this.parentElement.parentElement.id)}});var s="/api/libraries/datasets/download/"+v;var u={ldda_ids:t};this.processDownload(s,u,"get")},processDownload:function(s,t,u){if(s&&t){t=typeof t=="string"?t:$.param(t);var r="";$.each(t.split("&"),function(){var v=this.split("=");r+='<input type="hidden" name="'+v[0]+'" value="'+v[1]+'" />'});$('<form action="'+s+'" method="'+(u||"post")+'">'+r+"</form>").appendTo("body").submit().remove();n.info("Your download will begin soon")}},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var r=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:this.templateNewFolderInModal(),buttons:{Create:function(){r.create_new_folder_event()},Close:function(){r.modal.hide();r.modal=null}}})},create_new_folder_event:function(){var r=this.serialize_new_folder();if(this.validate_new_folder(r)){var t=new c();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];t.url=t.urlRoot+"/"+current_folder_id;var s=this;t.save(r,{success:function(u){s.modal.hide();n.success("Folder created");s.render({id:current_folder_id})},error:function(){n.error("An error occured :(")}})}else{n.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(r){return r.name!==""}});var a=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal"},modal:null,collection:null,initialize:function(){var r=this;this.collection=new o();this.collection.fetch({success:function(s){r.render()},error:function(t,s){if(s.statusCode().status===403){n.info("Please log in first. Redirecting to login page in 3s.");setTimeout(that.redirectToLogin,3000)}else{n.error("An error occured. Please try again.")}}});$("#center").css("overflow","auto")},render:function(t){var r=this.templateLibraryList();var s=null;if(this.collection!==null&&typeof t==="undefined"){s=this.collection.models}else{if(t!==null){s=t}else{s=[]}}this.$el.html(r({libraries:s,order:this.collection.sort_order}))},sortLibraries:function(s,r){if(s==="name"){if(r==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(u,t){if(u.get("name").toLowerCase()>t.get("name").toLowerCase()){return 1}if(t.get("name").toLowerCase()>u.get("name").toLowerCase()){return -1}return 0}}else{if(r==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(u,t){if(u.get("name").toLowerCase()>t.get("name").toLowerCase()){return -1}if(t.get("name").toLowerCase()>u.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; overflow: auto !important; ">');tmpl_array.push("");tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push('<a href="" id="create_new_library_btn" class="btn btn-primary file ">New Library</a>');tmpl_array.push('<table class="library_table table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th><a title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(" <th>description</th>");tmpl_array.push(" <th>synopsis</th> ");tmpl_array.push(" </thead>");tmpl_array.push(" <tbody>");tmpl_array.push(" <% _.each(libraries, function(library) { %>");tmpl_array.push(" <tr>");tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(" </tr>");tmpl_array.push(" <% }); %>");tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(s){s.preventDefault();s.stopPropagation();var r=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){r.create_new_library_event()},Close:function(){r.modal.hide()}}})},create_new_library_event:function(){var t=this.serialize_new_library();if(this.validate_new_library(t)){var s=new f();var r=this;s.save(t,{success:function(u){r.collection.add(u);r.modal.hide();r.clear_library_modal();r.render();n.success("Library created")},error:function(){n.error("An error occured :(")}})}else{n.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(r){return r.name!==""}});var q=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var g=Backbone.View.extend({initialize:function(){galaxyLibraryview=new a();library_router=new q();folderContentView=new m();library_router.on("route:libraries",function(){galaxyLibraryview.render()});library_router.on("route:sort_libraries",function(s,r){galaxyLibraryview.sortLibraries(s,r);galaxyLibraryview.render()});library_router.on("route:folder_content",function(r){folderContentView.render({id:r})});library_router.on("route:download",function(r,s){if($("#center").find(":checked").length===0){library_router.navigate("folders/"+r,{trigger:true,replace:true})}else{folderContentView.download(r,s);library_router.navigate("folders/"+r,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:g}});
\ No newline at end of file
+var view=null;var library_router=null;var responses=[];define(["galaxy.masthead","utils/utils","libs/toastr"],function(k,h,m){var f=Backbone.Model.extend({urlRoot:"/api/libraries"});var c=Backbone.Model.extend({urlRoot:"/api/folders"});var n=Backbone.Collection.extend({url:"/api/libraries",model:f,sort_key:"name",sort_order:null,});var i=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var d=Backbone.Collection.extend({model:i});var e=Backbone.Model.extend({defaults:{folder:new d(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(q){this.full_path=q[0].full_path;this.get("folder").reset(q[1].folder_contents);return q}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var j=Backbone.Model.extend({url:"/api/histories/"});var o=Backbone.Collection.extend({url:"/api/histories",model:j});var l=Backbone.View.extend({el:"#center",progress:0,progressStep:1,lastSelectedHistory:"",modal:null,folders:null,initialize:function(){this.folders=[];this.queue=jQuery.Deferred();this.queue.resolve()},templateFolder:function(){var q=[];q.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; ">');q.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');q.push('<div id="library_folder_toolbar" >');q.push(' <button title="Create New Folder" id="toolbtn_create_folder" class="btn btn-primary" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder-close"></span> folder</button>');q.push(' <button title="Import selected datasets into history" id="toolbtn_bulk_import" class="btn btn-primary" style="display: none; margin-left: 0.5em;" type="button"><span class="fa fa-external-link"></span> to history</button>');q.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display: none; ">');q.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">');q.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');q.push(" </button>");q.push(' <ul class="dropdown-menu" role="menu">');q.push(' <li><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');q.push(' <li><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');q.push(' <li><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');q.push(" </ul>");q.push(" </div>");q.push("</div>");q.push('<ol class="breadcrumb">');q.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');q.push(" <% _.each(path, function(path_item) { %>");q.push(" <% if (path_item[0] != id) { %>");q.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');q.push("<% } else { %>");q.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');q.push(" <% } %>");q.push(" <% }); %>");q.push("</ol>");q.push('<table id="folder_table" class="library_table table table-condensed">');q.push(" <thead>");q.push(' <th class="button_heading"></th>');q.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');q.push(" <th>name</th>");q.push(" <th>data type</th>");q.push(" <th>size</th>");q.push(" <th>date (UTC)</th>");q.push(" </thead>");q.push(" <tbody>");q.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');q.push(" <td></td>");q.push(" <td></td>");q.push(" <td></td>");q.push(" <td></td>");q.push(" <td></td>");q.push(" </tr>");q.push(" <% _.each(items, function(content_item) { %>");q.push(' <% if (content_item.get("type") === "folder") { %>');q.push(' <tr class="folder_row light" id="<%- content_item.id %>">');q.push(" <td>");q.push(' <span title="Folder" class="fa fa-folder-o"></span>');q.push(" </td>");q.push(" <td></td>");q.push(" <td>");q.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');q.push(' <% if (content_item.get("item_count") === 0) { %>');q.push(' <span class="muted">(empty folder)</span>');q.push(" <% } %>");q.push(" </td>");q.push(" <td>folder</td>");q.push(' <td><%= _.escape(content_item.get("item_count")) %> item(s)</td>');q.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');q.push(" </tr>");q.push(" <% } else { %>");q.push(' <tr class="dataset_row light" id="<%- content_item.id %>">');q.push(" <td>");q.push(' <span title="Dataset" class="fa fa-file-o"></span>');q.push(" </td>");q.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');q.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');q.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');q.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');q.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');q.push(" </tr>");q.push(" <% } %> ");q.push(" <% }); %>");q.push(" ");q.push(" </tbody>");q.push("</table>");q.push("</div>");return q.join("")},templateDatasetModal:function(){var q=[];q.push('<div class="modal_table">');q.push(' <table class="table table-striped table-condensed">');q.push(" <tr>");q.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');q.push(' <td><%= _.escape(item.get("name")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Data type</th>');q.push(' <td><%= _.escape(item.get("data_type")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Genome build</th>');q.push(' <td><%= _.escape(item.get("genome_build")) %></td>');q.push(" </tr>");q.push(' <th scope="row">Size</th>');q.push(" <td><%= _.escape(size) %></td>");q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Date uploaded (UTC)</th>');q.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Uploaded by</th>');q.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');q.push(" </tr>");q.push(' <tr scope="row">');q.push(' <th scope="row">Data Lines</th>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');q.push(" </tr>");q.push(' <th scope="row">Comment Lines</th>');q.push(' <% if (item.get("metadata_comment_lines") === "") { %>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');q.push(" <% } else { %>");q.push(' <td scope="row">unknown</td>');q.push(" <% } %>");q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Number of Columns</th>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Column Types</th>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Miscellaneous information</th>');q.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');q.push(" </tr>");q.push(" </table>");q.push(' <pre class="peek">');q.push(" </pre>");q.push("</div>");return q.join("")},templateHistorySelectInModal:function(){var q=[];q.push('<span id="history_modal_combo" style="width:90%; margin-left: 1em; margin-right: 1em; ">');q.push("Select history: ");q.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');q.push(" <% _.each(histories, function(history) { %>");q.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');q.push(" <% }); %>");q.push("</select>");q.push("</span>");return q.join("")},templateBulkImportInModal:function(){var q=[];q.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');q.push("Select history: ");q.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');q.push(" <% _.each(histories, function(history) { %>");q.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');q.push(" <% }); %>");q.push("</select>");q.push("</span>");return q.join("")},templateProgressBar:function(){var q=[];q.push('<div class="import_text">');q.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");q.push("</div>");q.push('<div class="progress">');q.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');q.push(' <span class="completion_span">0% Complete</span>');q.push(" </div>");q.push("</div>");q.push("");return q.join("")},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_modal">');tmpl_array.push("<form>");tmpl_array.push('<input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push('<input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push("</form>");tmpl_array.push("</div>");return tmpl_array.join("")},events:{"click #select-all-checkboxes":"selectAll","click #toolbtn_bulk_import":"modalBulkImport","click #toolbtn_dl":"bulkDownload","click #toolbtn_create_folder":"createFolderFromModal","click .library-dataset":"showDatasetDetails","click .dataset_row":"selectClickedRow"},render:function(q){$("#center").css("overflow","auto");view=this;var s=this;var r=new e({id:q.id});r.url=r.attributes.urlRoot+q.id+"/contents";r.fetch({success:function(t){for(var v=0;v<r.attributes.folder.models.length;v++){var u=r.attributes.folder.models[v];if(u.get("type")==="file"){u.set("readable_size",s.size_to_string(u.get("file_size")))}}var x=r.full_path;var y;if(x.length===1){y=0}else{y=x[x.length-2][0]}var w=_.template(s.templateFolder(),{path:r.full_path,items:r.attributes.folder.models,id:q.id,upper_folder_id:y});s.$el.html(w)},error:function(){m.error("An error occured :(")}})},size_to_string:function(q){var r="";if(q>=100000000000){q=q/100000000000;r="TB"}else{if(q>=100000000){q=q/100000000;r="GB"}else{if(q>=100000){q=q/100000;r="MB"}else{if(q>=100){q=q/100;r="KB"}else{q=q*10;r="b"}}}}return(Math.round(q)/10)+r},showDatasetDetails:function(t){t.preventDefault();var u=$(t.target).parent().parent().parent().attr("id");if(typeof u==="undefined"){u=$(t.target).parent().attr("id")}if(typeof u==="undefined"){u=$(t.target).parent().parent().attr("id")}var s=new i();var r=new o();s.id=u;var q=this;s.fetch({success:function(v){r.fetch({success:function(w){q.renderModalAfterFetch(v,w)},error:function(){m.error("An error occured during fetching histories:(");q.renderModalAfterFetch(v)}})},error:function(){m.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(v,s){var t=this.size_to_string(v.get("file_size"));var u=_.template(this.templateDatasetModal(),{item:v,size:t});var r=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:u,buttons:{Import:function(){r.importCurrentIntoHistory()},Download:function(){r.downloadCurrent()},Close:function(){r.modal.hide()}}});$(".peek").html(v.get("peek"));if(typeof history.models!==undefined){var q=_.template(this.templateHistorySelectInModal(),{histories:s.models});$(this.modal.elMain).find(".buttons").prepend(q);if(r.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(r.lastSelectedHistory)}}},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var q=[];q.push($("#id_row").attr("data-id"));var r="/api/libraries/datasets/download/uncompressed";var s={ldda_ids:q};folderContentView.processDownload(r,s);this.modal.enableButton("Import");this.modal.enableButton("Download")},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var s=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=s;var q=$("#id_row").attr("data-id");var t=new b();var r=this;t.url=t.urlRoot+s+"/contents";t.save({content:q,source:"library"},{success:function(){m.success("Dataset imported");r.modal.enableButton("Import");r.modal.enableButton("Download")},error:function(){m.error("An error occured! Dataset not imported. Please try again.");r.modal.enableButton("Import");r.modal.enableButton("Download")}})},selectAll:function(r){var q=r.target.checked;that=this;$(":checkbox").each(function(){this.checked=q;$row=$(this.parentElement.parentElement);(q)?that.makeDarkRow($row):that.makeWhiteRow($row)});this.checkTools()},selectClickedRow:function(r){var t="";var q;var s;if(r.target.localName==="input"){t=r.target;q=$(r.target.parentElement.parentElement);s="input"}else{if(r.target.localName==="td"){t=$("#"+r.target.parentElement.id).find(":checkbox")[0];q=$(r.target.parentElement);s="td"}}if(t.checked){if(s==="td"){t.checked="";this.makeWhiteRow(q)}else{if(s==="input"){this.makeDarkRow(q)}}}else{if(s==="td"){t.checked="selected";this.makeDarkRow(q)}else{if(s==="input"){this.makeWhiteRow(q)}}}this.checkTools()},makeDarkRow:function(q){q.removeClass("light");q.find("a").removeClass("light");q.addClass("dark");q.find("a").addClass("dark");q.find("span").removeClass("fa-file-o");q.find("span").addClass("fa-file")},makeWhiteRow:function(q){q.removeClass("dark");q.find("a").removeClass("dark");q.addClass("light");q.find("a").addClass("light");q.find("span").addClass("fa-file-o");q.find("span").removeClass("fa-file")},checkTools:function(){var q=$("#folder_table").find(":checked");if(q.length>0){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}else{$("#toolbtn_bulk_import").hide();$("#toolbtn_dl").hide()}},modalBulkImport:function(){var r=this;var q=new o();q.fetch({success:function(s){var t=_.template(r.templateBulkImportInModal(),{histories:s.models});r.modal=Galaxy.modal;r.modal.show({closing_events:true,title:"Import into History",body:t,buttons:{Import:function(){r.importAllIntoHistory()},Close:function(){r.modal.hide()}}})},error:function(){m.error("An error occured :(")}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var s=$("select[name=dataset_import_bulk] option:selected").val();var w=$("select[name=dataset_import_bulk] option:selected").text();var y=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){y.push(this.parentElement.parentElement.id)}});var x=_.template(this.templateProgressBar(),{history_name:w});$(this.modal.elMain).find(".modal-body").html(x);var t=100/y.length;this.initProgress(t);var q=[];for(var r=y.length-1;r>=0;r--){library_dataset_id=y[r];var u=new b();var v=this;u.url=u.urlRoot+s+"/contents";u.content=library_dataset_id;u.source="library";q.push(u)}this.chainCall(q)},chainCall:function(r){var q=this;var s=r.pop();if(typeof s==="undefined"){m.success("All datasets imported");this.modal.hide();return}var t=$.when(s.save({content:s.content,source:s.source})).done(function(u){q.updateProgress();responses.push(u);q.chainCall(r)})},initProgress:function(q){this.progress=0;this.progressStep=q},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(q,u){var s=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){s.push(this.parentElement.parentElement.id)}});var r="/api/libraries/datasets/download/"+u;var t={ldda_ids:s};this.processDownload(r,t,"get")},processDownload:function(r,s,t){if(r&&s){s=typeof s=="string"?s:$.param(s);var q="";$.each(s.split("&"),function(){var u=this.split("=");q+='<input type="hidden" name="'+u[0]+'" value="'+u[1]+'" />'});$('<form action="'+r+'" method="'+(t||"post")+'">'+q+"</form>").appendTo("body").submit().remove();m.info("Your download will begin soon")}},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var q=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:this.templateNewFolderInModal(),buttons:{Create:function(){q.create_new_folder_event()},Close:function(){q.modal.hide();q.modal=null}}})},create_new_folder_event:function(){var q=this.serialize_new_folder();if(this.validate_new_folder(q)){var s=new c();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];s.url=s.urlRoot+"/"+current_folder_id;var r=this;s.save(q,{success:function(t){r.modal.hide();m.success("Folder created");r.render({id:current_folder_id})},error:function(){m.error("An error occured :(")}})}else{m.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(q){return q.name!==""}});var a=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal"},modal:null,collection:null,initialize:function(){var q=this;this.collection=new n();this.collection.fetch({success:function(r){q.render()},error:function(s,r){if(r.statusCode().status===403){m.info("Please log in first. Redirecting to login page in 3s.");setTimeout(that.redirectToLogin,3000)}else{m.error("An error occured. Please try again.")}}});$("#center").css("overflow","auto")},render:function(s){var q=this.templateLibraryList();var r=null;if(this.collection!==null&&typeof s==="undefined"){r=this.collection.models}else{if(s!==null){r=s}else{r=[]}}this.$el.html(q({libraries:r,order:this.collection.sort_order}))},sortLibraries:function(r,q){if(r==="name"){if(q==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(t,s){if(t.get("name").toLowerCase()>s.get("name").toLowerCase()){return 1}if(s.get("name").toLowerCase()>t.get("name").toLowerCase()){return -1}return 0}}else{if(q==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(t,s){if(t.get("name").toLowerCase()>s.get("name").toLowerCase()){return -1}if(s.get("name").toLowerCase()>t.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; overflow: auto !important; ">');tmpl_array.push("");tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push('<a href="" id="create_new_library_btn" class="btn btn-primary file ">New Library</a>');tmpl_array.push('<table class="library_table table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th><a title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(" <th>description</th>");tmpl_array.push(" <th>synopsis</th> ");tmpl_array.push(" </thead>");tmpl_array.push(" <tbody>");tmpl_array.push(" <% _.each(libraries, function(library) { %>");tmpl_array.push(" <tr>");tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(" </tr>");tmpl_array.push(" <% }); %>");tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(r){r.preventDefault();r.stopPropagation();var q=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){q.create_new_library_event()},Close:function(){q.modal.hide()}}})},create_new_library_event:function(){var s=this.serialize_new_library();if(this.validate_new_library(s)){var r=new f();var q=this;r.save(s,{success:function(t){q.collection.add(t);q.modal.hide();q.clear_library_modal();q.render();m.success("Library created")},error:function(){m.error("An error occured :(")}})}else{m.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(q){return q.name!==""}});var p=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var g=Backbone.View.extend({initialize:function(){galaxyLibraryview=new a();library_router=new p();folderContentView=new l();library_router.on("route:libraries",function(){galaxyLibraryview.render()});library_router.on("route:sort_libraries",function(r,q){galaxyLibraryview.sortLibraries(r,q);galaxyLibraryview.render()});library_router.on("route:folder_content",function(q){folderContentView.render({id:q})});library_router.on("route:download",function(q,r){if($("#center").find(":checked").length===0){library_router.navigate("folders/"+q,{trigger:true,replace:true})}else{folderContentView.download(q,r);library_router.navigate("folders/"+q,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:g}});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/galaxy.modal.js
--- a/static/scripts/packed/galaxy.modal.js
+++ /dev/null
@@ -1,1 +0,0 @@
-define([],function(){var a=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"galaxy-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(b){if(b){this._create(b)}},show:function(b){this.initialize(b);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",true)},showButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).show()},hideButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).hide()},getButton:function(b){var c=this.buttonList[b];return this.$buttons.find("#"+c)},scrollTop:function(){return this.$body.scrollTop()},_create:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove();$(document).off("keyup")}this.setElement(this._template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var b=0;$.each(this.options.buttons,function(e,g){var f="button-"+b++;c.$buttons.append($('<button id="'+f+'"></button>').text(e).click(g)).append(" ");c.buttonList[e]=f})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){c.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){c.hide()})}},_template:function(b){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+b+'</h4></div><div class="modal-body" style="position: static;"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{GalaxyModal:a}});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/mvc/ui/ui-modal.js
--- /dev/null
+++ b/static/scripts/packed/mvc/ui/ui-modal.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,this.optionsDefault);if(this.options.body=="progress"){this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')}if(this.$el){this.$el.remove();$(document).off("keyup")}this.setElement(this._template(this.options.title));this.$dialog=(this.$el).find(".modal-dialog");this.$body=(this.$el).find(".modal-body");this.$footer=(this.$el).find(".modal-footer");this.$buttons=(this.$el).find(".buttons");this.$backdrop=(this.$el).find(".modal-backdrop");this.$body.html(this.options.body);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){d.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+c+'</h4></div><div class="modal-body" style="position: static;"></div><div class="modal-footer"><div class="buttons" style="float: right;"></div></div></div</div></div>'}});return{View:b}});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui/ui-popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,list_extensions:[],list_genomes:[],auto:{id:"auto",text:"Auto-detect",description:"This system will try to detect the file type automatically. If your file is not detected properly as one of the known formats, it most likely means that it has some format problems (e.g., different number of columns on different rows). You can still coerce the system to set your data to the format you think it should be. You can also upload compressed files, which will automatically be decompressed."},collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(i){this.options=_.defaults(i,this.options)}if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.get(galaxy_config.root+"api/datatypes?extension_only=False",function(j){for(key in j){h.list_extensions.push({id:j[key].extension,text:j[key].extension,description:j[key].description,description_url:j[key].description_url})}h.list_extensions.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0});if(!h.options.datatypes_disable_auto){h.list_extensions.unshift(h.auto)}});f.get(galaxy_config.root+"api/genomes",function(j){for(key in j){h.list_genomes.push({id:j[key][1],text:j[key][0]})}h.list_genomes.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0})});this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Paste/Fetch data":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}this.modal.show();this._updateUser();this._updateScreen()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}tool_input={};if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateUser:function(){this.current_user=Galaxy.currUser.get("id");this.current_history=null;if(this.current_user){this.current_history=Galaxy.currHistoryPanel.model.get("id")}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Paste/Fetch data")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Paste/Fetch data")}if(this.current_user&&this.options.ftp_upload_dir&&this.options.ftp_upload_site){this.modal.showButton("Choose FTP file")}else{this.modal.hideButton("Choose FTP file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui/ui-popover","mvc/ui/ui-modal","mvc/ui","utils/uploadbox"],function(f,e,c,b,g,d,a){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,list_extensions:[],list_genomes:[],auto:{id:"auto",text:"Auto-detect",description:"This system will try to detect the file type automatically. If your file is not detected properly as one of the known formats, it most likely means that it has some format problems (e.g., different number of columns on different rows). You can still coerce the system to set your data to the format you think it should be. You can also upload compressed files, which will automatically be decompressed."},collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(i){this.options=_.defaults(i,this.options)}if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.get(galaxy_config.root+"api/datatypes?extension_only=False",function(j){for(key in j){h.list_extensions.push({id:j[key].extension,text:j[key].extension,description:j[key].description,description_url:j[key].description_url})}h.list_extensions.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0});if(!h.options.datatypes_disable_auto){h.list_extensions.unshift(h.auto)}});f.get(galaxy_config.root+"api/genomes",function(j){for(key in j){h.list_genomes.push({id:j[key][1],text:j[key][0]})}h.list_genomes.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0})});this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.View({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Paste/Fetch data":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}this.modal.show();this._updateUser();this._updateScreen()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}tool_input={};if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateUser:function(){this.current_user=Galaxy.currUser.get("id");this.current_history=null;if(this.current_user){this.current_history=Galaxy.currHistoryPanel.model.get("id")}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Paste/Fetch data")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Paste/Fetch data")}if(this.current_user&&this.options.ftp_upload_dir&&this.options.ftp_upload_site){this.modal.showButton("Choose FTP file")}else{this.modal.hideButton("Choose FTP file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -83,7 +83,7 @@
## load galaxy js-modules
$(function() {
- require(['galaxy.masthead', 'galaxy.menu', 'galaxy.modal', 'galaxy.frame', 'mvc/upload/upload-view'],
+ require(['galaxy.masthead', 'galaxy.menu', 'mvc/ui/ui-modal', 'galaxy.frame', 'mvc/upload/upload-view'],
function(mod_masthead, mod_menu, mod_modal, mod_frame, GalaxyUpload)
{
## check if masthead is available
@@ -95,7 +95,7 @@
## load global galaxy objects
Galaxy.masthead = new mod_masthead.GalaxyMasthead(masthead_config);
- Galaxy.modal = new mod_modal.GalaxyModal();
+ Galaxy.modal = new mod_modal.View();
Galaxy.frame = new mod_frame.GalaxyFrame();
## construct default menu options
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Ui/Charts: Enable job submission, revise data access, generalize framework, update elements
by commits-noreply@bitbucket.org 05 Mar '14
by commits-noreply@bitbucket.org 05 Mar '14
05 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4ec6ff7c4165/
Changeset: 4ec6ff7c4165
User: guerler
Date: 2014-03-06 06:48:58
Summary: Ui/Charts: Enable job submission, revise data access, generalize framework, update elements
Affected #: 25 files
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,10 +1,10 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils',
- 'plugin/views/charts', 'plugin/views/viewport', 'plugin/views/chart',
- 'plugin/models/config', 'plugin/models/datasets', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
- function( Portlet, Ui, Utils,
- ChartsView, ViewportView, ChartView,
- Config, Datasets, Chart, Charts, Types
+define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
+ 'plugin/views/charts', 'plugin/views/chart',
+ 'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
+ function( Portlet, Ui, Utils, Jobs, Datasets,
+ ChartsView, ChartView,
+ Config, Chart, Charts, Types
) {
// widget
@@ -17,11 +17,14 @@
this.options = options;
// link galaxy
- this.modal = parent.Galaxy.modal;
+ this.modal = Galaxy.modal;
// create configuration model
this.config = new Config();
+ // job/data /processor
+ this.jobs = new Jobs(this);
+
// create chart models
this.types = new Types();
this.chart = new Chart();
@@ -33,11 +36,7 @@
// create views
this.charts_view = new ChartsView(this);
this.chart_view = new ChartView(this);
- this.viewport_view = new ViewportView(this);
- // append view port to charts viewer
- this.charts_view.append(this.viewport_view.$el);
-
// create portlet
if (!this.options.config.widget) {
this.portlet = new Portlet.View({icon : 'fa-bar-chart-o'});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/bardiagram.js
--- a/config/plugins/visualizations/charts/static/charts/bardiagram.js
+++ b/config/plugins/visualizations/charts/static/charts/bardiagram.js
@@ -11,21 +11,25 @@
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarChart();
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarChart();
- self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/histogram.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/histogram.js
@@ -0,0 +1,49 @@
+// dependencies
+define([], function() {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // plot
+ plot: function(chart, request_dictionary) {
+
+ // update request dataset id
+ request_dictionary.id = chart.get('dataset_id_job');
+
+ // configure request
+ var index = 0;
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = {
+ x: index++,
+ y: index++
+ }
+ }
+
+ // send request
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarChart();
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/horizontal.js
--- a/config/plugins/visualizations/charts/static/charts/horizontal.js
+++ b/config/plugins/visualizations/charts/static/charts/horizontal.js
@@ -8,24 +8,28 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarHorizontalChart();
-
- self.d3_chart.xAxis.tickFormat(function() { return ''; });
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ this.app.datasets.request(request_dictionary, function(data) {
+ // add graph to screen
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarHorizontalChart();
+
+ self.d3_chart.xAxis.tickFormat(function() { return ''; });
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/line.js
--- a/config/plugins/visualizations/charts/static/charts/line.js
+++ b/config/plugins/visualizations/charts/static/charts/line.js
@@ -8,30 +8,31 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.chart_3d = nv.models.lineChart();
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.lineChart();
- self.chart_3d.xAxis
- .tickFormat(d3.format(',f'));
+ self.chart_3d.xAxis
+ .tickFormat(d3.format(',f'));
- self.chart_3d.yAxis
- .tickFormat(d3.format(',.2f'));
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.chart_3d);
+ self.chart_3d.yAxis
+ .tickFormat(d3.format(',.2f'));
+
+ self.options.svg.datum(data)
+ .call(self.chart_3d);
- nv.utils.windowResize(self.chart_3d.update);
-
- return self.chart_3d;
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/linewithfocus.js
--- a/config/plugins/visualizations/charts/static/charts/linewithfocus.js
+++ b/config/plugins/visualizations/charts/static/charts/linewithfocus.js
@@ -8,28 +8,31 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.chart_3d = nv.models.lineWithFocusChart();
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.lineWithFocusChart();
- self.chart_3d.xAxis
- .tickFormat(d3.format(',f'));
+ self.chart_3d.xAxis
+ .tickFormat(d3.format(',f'));
- self.chart_3d.yAxis
- .tickFormat(d3.format(',.2f'));
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.chart_3d);
+ self.chart_3d.yAxis
+ .tickFormat(d3.format(',.2f'));
+
+ self.options.svg.datum(data)
+ .call(self.chart_3d);
- nv.utils.windowResize(self.chart_3d.update);
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/piechart.js
--- a/config/plugins/visualizations/charts/static/charts/piechart.js
+++ b/config/plugins/visualizations/charts/static/charts/piechart.js
@@ -8,43 +8,46 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // loop through data groups
- for (var key in data) {
- // get group
- var group = data[key];
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
- // format chart data
- var pie_data = [];
- for (var key in group.values) {
- var value = group.values[key];
- pie_data.push ({
- key : value.x,
- y : value.y
+ // loop through data groups
+ for (var key in request_dictionary.groups) {
+ // get group
+ var group = request_dictionary.groups[key];
+
+ // format chart data
+ var pie_data = [];
+ for (var key in group.values) {
+ var value = group.values[key];
+ pie_data.push ({
+ key : value.x,
+ y : value.y
+ });
+ }
+
+ // add graph to screen
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.pieChart()
+ .donut(true)
+ .showLegend(false);
+
+ self.options.svg.datum(pie_data)
+ .call(self.chart_3d);
+
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
});
}
-
- // add graph to screen
- var self = this;
- nv.addGraph(function() {
- self.chart_3d = nv.models.pieChart()
- .donut(true)
- .showLegend(false);
-
- d3.select(self.options.svg_id)
- .datum(pie_data)
- .call(self.chart_3d);
-
- nv.utils.windowResize(self.chart_3d.update);
-
- return self.chart_3d;
- });
- }
+ });
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/scatterplot.js
--- a/config/plugins/visualizations/charts/static/charts/scatterplot.js
+++ b/config/plugins/visualizations/charts/static/charts/scatterplot.js
@@ -8,28 +8,31 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.d3_chart = nv.models.scatterChart()
- .showDistX(true)
- .showDistY(true)
- .color(d3.scale.category10().range());
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.scatterChart()
+ .showDistX(true)
+ .showDistY(true)
+ .color(d3.scale.category10().range());
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.02f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.02f'))
- self.d3_chart.xAxis.tickFormat(d3.format('.02f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.02f'))
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/stackedarea.js
--- a/config/plugins/visualizations/charts/static/charts/stackedarea.js
+++ b/config/plugins/visualizations/charts/static/charts/stackedarea.js
@@ -8,50 +8,35 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- // check data
- var valid = true;
- var length = 0;
- for (var key in data) {
- // evalute length
- if (length == 0) {
- length = data[key].values.length;
- } else {
- if (length != data[key].values.length) {
- valid = false;
- break;
- }
- }
- }
- if (!valid) {
- return;
- }
-
- // make plot
- self.d3_chart = nv.models.stackedAreaChart()
- .x(function(d) {
- return d.x
- })
- .y(function(d) {
- return d.y
- })
- .clipEdge(true);
-
- self.d3_chart.xAxis.tickFormat(function() { return ''; });
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ // make plot
+ self.d3_chart = nv.models.stackedAreaChart()
+ .x(function(d) {
+ return d.x
+ })
+ .y(function(d) {
+ return d.y
+ })
+ .clipEdge(true);
+
+ self.d3_chart.xAxis.tickFormat(function() { return ''; });
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/datasets.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/datasets.js
@@ -0,0 +1,137 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// widget
+return Backbone.Collection.extend(
+{
+ // initialize
+ initialize: function(app, options)
+ {
+ // link app
+ this.app = app;
+
+ // configure options
+ this.options = Utils.merge(options, this.optionsDefault);
+ },
+
+ // wait
+ request: function(options, success, error) {
+ // link this
+ var self = this;
+
+ // wait for dataset
+ Utils.request('GET', config.root + 'api/datasets/' + options.id, {}, function(dataset) {
+ switch (dataset.state) {
+ case 'error':
+ if (error) {
+ error(dataset);
+ }
+ break;
+ default:
+ if (options.groups) {
+ self._fetch(options, success);
+ } else {
+ success(dataset);
+ }
+ }
+ });
+ },
+
+ // fetch data columns into dataset object
+ _fetch: function(options, callback) {
+ // set offset
+ var offset = options.start ? options.start : 0;
+
+ // set limit
+ var limit = Math.abs(options.end - options.start);
+ var query_limit = this.app.config.get('query_limit');
+ if (!limit || limit > query_limit) {
+ limit = query_limit;
+ }
+
+ // get column indices
+ var index_string = '';
+ var index_map = {};
+ var index_count = 0;
+ for (var i in options.groups) {
+ var group = options.groups[i];
+ for (var key in group.columns) {
+ var column = group.columns[key];
+
+ // add to index string
+ index_string += column + ',';
+
+ // add to dictionary
+ index_map[column] = index_count;
+
+ // increase counter
+ index_count++;
+ }
+ }
+ if (index_count == 0) {
+ callback({});
+ return;
+ }
+ index_string = index_string.substring(0, index_string.length - 1);
+
+ // initialize result dictionary
+ var result = options.groups.slice(0);
+ for (var i in result) {
+ result[i].values = [];
+ }
+
+ // make request
+ var self = this;
+ Utils.request('GET', config.root + 'api/datasets/' + options.id, {
+ data_type : 'raw_data',
+ provider : 'dataset-column',
+ limit : limit,
+ offset : offset,
+ indeces : index_string
+ }, function(response) {
+
+ // loop through rows
+ for (var i in response.data) {
+ // get row
+ var row = response.data[i];
+
+ // collect all data into the defined groups
+ for (var j in options.groups) {
+ // get group
+ var group = options.groups[j];
+
+ // initialize value
+ var value = {
+ x : parseInt(i) + offset
+ };
+
+ // fill value
+ for (var key in group.columns) {
+ // get column
+ var column = group.columns[key];
+
+ // identify column
+ var index = index_map[column];
+
+ // read value from row
+ var v = row[index];
+ if(isNaN(v)) {
+ v = 0;
+ }
+
+ // add value to dictionary
+ value[key] = v;
+ }
+
+ // add to result
+ result[j].values.push(value);
+ }
+ }
+
+ // callback
+ callback(result);
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/jobs.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -0,0 +1,98 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// widget
+return Backbone.Model.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ // link app
+ this.app = app;
+
+ // link options
+ this.options = Utils.merge(options, this.optionsDefault);
+ },
+
+ // create job
+ submit: function(chart, request_string, callback) {
+ // link this
+ var self = this;
+
+ // backup chart details
+ var chart_id = chart.id;
+ var chart_type = chart.get('type');
+
+ // get chart settings
+ var chart_settings = this.app.types.get(chart_type);
+
+ // configure tool
+ data = {
+ 'tool_id' : 'rkit',
+ 'history_id' : chart.history_id,
+ 'inputs' : {
+ 'input' : chart.dataset_hid,
+ 'module' : chart_type,
+ 'options' : request_string
+ }
+ }
+
+ // set chart state
+ chart.state('submit', 'Sending job request...');
+
+ // post job
+ Utils.request('POST', config.root + 'api/tools', data,
+ // success handler
+ function(response) {
+ if (!response.outputs || response.outputs.length == 0) {
+ chart.state('failed', 'Job submission failed. No response.');
+ self.app.log('handle::load()', 'Job submission failed.');
+ } else {
+ // update galaxy history
+ Galaxy.currHistoryPanel.refreshHdas();
+
+ // get dataset
+ var job = response.outputs[0];
+
+ // check dataset
+ chart.state('queued', 'Job has been queued...');
+
+ // backup resulting dataset id
+ chart.set('dataset_id_job', job.id);
+
+ // wait for job completion
+ self._loop(job.id, function(job) {
+ switch (job.state) {
+ case 'ok':
+ chart.state('ok', 'Job completed successfully...');
+ callback(job);
+ return true;
+ case 'error':
+ chart.state('failed', 'Job has failed. Please check the history for details.');
+ return true;
+ case 'running':
+ chart.state('running', 'Job is running...');
+ return false;
+ }
+ });
+ }
+ },
+ // error handler
+ function(response) {
+ chart.state('failed', 'Job submission failed.');
+ self.app.log('handle::load()', 'Job submission failed.');
+ }
+ );
+ },
+
+ // request job details
+ _loop: function(id, callback) {
+ var self = this;
+ Utils.request('GET', config.root + 'api/jobs/' + id, {}, function(job) {
+ if (!callback(job)) {
+ setTimeout(function() { self._loop(id, callback); }, self.app.config.get('query_timeout'));
+ }
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/table.js
--- a/config/plugins/visualizations/charts/static/library/table.js
+++ b/config/plugins/visualizations/charts/static/library/table.js
@@ -82,9 +82,12 @@
// remove
remove: function(id) {
- this.$tbody.find('#' + id).remove();
- this.row_count--;
- this._refresh();
+ var item = this.$tbody.find('#' + id);
+ if (item.length > 0) {
+ item.remove();
+ this.row_count--;
+ this._refresh();
+ }
},
// remove
@@ -129,6 +132,9 @@
// commit
_commit: function(id, prepend) {
+ // remove previous item with same id
+ this.remove(id);
+
// add
this.row.attr('id', id);
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/ui.select.js
--- a/config/plugins/visualizations/charts/static/library/ui.select.js
+++ b/config/plugins/visualizations/charts/static/library/ui.select.js
@@ -8,9 +8,14 @@
optionsDefault: {
id : '',
cls : '',
- empty : 'No data available'
+ empty : 'No data available',
+ visible : true,
+ wait : false
},
+ // value
+ selected : null,
+
// initialize
initialize : function(options) {
// configure options
@@ -19,70 +24,102 @@
// create new element
this.setElement(this._template(this.options));
+ // link elements
+ this.$select = this.$el.find('#select');
+ this.$wait = this.$el.find('#wait');
+
// initial value
- if (this.options.value) {
- this.$el.val(this.options.value);
- }
+ this.selected = this.options.value;
// add change event
var self = this;
if (this.options.onchange) {
- this.$el.on('change', function() { self.options.onchange(self.value()); });
+ this.$select.on('change', function() {
+ self.value(self.$select.val());
+ });
}
// refresh
this._refresh();
+
+ // show/hide
+ if (!this.options.visible) {
+ this.hide();
+ }
+
+ // wait
+ if (this.options.wait) {
+ this.wait();
+ }
},
// value
value : function (new_value) {
+
// get current id/value
- var before = this.$el.val();
+ var before = this.selected;
// check if new_value is defined
if (new_value !== undefined) {
- this.$el.val(new_value);
+ this.selected = new_value;
+ this.$select.val(new_value);
}
// get current id/value
- var after = this.$el.val();
- if(after === undefined) {
- return null;
- } else {
+ var after = this.selected;
+ if(after) {
// fire onchange
- if ((after != before && this.options.onchange) || this.$el.find('option').length == 1) {
+ if ((after != before && this.options.onchange)) {
this.options.onchange(after);
}
-
- // return current value
- return after;
}
+
+ // return
+ return after;
},
// label
text : function () {
- return this.$el.find('option:selected').text();
+ return this.$select.find('option:selected').text();
+ },
+
+ // show
+ show: function() {
+ this.$wait.hide();
+ this.$select.show();
+ this.$el.show();
+ },
+
+ // hide
+ hide: function() {
+ this.$el.hide();
+ },
+
+ // wait
+ wait: function() {
+ this.$select.hide();
+ this.$wait.css('display','inline-block');
},
// disabled
disabled: function() {
- return this.$el.is(':disabled');
+ return this.$select.is(':disabled');
},
// enable
enable: function() {
- this.$el.prop('disabled', false);
+ this.$select.prop('disabled', false);
},
// disable
disable: function() {
- this.$el.prop('disabled', true);
+ this.$select.prop('disabled', true);
},
// add
add: function(options) {
// add options
- $(this.el).append(this._templateOption(options));
+ this.$select.append(this._templateOption(options));
// refresh
this._refresh();
@@ -91,8 +128,8 @@
// remove
del: function(value) {
// remove option
- $(this.el).find('option[value=' + value + ']').remove();
- $(this.el).trigger('change');
+ this.$select.find('option[value=' + value + ']').remove();
+ this.$select.trigger('change');
// refresh
this._refresh();
@@ -100,20 +137,18 @@
// render
update: function(options) {
- // selected
- var selected = this.$el.val();
-
// remove all options
- $(this.el).find('option').remove();
+ this.$select.find('option').remove();
// add new options
- for (var key in options.data) {
- $(this.el).append(this._templateOption(options.data[key]));
+ for (var key in options) {
+ this.$select.append(this._templateOption(options[key]));
}
- // add selected value
- if (this._exists(selected))
- $(this.el).val(selected);
+ // select first option if nothing else is selected
+ if (!this.selected && options.length > 0) {
+ this.value(options[0].value);
+ }
// refresh
this._refresh();
@@ -122,23 +157,31 @@
// refresh
_refresh: function() {
// remove placeholder
- $(this.el).find('option[value=null]').remove();
+ this.$select.find('option[value=null]').remove();
// count remaining entries
- var remaining = $(this.el).find('option').length;
+ var remaining = this.$select.find('option').length;
if (remaining == 0) {
// append placeholder
- $(this.el).append(this._templateOption({value : 'null', label : this.options.empty}));
+ this.$select.append(this._templateOption({value : 'null', label : this.options.empty}));
this.disable();
} else {
+ // enable select field
this.enable();
+
+ // update selected value
+ if (this.selected) {
+ //if (this._exists(selected)) {
+ this.$select.val(this.selected);
+ //}
+ }
}
},
// exists
_exists: function(value) {
// check if selected value exists
- return 0 != $(this.el).find('option[value=' + value + ']').length;
+ return 0 != this.$select.find('option[value=' + value + ']').length;
},
// option
@@ -148,21 +191,24 @@
// element
_template: function(options) {
- var tmpl = '<select id="' + options.id + '" class="select ' + options.cls + ' ' + options.id + '">';
+ var tmpl = '<div id="' + options.id + '">' +
+ '<i id="wait" class="fa fa-spinner fa-spin" style="font-size: 1.2em; display: none;"/>' +
+ '<select id="select" class="select ' + options.cls + ' ' + options.id + '">';
for (key in options.data) {
// options
var item = options.data[key];
// identify selected value
var tag = '';
- if (item.value == options.selected || item.value == '') {
+ if (item.value == options.value || item.value == '') {
tag = 'selected';
}
// add template string
- tmpl += '<option value="' + item.value + '" ' + tag + '>' + item.label + '</option>';
+ tmpl += '<option value="' + item.value + '" ' + tag + '>' + item.label + '</option>';
}
- tmpl += '</select>';
+ tmpl += '</select>' +
+ '</div>';
return tmpl;
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/utils.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/utils.js
@@ -0,0 +1,152 @@
+/**
+ * Galaxy utilities comprises small functions, which at this point
+ * do not require their own classes/files
+*/
+
+// dependencies
+define(["libs/underscore"], function(_) {
+
+// generic function to recieve json from url
+function get (url, success, error) {
+ request('GET', url, {}, success, error);
+};
+
+// generic function to send json to url
+function request (method, url, data, success, error) {
+
+ // encode data into url
+ if (method == 'GET' || method == 'DELETE') {
+ if (url.indexOf('?') == -1) {
+ url += '?';
+ } else {
+ url += '&';
+ }
+ url += $.param(data)
+ }
+
+ // prepare request
+ var xhr = new XMLHttpRequest();
+ xhr.open(method, url, true);
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.setRequestHeader('Cache-Control', 'no-cache');
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.onloadend = function() {
+ var status = xhr.status;
+ if (status == 200) {
+ try {
+ response = jQuery.parseJSON(xhr.responseText);
+ } catch (e) {
+ response = xhr.responseText;
+ }
+ success && success(response);
+ } else {
+ error && error(status);
+ }
+ };
+
+ // make request
+ if (method == 'GET' || method == 'DELETE') {
+ xhr.send();
+ } else {
+ xhr.send(JSON.stringify(data));
+ }
+};
+
+// get css value
+function cssGetAttribute (classname, name) {
+ // place dummy element
+ var el = $('<div class="' + classname + '"></div>');
+
+ // required append
+ el.appendTo(':eq(0)');
+
+ // get value
+ var value = el.css(name);
+
+ // remove element
+ el.remove();
+
+ // return css value
+ return value;
+};
+
+// load css
+function cssLoadFile (url) {
+ // check if css is already available
+ if (!$('link[href^="' + url + '"]').length)
+ $('<link href="' + galaxy_config.root + url + '" rel="stylesheet">').appendTo('head');
+};
+
+// merge
+function merge (options, optionsDefault) {
+ if (options)
+ return _.defaults(options, optionsDefault);
+ else
+ return optionsDefault;
+};
+
+// to string
+function bytesToString (size, normal_font) {
+ // identify unit
+ var unit = "";
+ if (size >= 100000000000) { size = size / 100000000000; unit = 'TB'; } else
+ if (size >= 100000000) { size = size / 100000000; unit = 'GB'; } else
+ if (size >= 100000) { size = size / 100000; unit = 'MB'; } else
+ if (size >= 100) { size = size / 100; unit = 'KB'; } else
+ if (size > 0) { size = size * 10; unit = 'b'; } else
+ return '<strong>-</strong>';
+
+ // return formatted string
+ var rounded = (Math.round(size) / 10);
+ if (normal_font) {
+ return rounded + ' ' + unit;
+ } else {
+ return '<strong>' + rounded + '</strong> ' + unit;
+ }
+};
+
+// unique ide
+function uuid(){
+ return (new Date().getTime()).toString(36);
+};
+
+// wrap
+function wrap($el) {
+ var wrapper = $('<p></p>');
+ wrapper.append($el);
+ return wrapper;
+};
+
+// time
+function time() {
+ // get date object
+ var d = new Date();
+
+ // format items
+ var hours = (d.getHours() < 10 ? "0" : "") + d.getHours();
+ var minutes = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes()
+
+ // format final stamp
+ var datetime = d.getDate() + "/"
+ + (d.getMonth() + 1) + "/"
+ + d.getFullYear() + ", "
+ + hours + ":"
+ + minutes;
+ return datetime;
+};
+
+// return
+return {
+ cssLoadFile : cssLoadFile,
+ cssGetAttribute : cssGetAttribute,
+ get : get,
+ merge : merge,
+ bytesToString: bytesToString,
+ uuid: uuid,
+ time: time,
+ wrap: wrap,
+ request: request
+};
+
+});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -7,10 +7,12 @@
{
// defaults
defaults : {
- id : null,
- title : '',
- type : '',
- date : null
+ id : null,
+ title : '',
+ type : '',
+ date : null,
+ state : '',
+ state_info : ''
},
// initialize
@@ -37,6 +39,11 @@
current.groups.add(group.clone());
});
current.trigger('change', current);
+ },
+
+ state: function(value, info) {
+ this.set('state_info', info);
+ this.set('state', value);
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/config.js
--- a/config/plugins/visualizations/charts/static/models/config.js
+++ b/config/plugins/visualizations/charts/static/models/config.js
@@ -1,15 +1,13 @@
// dependencies
define([], function() {
-
// model
return Backbone.Model.extend(
{
// options
defaults : {
- query_limit : 20,
- query_pace : 1000,
- query_max : 5,
+ query_limit : 1000,
+ query_timeout : 500,
title : 'Create a new chart'
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/datasets.js
--- a/config/plugins/visualizations/charts/static/models/datasets.js
+++ /dev/null
@@ -1,125 +0,0 @@
-// dependencies
-define(['utils/utils'], function(Utils) {
-
-// widget
-return Backbone.Model.extend(
-{
- // options
- optionsDefault : {
- limit : 500,
- pace : 1000,
- max : 2
- },
-
- // list
- list: {},
-
- // initialize
- initialize: function(app, options)
- {
- // link app
- this.app = app;
-
- // configure options
- this.options = Utils.merge(options, this.optionsDefault);
- },
-
- // get
- get: function(options, callback) {
- // check if dataset already exists
- var dataset = this.list[options.id];
- if (dataset) {
- if (dataset.values) {
- if (dataset.values[options.column]) {
- if (callback) {
- callback(dataset);
- }
- return dataset;
- }
- }
- } else {
- this.list[options.id] = dataset = this.app.options.dataset;
- }
-
- // initiate fetch cycle
- if (options.column !== undefined) {
- this._fetch(options, callback);
- } else {
- if (callback) {
- callback(dataset);
- }
- return dataset;
- }
-
- // return
- return dataset;
- },
-
- // size
- length: function() {
- return this.list.length;
- },
-
- // request data
- _fetch : function(options, callback) {
- // get dataset
- var dataset = this.list[options.id];
-
- // initialize values for datasets
- if (!dataset.values) {
- dataset.values = {};
- }
- if (!dataset.values[options.column]) {
- dataset.values[options.column] = [];
- }
-
- // initialize page number
- if (options.page === undefined) {
- options.page = 0;
- } else {
- options.page++;
- }
-
- // check max page
- if (options.page > this.options.max) {
- return;
- }
-
- // config limits
- var limit = this.options.limit;
- var offset = this.options.limit * options.page;
-
- // make request
- var self = this;
- Utils.request('GET', config.root + 'api/datasets/' + options.id, {
- data_type : 'raw_data',
- provider : 'dataset-column',
- limit : limit,
- offset : offset,
- indeces : options.column
- }, function(response) {
- // verify if all data has been fetched
- if (response.data.length > 0) {
- // add values to dataset
- for (var key in response.data){
- var value = response.data[key][0];
- if (value !== undefined) {
- dataset.values[options.column].push(value);
- } else {
- return dataset;
- }
- }
-
- // update charts
- if (callback) {
- callback(dataset);
- }
-
- // next call
- setTimeout(function() { self._fetch(options, callback); }, self.options.pace);
- }
- });
- }
-});
-
-});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/group.js
--- a/config/plugins/visualizations/charts/static/models/group.js
+++ b/config/plugins/visualizations/charts/static/models/group.js
@@ -6,8 +6,8 @@
{
// options
defaults : {
- label : 'Data label',
- date : ''
+ key : 'Data label',
+ date : ''
},
// reset
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/types.js
--- a/config/plugins/visualizations/charts/static/models/types.js
+++ b/config/plugins/visualizations/charts/static/models/types.js
@@ -7,48 +7,57 @@
// types
defaults: {
'bardiagram' : {
- title : 'Bar diagram',
- data : {
+ title : 'Bar diagram',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
+ 'histogram' : {
+ title : 'Histogram',
+ mode : 'execute',
+ columns : {
+ y : {
+ title : 'Derive frequencies'
+ }
+ }
+ },
'horizontal' : {
- title : 'Bar diagram (horizontal)',
- data : {
+ title : 'Bar diagram (horizontal)',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'line' : {
- title : 'Line chart',
- data : {
+ title : 'Line chart',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'linewithfocus' : {
- title : 'Line chart (with focus)',
- data : {
+ title : 'Line chart (with focus)',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'piechart' : {
- title : 'Pie chart',
- data : {
+ title : 'Pie chart',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'scatterplot' : {
- title : 'Scatter plot',
- data : {
+ title : 'Scatter plot',
+ columns : {
x : {
title : 'Values for x-axis'
},
@@ -58,8 +67,8 @@
}
},
'stackedarea' : {
- title : 'Stacked area',
- data : {
+ title : 'Stacked area',
+ columns : {
y : {
title : 'Values for y-axis'
}
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -97,7 +97,7 @@
// save chart
self._saveChart();
- // show viewport
+ // show charts
self.hide();
self.app.charts_view.$el.show();
}
@@ -125,7 +125,6 @@
self.app.config.set('title', self.title.value());
}
});
- this.dataset = new Ui.Input({value : app.options.dataset.id, disabled: true, visible: false});
// append element
var $settings = $('<div/>');
@@ -183,8 +182,8 @@
this.app.chart.groups.on('reset', function(group) {
self._removeAllGroups();
});
- this.app.chart.groups.on('change:label', function(group) {
- self._refreshLabels();
+ this.app.chart.groups.on('change:key', function(group) {
+ self._refreshGroupKey();
});
// reset
@@ -198,11 +197,11 @@
},
// update
- _refreshLabels: function() {
+ _refreshGroupKey: function() {
var self = this;
var counter = 0;
this.chart.groups.each(function(group) {
- var title = group.get('label', '');
+ var title = group.get('key', '');
if (title == '') {
title = 'Chart data';
}
@@ -213,8 +212,7 @@
// new group
_addGroupModel: function() {
var group = new Group({
- id : Utils.uuid(),
- dataset_id : this.chart.get('dataset_id')
+ id : Utils.uuid()
});
this.chart.groups.add(group);
return group;
@@ -241,7 +239,7 @@
});
// update titles
- this._refreshLabels()
+ this._refreshGroupKey();
},
// remove group
@@ -249,7 +247,7 @@
this.tabs.del(group.id);
// update titles
- this._refreshLabels()
+ this._refreshGroupKey();
},
// remove group
@@ -261,8 +259,10 @@
_resetChart: function() {
// reset chart details
this.chart.set('id', Utils.uuid());
+ this.chart.set('type', 'bardiagram');
this.chart.set('dataset_id', this.app.options.dataset.id);
- this.chart.set('type', 'bardiagram');
+ this.chart.set('dataset_hid', this.app.options.dataset.hid);
+ this.chart.set('history_id', this.app.options.dataset.history_id);
this.chart.set('title', 'New Chart');
},
@@ -272,7 +272,6 @@
this.chart.set({
type : this.table.value(),
title : this.title.value(),
- dataset_id : this.dataset.value(),
date : Utils.time()
});
@@ -280,11 +279,14 @@
var current = this.app.charts.get(this.chart.id);
if (!current) {
current = this.chart.clone();
+ current.copy(this.chart);
this.app.charts.add(current);
+ } else {
+ current.copy(this.chart);
}
-
- // update chart model
- current.copy(this.chart);
+
+ // trigger redraw
+ current.set('state', 'redraw');
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/views/charts.js
--- a/config/plugins/visualizations/charts/static/views/charts.js
+++ b/config/plugins/visualizations/charts/static/views/charts.js
@@ -1,5 +1,5 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/group'], function(Portlet, Table, Ui, Utils, Group) {
+define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/group', 'plugin/views/viewport',], function(Portlet, Table, Ui, Utils, Group, ViewportView) {
// widget
return Backbone.View.extend(
@@ -10,6 +10,9 @@
// link app
this.app = app;
+ // create viewport
+ this.viewport_view = new ViewportView(app);
+
// table
this.table = new Table({
content : 'Add charts to this table.',
@@ -32,7 +35,7 @@
self.app.config.set('title', chart.get('title'));
// show viewport
- self.app.viewport_view.show(chart_id);
+ self.viewport_view.showChart(chart_id);
}
});
@@ -89,11 +92,15 @@
});
this.portlet.append(this.table.$el);
- // append to main
+ // append portlet with table
if (!this.app.options.config.widget) {
this.$el.append(this.portlet.$el);
}
+ // append view port
+ this.$el.append(Utils.wrap(''));
+ this.$el.append(this.viewport_view.$el);
+
// events
var self = this;
this.app.charts.on('add', function(chart) {
@@ -106,8 +113,7 @@
});
this.app.charts.on('change', function(chart) {
// replace
- self._removeChart(chart);
- self._addChart(chart);
+ self._changeChart(chart);
});
},
@@ -117,12 +123,6 @@
this.$el.hide();
},
- // append
- append : function($el) {
- this.$el.append(Utils.wrap(''));
- this.$el.append($el);
- },
-
// add
_addChart: function(chart) {
// add title to table
@@ -146,11 +146,21 @@
// check if table is empty
if (this.table.size() == 0) {
this.hide();
+ this.app.chart.reset();
this.app.chart_view.$el.show();
} else {
// select available chart
this.table.value(this.app.charts.last().id);
}
+ },
+
+ // change
+ _changeChart: function(chart) {
+ // add chart
+ this._addChart(chart);
+
+ // select available chart
+ this.table.value(chart.id);
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/views/group.js
--- a/config/plugins/visualizations/charts/static/views/group.js
+++ b/config/plugins/visualizations/charts/static/views/group.js
@@ -1,6 +1,6 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils'],
- function(Portlet, Table, Ui, Utils) {
+define(['plugin/library/table', 'plugin/library/ui', 'utils/utils'],
+ function(Table, Ui, Utils) {
// chart config
return Backbone.View.extend(
@@ -23,18 +23,18 @@
this.group = options.group;
// ui elements
- this.label = new Ui.Input({
+ this.group_key = new Ui.Input({
placeholder: 'Data label',
onchange: function() {
- self.group.set('label', self.label.value());
+ self.group.set('key', self.group_key.value());
}
});
this.table = new Table({content: 'No data column.'});
- // add table to portlet
+ // create element
var $view = $('<div/>');
$view.append(Utils.wrap((new Ui.Label({title: 'Provide a label:'})).$el));
- $view.append(Utils.wrap(this.label.$el));
+ $view.append(Utils.wrap(this.group_key.$el));
$view.append(Utils.wrap((new Ui.Label({title: 'Select columns:'})).$el));
$view.append(Utils.wrap(this.table.$el));
@@ -44,101 +44,92 @@
// change
var self = this;
this.chart.on('change:dataset_id', function() {
- self._refreshDataset();
+ self._refreshTable();
});
this.chart.on('change:type', function() {
- self._refreshType();
+ self._refreshTable();
});
- this.group.on('change:label', function() {
- self._refreshLabel();
+ this.group.on('change:key', function() {
+ self._refreshGroupKey();
});
this.group.on('change', function() {
self._refreshGroup();
});
// refresh
- this._refresh();
- },
-
- // render
- _refresh: function() {
- this._refreshDataset();
- this._refreshType();
- this._refreshLabel();
+ this._refreshTable();
+ this._refreshGroupKey();
this._refreshGroup();
},
// update dataset
- _refreshDataset: function() {
+ _refreshTable: function() {
// identify datasets
var dataset_id = this.chart.get('dataset_id');
+ var chart_type = this.chart.get('type');
// check if dataset is available
- if (!dataset_id) {
+ if (!dataset_id || !chart_type) {
return;
}
+ // link this
+ var self = this;
+
+ // configure chart type
+ var chart_settings = this.app.types.get(chart_type);
+
+ // reset table
+ this.table.removeAll();
+
+ // load list
+ var list = {};
+ for (var id in chart_settings.columns) {
+ // initialize
+ var value = this.group.get(id);
+ if (!value) {
+ this.group.set(id, 0);
+ }
+
+ // create select field
+ var data_def = chart_settings.columns[id];
+ var select = new Ui.Select({
+ id : 'select_' + id,
+ gid : id,
+ onchange : function(value) {
+ self.group.set(this.gid, value);
+ },
+ value : value,
+ wait : true
+ });
+
+ // add row to table
+ this.table.add(data_def.title);
+ this.table.add(select.$el);
+ this.table.append(id);
+
+ // add select field to list
+ list[id] = select;
+ }
+
// get dataset
- var dataset = this.app.datasets.get({id : dataset_id});
-
- // check
- if (!dataset) {
- this.app.log('Group::_refreshDataset()', 'Failed to retrieve dataset.');
- return;
- }
-
- // configure columns
- this.columns = [];
- var meta = dataset.metadata_column_types;
- for (var key in meta){
- this.columns.push({
- 'label' : key + ' [' + meta[key] + ']',
- 'value' : key
- });
- }
-
- // update select fields
- for (var key in this.list) {
- this.list[key].update(this.columns);
- }
- },
-
- // update
- _refreshType: function() {
- // configure chart type
- var self = this;
- var chart_type = this.chart.get('type');
- if (chart_type) {
- var chart_settings = this.app.types.get(chart_type);
-
- // table
- this.table.removeAll();
- this.list = {};
- for (var id in chart_settings.data) {
- // create select field
- var data_def = chart_settings.data[id];
- var select = new Ui.Select({
- id : 'select_' + id,
- gid : id,
- data : this.columns,
- onchange : function(value) {
- self.group.set(this.gid, value);
- },
- value : this.group.get(id)
+ this.app.datasets.request({id : dataset_id}, function(dataset) {
+ // configure columns
+ self.columns = [];
+ var meta = dataset.metadata_column_types;
+ for (var key in meta){
+ self.columns.push({
+ 'label' : key + ' [' + meta[key] + ']',
+ 'value' : key
});
-
- // set model value
- this.group.set(id, select.value());
-
- // add row to table
- this.table.add(data_def.title);
- this.table.add(select.$el);
- this.table.append(id);
-
- // add select field to list
- this.list[id] = select;
}
- }
+
+ // update select fields
+ for (var key in list) {
+ list[key].update(self.columns);
+ list[key].show();
+ }
+ });
},
// update
@@ -146,13 +137,13 @@
this.group.set('date', Utils.time());
},
- // update label
- _refreshLabel: function() {
- var label_text = this.group.get('label');
- if (label_text === undefined) {
- label_text = '';
+ // update group key
+ _refreshGroupKey: function() {
+ var key_text = this.group.get('key');
+ if (key_text === undefined) {
+ key_text = '';
}
- this.label.value(label_text);
+ this.group_key.value(key_text);
}
});
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0