diff --git a/.gitignore b/.gitignore index 482a69a5cc7..371240a7939 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,8 @@ object_store_conf.xml job_metrics_conf.xml workflow_schedulers_conf.xml config/* +config/plugins/interactive_environments/**/*.ini +!config/plugins static/welcome.html.* static/welcome.html diff --git a/client/galaxy/scripts/layout/menu.js b/client/galaxy/scripts/layout/menu.js index 41db9ab0b4e..f82b571dddd 100644 --- a/client/galaxy/scripts/layout/menu.js +++ b/client/galaxy/scripts/layout/menu.js @@ -93,7 +93,12 @@ var Collection = Backbone.Collection.extend({ title : 'Saved Visualizations', url : 'visualization/list', target : '_frame' - }] + },{ + title : 'Interactive Environments', + url : 'visualization/gie_list', + target : 'galaxy_main' + } + ] }); // diff --git a/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample b/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample new file mode 100644 index 00000000000..89797badfa6 --- /dev/null +++ b/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample @@ -0,0 +1,14 @@ +# This file lists acceptable images to allow runing. +# +# This allows you, the admin, to create multiple flavours +# for your users to run. E.g. maybe you need a geosciences flavour, +# you can create the image based on our default image and add the +# appropriate `apt-get/pip install` statements. +--- +- + image: bgruening/docker-jupyter-notebook:16.01 + description: | + The Jupyter notebook is the next iteration of IPython, allowing + analysis in many different languages. This image features the Python, + R, Julia, Haskell, Bash kernels and many scientific analysis stacks for + each. diff --git a/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample b/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample index c89fe09a8bc..ec7cedbeddf 100644 --- a/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample +++ b/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample @@ -15,8 +15,7 @@ # usual group/sudo changes. #command = docker {docker_args} -# The docker image name that should be started. -image = bgruening/docker-jupyter-notebook:16.01 +# The image argument was moved to "allowed_images.yml.sample" # Additional arguments that are passed to the `docker run` command. command_inject = --sig-proxy=true -e DEBUG=false -e DEFAULT_CONTAINER_RUNTIME=120 diff --git a/config/plugins/interactive_environments/jupyter/templates/jupyter.mako b/config/plugins/interactive_environments/jupyter/templates/jupyter.mako index d76e2998e95..69bf37fc454 100644 --- a/config/plugins/interactive_environments/jupyter/templates/jupyter.mako +++ b/config/plugins/interactive_environments/jupyter/templates/jupyter.mako @@ -24,10 +24,14 @@ else: DATASET_HID = None # Add all environment variables collected from Galaxy's IE infrastructure -ie_request.launch(env_override={ - 'notebook_password': PASSWORD, - 'dataset_hid': DATASET_HID, -}) +ie_request.launch( + image=trans.request.params.get('image_tag', None), + additional_ids=trans.request.params.get('additional_dataset_ids', None), + env_override={ + 'notebook_password': PASSWORD, + 'dataset_hid': DATASET_HID, + } +) ## General IE specific # Access URLs for the notebook from within galaxy. diff --git a/config/plugins/interactive_environments/rstudio/config/allowed_images.yml.sample b/config/plugins/interactive_environments/rstudio/config/allowed_images.yml.sample new file mode 100644 index 00000000000..bcbcb82d27c --- /dev/null +++ b/config/plugins/interactive_environments/rstudio/config/allowed_images.yml.sample @@ -0,0 +1,14 @@ +# This file lists acceptable images to allow runing. +# +# This allows you, the admin, to create multiple flavours +# for your users to run. E.g. maybe you need a geosciences flavour, +# you can create the image based on our default image and add the +# appropriate `apt-get/pip install` statements. +--- +- + image: erasche/docker-rstudio-notebook:15.10 + description: | + If you've ever done R analysis, you probably used RStudio. This + familiar R analysis software suite will let you explore your datasets + in depth. Comes with ggplot2, RODBC, maps, shinyapps, knitr, LaTeX, + bioconductor, cummeRbund, and many more pre-installed packages. diff --git a/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample b/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample index 17f16c8a7ba..ac15696936d 100644 --- a/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample +++ b/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample @@ -17,8 +17,7 @@ password_auth = True # usual group/sudo changes. #command = docker {docker_args} -# The docker image name that should be started. -image = erasche/docker-rstudio-notebook:15.10 +# The image argument was moved to "allowed_images.yml.sample" # Additional arguments that are passed to the `docker run` command. #command_inject = --sig-proxy=true -e DEBUG=false diff --git a/config/plugins/interactive_environments/rstudio/templates/rstudio.mako b/config/plugins/interactive_environments/rstudio/templates/rstudio.mako index 9d35421ba5a..26156de3a2c 100644 --- a/config/plugins/interactive_environments/rstudio/templates/rstudio.mako +++ b/config/plugins/interactive_environments/rstudio/templates/rstudio.mako @@ -16,10 +16,14 @@ USERNAME = "galaxy" if hda.datatype.__class__.__name__ == "RData": shutil.copy( hda.file_name, os.path.join(temp_dir, '.RData') ) -ie_request.launch(env_override={ - 'notebook_username': USERNAME, - 'notebook_password': PASSWORD, -}) +ie_request.launch( + image=trans.request.params.get('image_tag', None), + additional_ids=trans.request.params.get('additional_dataset_ids', None), + env_override={ + 'notebook_username': USERNAME, + 'notebook_password': PASSWORD, + } +) ## General IE specific # Access URLs for the notebook from within galaxy. diff --git a/lib/galaxy/config.py b/lib/galaxy/config.py index 14d584d632c..b9b5ea9daa4 100644 --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -451,6 +451,7 @@ class Configuration( object ): self.visualization_plugins_directory = kwargs.get( 'visualization_plugins_directory', 'config/plugins/visualizations' ) ie_dirs = kwargs.get( 'interactive_environment_plugins_directory', None ) + self.gie_dirs = [d.strip() for d in (ie_dirs.split(",") if ie_dirs else [])] if ie_dirs and not self.visualization_plugins_directory: self.visualization_plugins_directory = ie_dirs elif ie_dirs: diff --git a/lib/galaxy/web/base/interactive_environments.py b/lib/galaxy/web/base/interactive_environments.py index ef476bd7e29..32322b9db2b 100644 --- a/lib/galaxy/web/base/interactive_environments.py +++ b/lib/galaxy/web/base/interactive_environments.py @@ -2,13 +2,14 @@ import ConfigParser import os import json +import yaml import stat import random import tempfile from subprocess import Popen, PIPE from galaxy.util.bunch import Bunch -from galaxy import web +from galaxy import web, model from galaxy.managers import api_keys from galaxy.tools.deps.docker_util import DockerVolume @@ -39,6 +40,7 @@ class InteractiveEnvironmentRequest(object): self.attr.HOST = trans.request.host.rsplit(':', 1)[0] self.load_deploy_config() + self.load_allowed_images() self.attr.docker_hostname = self.attr.viz_config.get("docker", "docker_hostname") # Generate per-request passwords the IE plugin can use to configure @@ -69,6 +71,29 @@ class InteractiveEnvironmentRequest(object): else: self.attr.proxy_prefix = '' + def load_allowed_images(self): + if os.path.exists(os.path.join(self.attr.our_config_dir, 'allowed_images.yml')): + fn = os.path.join(self.attr.our_config_dir, 'allowed_images.yml') + elif os.path.exists(os.path.join(self.attr.our_config_dir, 'allowed_images.yml.sample')): + fn = os.path.join(self.attr.our_config_dir, 'allowed_images.yml.sample') + else: + # If we don't have an allowed images, then we fall back to image + # name specified in the .ini file + try: + self.allowed_images = [self.attr.viz_config.image] + self.default_image = self.attr.viz_config.image + return + except AttributeError: + raise Exception("[{0}] Could not find allowed_images.yml, or image tag in {0}.ini file for ".format(self.attr.viz_id)) + + with open(fn, 'r') as handle: + self.allowed_images = [x['image'] for x in yaml.load(handle)] + + if len(self.allowed_images) == 0: + raise Exception("No allowed images specified for " + self.attr.viz_id) + + self.default_image = self.allowed_images[0] + def load_deploy_config(self, default_dict={}): # For backwards compat, any new variables added to the base .ini file # will need to be recorded here. The ConfigParser doesn't provide a @@ -178,7 +203,7 @@ class InteractiveEnvironmentRequest(object): def volume(self, host_path, container_path, **kwds): return DockerVolume(host_path, container_path, **kwds) - def docker_cmd(self, env_override={}, volumes=[]): + def docker_cmd(self, image, env_override={}, volumes=[]): """ Generate and return the docker command to execute """ @@ -201,13 +226,64 @@ class InteractiveEnvironmentRequest(object): environment=env_str, import_volume_str=import_volume_str, volume_str=volume_str, - image=self.attr.viz_config.get("docker", "image") + image=image, ) return command - def launch(self, raw_cmd=None, env_override={}, volumes=[]): + def _idsToVolumes(self, ids): + if len(ids.strip()) == 0: + return [] + + # They come as a comma separated list + ids = ids.split(',') + + # Next we need to turn these into volumes + volumes = [] + for id in ids: + decoded_id = self.trans.security.decode_id(id) + dataset = self.trans.sa_session.query(model.HistoryDatasetAssociation).get(decoded_id) + # TODO: do we need to check if the user has access? + volumes.append(self.volume(dataset.get_file_name(), '/import/[{0}] {1}.{2}'.format(dataset.id, dataset.name, dataset.ext))) + return volumes + + def launch(self, image=None, additional_ids=None, raw_cmd=None, env_override={}, volumes=[]): + """Launch a docker image. + + :type image: str + :param image: Optional image name. If not provided, self.default_image + is used, which is the first image listed in the + allowed_images.yml{,.sample} file. + + :type additional_ids: str + :param additional_ids: comma separated list of encoded HDA IDs. These + are transformed into Volumes and added to that + argument + + :type raw_cmd: str + :param raw_cmd: raw docker command. Usually generated with self.docker_cmd() + + :type env_override: dict + :param env_override: dictionary of environment variables to add. + + :type volumes: list of galaxy.tools.deps.docker_util.DockerVolume + :param volumes: dictionary of docker volume mounts + + """ + if image is None: + image = self.default_image + + if image not in self.allowed_images: + # Now that we're allowing users to specify images, we need to ensure that they aren't + # requesting images we have not specifically allowed. + raise Exception("Attempting to launch disallowed image! %s not in list of allowed images [%s]" + % (image, ', '.join(self.allowed_images))) + + if additional_ids is not None: + volumes += self._idsToVolumes(additional_ids) + if raw_cmd is None: - raw_cmd = self.docker_cmd(env_override=env_override, volumes=volumes) + raw_cmd = self.docker_cmd(image, env_override=env_override, volumes=volumes) + log.info("Starting docker container for IE {0} with command [{1}]".format( self.attr.viz_id, raw_cmd diff --git a/lib/galaxy/webapps/galaxy/controllers/visualization.py b/lib/galaxy/webapps/galaxy/controllers/visualization.py index c8c3a869288..fbeef55537a 100644 --- a/lib/galaxy/webapps/galaxy/controllers/visualization.py +++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py @@ -22,6 +22,8 @@ from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesVisu from galaxy.web.framework.helpers import grids, time_ago from .library import LibraryListGrid +import os +import yaml log = logging.getLogger( __name__ ) @@ -1013,6 +1015,45 @@ class VisualizationController( BaseUIController, SharableMixin, UsesVisualizatio } return trans.fill_template_mako( "visualization/phyloviz.mako", data=data, config=config ) + @web.expose + @web.require_login( "run Galaxy Interactive Environments" ) + def gie_list( self, trans, **kwargs ): + if not hasattr( self, 'gie_image_map' ): + self.gie_image_map = {} + + for gie_dir in self.app.config.gie_dirs: + gie_list = os.listdir( gie_dir ) + for gie in gie_list: + gie_path = os.path.join(gie_dir, gie) + + if not os.path.isdir(gie_path): + continue + + if not os.path.exists(self._gie_config_dir(gie_path)): + continue + + if os.path.exists( self._gie_config_dir( gie_path, 'allowed_images.yml' ) ): + image_file = self._gie_config_dir( gie_path, 'allowed_images.yml' ) + elif os.path.exists( self._gie_config_dir( gie_path, 'allowed_images.yml.sample' ) ): + image_file = self._gie_config_dir( gie_path, 'allowed_images.yml.sample' ) + else: + continue + + with open( image_file, 'r' ) as handle: + self.gie_image_map[gie] = yaml.load( handle ) + + return trans.fill_template_mako( + "visualization/gie.mako", + gie_image_map=self.gie_image_map, + history=trans.get_history(), + ) + + def _gie_config_dir(self, gie_path, *args): + nargs = [gie_path, 'config'] + if len(args) > 0: + nargs += args + return os.path.join(*nargs) + @web.json def bookmarks_from_dataset( self, trans, hda_id=None, ldda_id=None ): if hda_id: diff --git a/static/maps/layout/menu.js.map b/static/maps/layout/menu.js.map index 0cf37a262f8..03bb3eff817 100644 --- a/static/maps/layout/menu.js.map +++ b/static/maps/layout/menu.js.map @@ -1 +1 @@ -{"version":3,"file":"menu.js","sources":["../../src/layout/menu.js"],"names":["define","Tours","Collection","Backbone","extend","model","Model","defaults","visible","target","fetch","options","this","reset","add","id","title","url","tooltip","disabled","Galaxy","user","menu","user_requests","lims_doc_url","get","cls","helpTab","support_url","search_url","mailing_lists","screencasts_url","wiki_url","citation_url","onclick","app","display","ToursView","window","location","root","terms_url","push","biostar_url","unshift","biostar_url_redirect","userTab","divider","use_remote_user","allow_user_creation","activeView","active_view","set","jQuery","Deferred","resolve","promise","Tab","View","initialize","setElement","_template","$dropdown","$","$toggle","$menu","$note","listenTo","render","events","click .dropdown-toggle","self","remove","$el","attr","css","visibility","_formatUrl","html","removeClass","addClass","placement","show","off","on","hide","empty","_","each","menuItem","append","_buildMenuItem","e","preventDefault","frame","_toggleClick","buildLink","label","trigger","m","popover","content","setTimeout","attributes","indexOf","charAt"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"menu.js","sources":["../../src/layout/menu.js"],"names":["define","Tours","Collection","Backbone","extend","model","Model","defaults","visible","target","fetch","options","this","reset","add","id","title","url","tooltip","disabled","Galaxy","user","menu","user_requests","lims_doc_url","get","cls","helpTab","support_url","search_url","mailing_lists","screencasts_url","wiki_url","citation_url","onclick","app","display","ToursView","window","location","root","terms_url","push","biostar_url","unshift","biostar_url_redirect","userTab","divider","use_remote_user","allow_user_creation","activeView","active_view","set","jQuery","Deferred","resolve","promise","Tab","View","initialize","setElement","_template","$dropdown","$","$toggle","$menu","$note","listenTo","render","events","click .dropdown-toggle","self","remove","$el","attr","css","visibility","_formatUrl","html","removeClass","addClass","placement","show","off","on","hide","empty","_","each","menuItem","append","_buildMenuItem","e","preventDefault","frame","_toggleClick","buildLink","label","trigger","m","popover","content","setTimeout","attributes","indexOf","charAt"],"mappings":"AACAA,QAAQ,aAAc,SAAUC,GAChC,GAAIC,GAAaC,SAASD,WAAWE,QACjCC,MAAOF,SAASG,MAAMF,QAClBG,UACIC,SAAkB,EAClBC,OAAkB,aAG1BC,MAAO,SAAUC,GACbA,EAAUA,MACVC,KAAKC,QAKLD,KAAKE,KACDC,GAAkB,WAClBC,MAAkB,eAClBC,IAAkB,GAClBC,QAAkB,uBAMtBN,KAAKE,KACDC,GAAkB,WAClBC,MAAkB,WAClBC,IAAkB,WAClBC,QAAkB,6BAClBC,UAAmBC,OAAOC,KAAKN,KAMnCH,KAAKE,KACDC,GAAkB,SAClBC,MAAkB,cAClBC,IAAkB,gBAClBC,QAAkB,6BAClBI,OACQN,MAAU,iBACVC,IAAU,iBAEVD,MAAU,YACVC,IAAU,2BAEVD,MAAU,YACVC,IAAU,4BAEVD,MAAU,iBACVC,IAAU,iCAEVD,MAAU,QACVC,IAAU,0BAOtBN,EAAQY,eAAiBX,KAAKE,KAC1BC,GAAkB,MAClBC,MAAkB,MAClBM,OACQN,MAAU,sBACVC,IAAU,mBAEVD,MAAU,eACVC,IAAU,gCAEVD,MAAU,OACVC,IAAUN,EAAQa,iBAO9BZ,KAAKE,KACDC,GAAkB,gBAClBC,MAAkB,gBAClBC,IAAkB,qBAClBC,QAAkB,qBAClBC,UAAmBC,OAAOC,KAAKN,GAC/BO,OACQN,MAAU,oBACVC,IAAU,0BACVR,OAAU,WAEVO,MAAU,uBACVC,IAAU,qBACVR,OAAU,WAEVO,MAAU,2BACVC,IAAU,yBACVR,OAAU,kBAQtBW,OAAOC,KAAKI,IAAK,aAAgBb,KAAKE,KAClCC,GAAkB,QAClBC,MAAkB,QAClBC,IAAkB,QAClBC,QAAkB,yBAClBQ,IAAkB,cAMtB,IAAIC,IACAZ,GAAkB,OAClBC,MAAkB,OAClBE,QAAkB,uCAClBI,OACQN,MAAU,UACVC,IAAUN,EAAQiB,YAClBnB,OAAU,WAEVO,MAAU,SACVC,IAAUN,EAAQkB,WAClBpB,OAAU,WAEVO,MAAU,gBACVC,IAAUN,EAAQmB,cAClBrB,OAAU,WAEVO,MAAU,SACVC,IAAUN,EAAQoB,gBAClBtB,OAAU,WAEVO,MAAU,OACVC,IAAUN,EAAQqB,SAClBvB,OAAU,WAEVO,MAAU,qBACVC,IAAUN,EAAQsB,aAClBxB,OAAU,WAEVO,MAAU,oBACVC,IAAU,QACViB,QAAU,WACFd,OAAOe,IACPf,OAAOe,IAAIC,QAAQ,GAAInC,GAAMoC,WAG7BC,OAAOC,SAAWnB,OAAOoB,KAAO,WAyBpD,IApBA7B,EAAQ8B,WAAad,EAAQL,KAAKoB,MAC9B1B,MAAU,uBACVC,IAAUN,EAAQ8B,UAClBhC,OAAU,WAEdE,EAAQgC,aAAehB,EAAQL,KAAKsB,SAChC5B,MAAU,iBACVC,IAAU,oCACVR,OAAU,WAEdE,EAAQgC,aAAehB,EAAQL,KAAKsB,SAChC5B,MAAU,iBACVC,IAAUN,EAAQkC,qBAClBpC,OAAU,WAEdG,KAAKE,IAAKa,GAKJP,OAAOC,KAAKN,GAkBX,CACH,GAAI+B,IACA/B,GAAkB,OAClBC,MAAkB,OAClBU,IAAkB,gBAClBR,QAAkB,qCAClBI,OACQN,MAAU,gBAAkBI,OAAOC,KAAKI,IAAK,WAE7CT,MAAU,cACVC,IAAU,qBACVR,OAAU,gBAEVO,MAAU,gBACVC,IAAU,cACVR,OAAU,gBAEVO,MAAU,SACVC,IAAU,cACVR,OAAU,OACVsC,SAAU,IAEV/B,MAAU,kBACVC,IAAU,eACVR,OAAU,gBAEVO,MAAU,iBACVC,IAAU,eACVR,OAAU,gBAEVO,MAAU,cACVC,IAAU,YACVR,OAAU,SAEVO,MAAU,WACVC,IAAU,8BACVR,OAAU,gBAGtBE,GAAQqC,iBAAmBF,EAAQxB,KAAKoB,MACpC1B,MAAU,cACVC,IAAU,mCACVR,OAAU,gBAEdG,KAAKE,IAAKgC,OA9DQ,CAClB,GAAIA,IACA/B,GAAkB,OAClBC,MAAkB,OAClBU,IAAkB,iBAClBR,QAAkB,gCAClBI,OACIN,MAAc,QACdC,IAAc,aACdR,OAAc,gBAGtBE,GAAQsC,qBAAuBH,EAAQxB,KAAKoB,MACxC1B,MAAU,WACVC,IAAU,cACVR,OAAU,gBAEdG,KAAKE,IAAKgC,GA+Cd,GAAII,GAAatC,KAAKa,IAAKd,EAAQwC,YAEnC,OADAD,IAAcA,EAAWE,IAAK,UAAU,IACjC,GAAIC,QAAOC,UAAWC,UAAUC,aAK3CC,EAAMtD,SAASuD,KAAKtD,QACpBuD,WAAY,SAAWhD,GACnBC,KAAKP,MAAQM,EAAQN,MACrBO,KAAKgD,WAAYhD,KAAKiD,aACtBjD,KAAKkD,UAAalD,KAAKmD,EAAG,aAC1BnD,KAAKoD,QAAapD,KAAKmD,EAAG,oBAC1BnD,KAAKqD,MAAarD,KAAKmD,EAAG,kBAC1BnD,KAAKsD,MAAatD,KAAKmD,EAAG,kBAC1BnD,KAAKuD,SAAUvD,KAAKP,MAAO,SAAUO,KAAKwD,OAAQxD,OAGtDyD,QACIC,yBAA2B,gBAG/BF,OAAQ,WACJ,GAAIG,GAAO3D,IAyCX,OAxCAmD,GAAG,YAAaS,SAChB5D,KAAK6D,IAAIC,KAAM,KAAM9D,KAAKP,MAAMU,IACvB4D,KAAOC,WAAahE,KAAKP,MAAMoB,IAAK,YAAe,WAAa,WACzEb,KAAKP,MAAM+C,IAAK,MAAOxC,KAAKiE,WAAYjE,KAAKP,MAAMoB,IAAK,SACxDb,KAAKsD,MAAMY,KAAMlE,KAAKP,MAAMoB,IAAK,SAAY,IAClCsD,cAAcC,SAAU,iBACxBA,SAAUpE,KAAKP,MAAMoB,IAAK,aAC1BkD,KAAOvC,QAAYxB,KAAKP,MAAMoB,IAAK,cAAiB,SAAW,SAC1Eb,KAAKoD,QAAQc,KAAMlE,KAAKP,MAAMoB,IAAK,UAAa,IACnCsD,cAAcC,SAAU,mBACxBA,SAAUpE,KAAKP,MAAMoB,IAAK,QAC1BuD,SAAUpE,KAAKP,MAAMoB,IAAK,SAAY,oBAAsBb,KAAKP,MAAMoB,IAAK,SAC5EuD,SAAUpE,KAAKP,MAAMoB,IAAK,WAAc,UACxCiD,KAAM,SAAU9D,KAAKP,MAAMoB,IAAK,WAChCiD,KAAM,OAAQ9D,KAAKP,MAAMoB,IAAK,QAC9BiD,KAAM,QAAS9D,KAAKP,MAAMoB,IAAK,YAC/BP,QAAS,WACtBN,KAAKP,MAAMoB,IAAK,YAAeb,KAAKoD,QAAQ9C,SAAW+D,UAAW,WAClErE,KAAKkD,UAAUiB,cAAcC,SAAU,YACxBA,SAAUpE,KAAKP,MAAMoB,IAAK,aAAgB,YAC1CuD,SAAUpE,KAAKP,MAAMoB,IAAK,WAAc,UAClDb,KAAKP,MAAMoB,IAAK,SAAYb,KAAKP,MAAMoB,IAAK,cAC7Cb,KAAKqD,MAAMiB,OACXnB,EAAG,cAAemB,OAAOC,MAAMC,GAAI,QAAU,WACzCrB,EAAG,cAAesB,OAClBd,EAAKlE,MAAM+C,IAAK,aAAa,OAGjCmB,EAAKN,MAAMoB,OACXtB,EAAG,cAAesB,QAEtBzE,KAAKqD,MAAMqB,QAAQP,YAAa,iBAC3BnE,KAAKP,MAAMoB,IAAK,UACjB8D,EAAEC,KAAM5E,KAAKP,MAAMoB,IAAK,QAAU,SAAUgE,GACxClB,EAAKN,MAAMyB,OAAQnB,EAAKoB,eAAgBF,IACxCA,EAAS1C,SAAWwB,EAAKN,MAAMyB,OAAQ3B,EAAG,SAAUiB,SAAU,cAElET,EAAKN,MAAMe,SAAU,iBACrBT,EAAKP,QAAQ0B,OAAQ3B,EAAG,QAASiB,SAAU,WAExCpE,MAIX+E,eAAgB,SAAWhF,GACvB,GAAI4D,GAAO3D,IAOX,OANAD,GAAU4E,EAAEhF,SAAUI,OAClBK,MAAc,GACdC,IAAc,GACdR,OAAc,YAElBE,EAAQM,IAAMsD,EAAKM,WAAYlE,EAAQM,KAChC8C,EAAG,SAAU2B,OAChB3B,EAAG,QAASW,KAAM,OAAQ/D,EAAQM,KACtByD,KAAM,SAAU/D,EAAQF,QACxBqE,KAAMnE,EAAQK,OACdoE,GAAI,QAAS,SAAUQ,GACnBA,EAAEC,iBACFtB,EAAKlE,MAAM+C,IAAK,aAAa,GACzBzC,EAAQuB,QACRvB,EAAQuB,UAERd,OAAO0E,MAAMhF,IAAKH,OAO9CoF,aAAc,SAAUH,GAehB,QAASI,GAAWC,EAAOhF,GACvB,MAAO8C,GAAG,UAAW2B,OAAQ3B,EAAG,QAASW,KAAM,OAAQtD,OAAOoB,KAAOvB,GAAM6D,KAAMmB,IAAUnB,OAfnG,GAAIP,GAAO3D,KACPP,EAAQO,KAAKP,KACjBuF,GAAEC,iBACF9B,EAAG,YAAasB,OAChBhF,EAAM6F,QAAS,WAAY,SAAUC,GACjC9F,EAAMU,KAAOoF,EAAEpF,IAAMoF,EAAE1E,IAAK,SAAY0E,EAAE/C,IAAK,aAAa,KAE1D/C,EAAMoB,IAAK,aAUbb,KAAKoD,QAAQoC,SAAWxF,KAAKoD,QAAQoC,QAAS,WAC9CxF,KAAKoD,QAAQoC,SACTtB,MAAc,EACdG,UAAc,SACdoB,QAAc,UAAYL,EAAW,QAAS,8BAAiC,OACrDA,EAAW,WAAY,+BAAkC,0BACpFI,QAAS,QACZE,WAAY,WAAa/B,EAAKP,QAAQoC,QAAS,YAAe,MAhBxD/F,EAAMoB,IAAK,QAGbpB,EAAM+C,IAAK,aAAa,GAFxB/C,EAAMoB,IAAK,WAAcpB,EAAMoB,IAAK,aAAgBL,OAAO0E,MAAMhF,IAAKT,EAAMkG,aAoBxF1B,WAAY,SAAU5D,GAClB,MAAqB,gBAAPA,IAA2C,KAAxBA,EAAIuF,QAAS,OAAoC,KAAnBvF,EAAIwF,OAAQ,GAAarF,OAAOoB,KAAOvB,EAAMA,GAIhH4C,UAAW,WACP,MAAQ,kJAUhB,QACI3D,WAAcA,EACduD,IAAcA"} \ No newline at end of file diff --git a/static/scripts/bundled/analysis.bundled.js b/static/scripts/bundled/analysis.bundled.js index 2220268b075..4a89d956d53 100644 --- a/static/scripts/bundled/analysis.bundled.js +++ b/static/scripts/bundled/analysis.bundled.js @@ -1,12 +1,12 @@ -webpackJsonp([3,1],[function(t,e,i){(function(t,e){var n=i(1),s=n,o=i(59).GalaxyApp,a=i(57),r=i(11),l=i(88),c=i(87),d=i(61),h=i(19),u=i(46);window.app=function(i,n){window.Galaxy=new o(i,n),Galaxy.debug("analysis app");var p=i.config,g=new l({el:"#left",userIsAnonymous:Galaxy.user.isAnonymous(),search_url:p.search_url,toolbox:p.toolbox,toolbox_in_panel:p.toolbox_in_panel,stored_workflow_menu_entries:p.stored_workflow_menu_entries,nginx_upload_path:p.nginx_upload_path,ftp_upload_site:p.ftp_upload_site,default_genome:p.default_genome,default_extension:p.default_extension}),f=new r.CenterPanel({el:"#center"}),m=new c({el:"#right",galaxyRoot:Galaxy.root,userIsAnonymous:Galaxy.user.isAnonymous(),allow_user_dataset_purge:p.allow_user_dataset_purge}),v=new d.PageLayoutView(t.extend(i,{el:"body",left:g,center:f,right:m}));Galaxy.page=v,Galaxy.params=Galaxy.config.params,Galaxy.toolPanel=g.tool_panel,Galaxy.upload=g.uploadButton,Galaxy.currHistoryPanel=m.historyView,Galaxy.currHistoryPanel.listenToGalaxy(Galaxy),Galaxy.app={display:function(t,e){s(".select2-hidden-accessible").remove(),f.display(t)}};new(e.Router.extend({initialize:function(t){this.options=t},execute:function(t,e,i){Galaxy.debug("router execute:",t,e,i);var n=a.parse(e.pop());e.push(n),t&&t.apply(this,e)},routes:{"(/)":"home","(/)root*":"home","(/)tours(/)(:tour_id)":"show_tours"},show_tours:function(t){t?u.giveTour(t):f.display(new u.ToursView)},home:function(t){t.tool_id||t.job_id?"upload1"===t.tool_id?(Galaxy.upload.show(),this._loadCenterIframe("welcome")):this._loadToolForm(t):t.workflow_id?this._loadCenterIframe("workflow/run?id="+t.workflow_id):t.m_c?this._loadCenterIframe(t.m_c+"/"+t.m_a):this._loadCenterIframe("welcome")},_loadToolForm:function(t){t.id=t.tool_id,f.display(new h.View(t))},_loadCenterIframe:function(t,e){e=e||Galaxy.root,t=e+t,f.$("#galaxy_main").prop("src",t)}}))(i);s(function(){v.render().right.historyView.loadCurrentHistory(),Galaxy.listenTo(v.right.historyView,"history-size-change",function(){Galaxy.user.fetch({url:Galaxy.user.urlRoot()+"/"+(Galaxy.user.id||"current")})}),v.right.historyView.connectToQuotaMeter(v.masthead.quotaMeter),e.history.start({root:Galaxy.root,pushState:!0})})}}).call(e,i(3),i(2))},,,,,,,function(t,e,i){var n,s;(function(o,a){n=[i(4),i(23),i(53),i(22),i(49),i(13),i(8)],s=function(t,e,i,n,s,r,l){var c=o.View.extend({tagName:"label",initialize:function(t){this.model=t&&t.model||new o.Model(t),this.tagName=t.tagName||this.tagName,this.setElement(a("<"+this.tagName+"/>")),this.listenTo(this.model,"change",this.render,this),this.render()},title:function(t){this.model.set("title",t)},value:function(){return this.model.get("title")},render:function(){return this.$el.removeClass().addClass("ui-label").addClass(this.model.get("cls")).html(this.model.get("title")),this}}),d=o.View.extend({initialize:function(t){this.model=t&&t.model||new o.Model({message:null,status:"info",cls:"",persistent:!1}).set(t),this.listenTo(this.model,"change",this.render,this),this.render()},update:function(t){this.model.set(t)},render:function(){this.$el.removeClass().addClass("ui-message").addClass(this.model.get("cls"));var t=this.model.get("status");if(this.model.get("large")?this.$el.addClass(("success"==t&&"done"||"danger"==t&&"error"||t)+"messagelarge"):this.$el.addClass("alert").addClass("alert-"+t),this.model.get("message")){if(this.$el.html(this.model.get("message")),this.$el.fadeIn(),this.timeout&&window.clearTimeout(this.timeout),!this.model.get("persistent")){var e=this;this.timeout=window.setTimeout(function(){e.$el.fadeOut()},3e3)}}else this.$el.fadeOut();return this}}),h=o.View.extend({initialize:function(t){this.model=t&&t.model||new o.Model({type:"text",placeholder:"",disabled:!1,visible:!0,cls:"",area:!1}).set(t),this.tagName=this.model.get("area")?"textarea":"input",this.setElement(a("<"+this.tagName+"/>")),this.listenTo(this.model,"change",this.render,this),this.render()},events:{input:"_onchange"},value:function(t){return void 0!==t&&this.model.set("value","string"==typeof t?t:""),this.model.get("value")},render:function(){return this.$el.removeClass().addClass("ui-"+this.tagName).addClass(this.model.get("cls")).attr("id",this.model.id).attr("type",this.model.get("type")).attr("placeholder",this.model.get("placeholder")).val(this.model.get("value")),this.model.get("disabled")?this.$el.attr("disabled",!0):this.$el.removeAttr("disabled"),this.$el[this.model.get("visible")?"show":"hide"](),this},_onchange:function(){this.value(this.$el.val()),this.model.get("onchange")&&this.model.get("onchange")(this.model.get("value"))}}),u=o.View.extend({initialize:function(t){this.model=t&&t.model||new o.Model(t),this.setElement(a("
").append(this.$info=a("
")).append(this.$hidden=a("
"))),this.listenTo(this.model,"change",this.render,this),this.render()},value:function(t){return void 0!==t&&this.model.set("value",t),this.model.get("value")},render:function(){return this.$el.attr("id",this.model.id),this.$hidden.val(this.model.get("value")),this.model.get("info")?this.$info.show().html(this.model.get("info")):this.$info.hide(),this}});return{Button:r.ButtonDefault,ButtonIcon:r.ButtonIcon,ButtonCheck:r.ButtonCheck,ButtonMenu:r.ButtonMenu,ButtonLink:r.ButtonLink,Input:h,Label:c,Message:d,Modal:l,RadioButton:n.RadioButton,Checkbox:n.Checkbox,Radio:n.Radio,Select:e,Hidden:u,Slider:i,Drilldown:s}}.apply(e,n),!(void 0!==s&&(t.exports=s))}).call(e,i(2),i(1))},,function(t,e,i){var n,s;(function(o,a){n=[i(4)],s=function(t){var e=o.View.extend({visible:!1,initialize:function(e){var i=this;this.options=t.merge(e,{id:t.uid(),title:"",icon:"",buttons:null,body:null,scrollable:!0,nopadding:!1,operations:null,placement:"bottom",cls:"ui-portlet",operations_flt:"right",collapsible:!1,collapsed:!1}),this.setElement(this._template(this.options)),this.$body=this.$(".portlet-body"),this.$title=this.$(".portlet-title-text"),this.$header=this.$(".portlet-header"),this.$content=this.$(".portlet-content"),this.$footer=this.$(".portlet-footer"),this.options.nopadding&&(this.$content.css("padding","0px"),this.$body.css("padding","0px")),this.$buttons=this.$(".portlet-buttons"),this.options.buttons?a.each(this.options.buttons,function(t,e){e.$el.prop("id",t),i.$buttons.append(e.$el)}):this.$buttons.remove(),this.$operations=this.$(".portlet-operations"),this.options.operations&&a.each(this.options.operations,function(t,e){e.$el.prop("id",t),i.$operations.append(e.$el)}),this.options.body&&this.append(this.options.body),this.collapsed=!1,this.options.collapsible&&(this.$title.addClass("no-highlight").css({cursor:"pointer","text-decoration":"underline"}),this.$title.on("click",function(){i.collapsed?i.expand():i.collapse()}),this.options.collapsed&&this.collapse())},append:function(t){this.$body.append(t)},empty:function(){this.$body.empty()},header:function(){return this.$header},body:function(){return this.$body},footer:function(){return this.$footer},show:function(){this.visible=!0,this.$el.fadeIn("fast")},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(t){this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(t){this.$buttons.find("#"+t).prop("disabled",!0)},hideOperation:function(t){this.$operations.find("#"+t).hide()},showOperation:function(t){this.$operations.find("#"+t).show()},setOperation:function(t,e){var i=this.$operations.find("#"+t);i.off("click"),i.on("click",e)},title:function(t){var e=this.$title;return t&&e.html(t),e.html()},collapse:function(){this.collapsed=!0,this.$content.height("0%"),this.$body.hide(),this.$footer.hide(),this.trigger("collapsed")},expand:function(){this.collapsed=!1,this.$content.height("100%"),this.$body.fadeIn("fast"),this.$footer.fadeIn("fast"),this.trigger("expanded")},disable:function(){this.$(".portlet-backdrop").show()},enable:function(){this.$(".portlet-backdrop").hide()},_template:function(t){var e='
';return t.title&&(e+='
',t.icon&&(e+=' '),e+=''+t.title+"
"),e+='
',"top"==t.placement&&(e+='
'),e+='
',"bottom"==t.placement&&(e+='
'),e+='