diff --git a/client/galaxy/scripts/app/singleton.js b/client/galaxy/scripts/app/singleton.js index bab784f2af9..3b711cfb382 100644 --- a/client/galaxy/scripts/app/singleton.js +++ b/client/galaxy/scripts/app/singleton.js @@ -4,12 +4,12 @@ import addLogging from "utils/add-logging"; import { GalaxyApp } from "./galaxy"; -// import { serverPath } from "utils/serverPath"; +import { serverPath } from "utils/serverPath"; -export function setGalaxyInstance(factory, atTop = true) { - // console.warn("setGalaxyInstance", serverPath()); +export function setGalaxyInstance(factory) { + console.warn("setGalaxyInstance", serverPath()); - let storage = getStorage(atTop); + let storage = getStorage(); let newInstance = factory(GalaxyApp); if (!(newInstance instanceof GalaxyApp)) { newInstance = new GalaxyApp(newInstance); @@ -19,7 +19,6 @@ export function setGalaxyInstance(factory, atTop = true) { } // Debugging frame property - // storage._galaxyInstance = new Proxy(newInstance, { // get(galaxy, prop) { // if (prop == "frame") { @@ -46,17 +45,18 @@ export function setGalaxyInstance(factory, atTop = true) { return storage._galaxyInstance; } -export function getGalaxyInstance(atTop = true) { - let storage = getStorage(atTop); +export function getGalaxyInstance() { + let storage = getStorage(); return storage._galaxyInstance; } -export function galaxyIsInitialized(atTop = true) { - let instance = getGalaxyInstance(atTop); +export function galaxyIsInitialized() { + let instance = getGalaxyInstance(); return instance !== null; } -export function getStorage(atTop = true) { - let storage = window !== window.top && atTop ? window.top : window; - return storage; +// Having a CORS issue in the toolshed iframe, store separate versions +// of galaxy in each window for the short-term +export function getStorage() { + return window; } diff --git a/client/galaxy/scripts/apps/admin.js b/client/galaxy/scripts/apps/admin.js index caa631c8daf..f3d2ba2b54e 100644 --- a/client/galaxy/scripts/apps/admin.js +++ b/client/galaxy/scripts/apps/admin.js @@ -15,6 +15,7 @@ import DataTypes from "components/admin/DataTypes.vue"; import DataManagerView from "components/admin/DataManager/DataManagerView.vue"; import DataManagerRouter from "components/admin/DataManager/DataManagerRouter.vue"; import ErrorStack from "components/admin/ErrorStack.vue"; +import DisplayApplications from "components/admin/DisplayApplications.vue"; import Vue from "vue"; import { serverPath } from "utils/serverPath"; @@ -35,6 +36,7 @@ window.app = function app(options, bootstrapped) { "(/)admin(/)roles": "show_roles", "(/)admin(/)groups": "show_groups", "(/)admin(/)error_stack": "show_error_stack", + "(/)admin(/)display_applications": "show_display_applications", "(/)admin(/)tool_versions": "show_tool_versions", "(/)admin(/)quotas": "show_quotas", "(/)admin(/)repositories": "show_repositories", @@ -113,12 +115,14 @@ window.app = function app(options, bootstrapped) { }) ); }, + _display_vue_helper: function(component, props) { let instance = Vue.extend(component); let vm = document.createElement("div"); this.page.display(vm); new instance(props).$mount(vm); }, + show_data_tables: function() { this._display_vue_helper(DataTables); }, @@ -131,6 +135,10 @@ window.app = function app(options, bootstrapped) { this._display_vue_helper(ErrorStack); }, + show_display_applications: function() { + this._display_vue_helper(DisplayApplications); + }, + show_data_manager: function(path) { let vueMount = document.createElement("div"); this.page.display(vueMount); diff --git a/client/galaxy/scripts/apps/extended.js b/client/galaxy/scripts/apps/extended.js index 59bd7c460f9..50580cb7500 100644 --- a/client/galaxy/scripts/apps/extended.js +++ b/client/galaxy/scripts/apps/extended.js @@ -80,3 +80,6 @@ export function multiHistory(options) { multipanel.render(0); }); } + +// Used in common.mako +export { default as store } from "store"; \ No newline at end of file diff --git a/client/galaxy/scripts/apps/panels/admin-panel.js b/client/galaxy/scripts/apps/panels/admin-panel.js index 0d6d6929abf..bf44e4175a9 100644 --- a/client/galaxy/scripts/apps/panels/admin-panel.js +++ b/client/galaxy/scripts/apps/panels/admin-panel.js @@ -34,6 +34,7 @@ var AdminPanel = Backbone.View.extend({ { title: _l("Display applications"), url: "admin/display_applications", + target: "__use_router__", id: "admin-link-display-applications" }, { diff --git a/client/galaxy/scripts/components/GalaxyLoader.vue b/client/galaxy/scripts/components/GalaxyLoader.vue index afe8ebb75d8..a21b2a37604 100644 --- a/client/galaxy/scripts/components/GalaxyLoader.vue +++ b/client/galaxy/scripts/components/GalaxyLoader.vue @@ -9,147 +9,154 @@ diff --git a/client/galaxy/scripts/components/admin/AdminServices.js b/client/galaxy/scripts/components/admin/AdminServices.js index c70276f7e55..22c0c1c2e33 100644 --- a/client/galaxy/scripts/components/admin/AdminServices.js +++ b/client/galaxy/scripts/components/admin/AdminServices.js @@ -5,3 +5,13 @@ export function getErrorStack() { let url = `${getAppRoot()}api/tools/error_stack`; return axios.get(url); } + +export function getDisplayApplications() { + let url = `${getAppRoot()}api/display_applications`; + return axios.get(url); +} + +export function reloadDisplayApplications(ids) { + let url = `${getAppRoot()}api/display_applications/reload`; + return axios.post(url, { ids: ids }); +} diff --git a/client/galaxy/scripts/components/admin/DisplayApplications.vue b/client/galaxy/scripts/components/admin/DisplayApplications.vue new file mode 100644 index 00000000000..74cf82a66fc --- /dev/null +++ b/client/galaxy/scripts/components/admin/DisplayApplications.vue @@ -0,0 +1,124 @@ + + diff --git a/client/galaxy/scripts/layout/panel.js b/client/galaxy/scripts/layout/panel.js index 705bc22418c..af891ca3bf5 100644 --- a/client/galaxy/scripts/layout/panel.js +++ b/client/galaxy/scripts/layout/panel.js @@ -203,23 +203,29 @@ var CenterPanel = Backbone.View.extend({ this.setElement($(this.template())); this.$frame = this.$(".center-frame"); this.$panel = this.$(".center-panel"); - this.$frame.on("load", _.bind(this._iframeChangeHandler, this)); + this.$frame.on("load", this._iframeChangeHandler.bind(this)); }, /** Display iframe if its target url changes, hide center panel */ _iframeChangeHandler: function(ev) { var iframe = ev.currentTarget; var location = iframe.contentWindow && iframe.contentWindow.location; - if (location && location.host) { - $(iframe).show(); - this.$panel.empty().hide(); - var Galaxy = getGalaxyInstance(); - Galaxy.trigger("center-frame:load", { - fullpath: location.pathname + location.search + location.hash, - pathname: location.pathname, - search: location.search, - hash: location.hash - }); + var Galaxy = getGalaxyInstance(); + // Adding try/catch to manage a CORS error in toolshed. Accessing + // location.host is a CORS no-no + try { + if (location && location.host) { + $(iframe).show(); + this.$panel.empty().hide(); + Galaxy.trigger("center-frame:load", { + fullpath: location.pathname + location.search + location.hash, + pathname: location.pathname, + search: location.search, + hash: location.hash + }); + } + } catch (err) { + console.warn("_iframeChangeHandler error", ev, location, Galaxy); } }, diff --git a/client/galaxy/scripts/mvc/collection/collection-li.js b/client/galaxy/scripts/mvc/collection/collection-li.js index 89663b4d463..48c0b7cf88c 100644 --- a/client/galaxy/scripts/mvc/collection/collection-li.js +++ b/client/galaxy/scripts/mvc/collection/collection-li.js @@ -1,12 +1,10 @@ -import LIST_ITEM from "mvc/list/list-item"; -import DATASET_LI from "mvc/dataset/dataset-li"; +import _ from "underscore"; +import $ from "jquery"; +import { ListItemView, FoldoutListItemView } from "mvc/list/list-item"; +import { DatasetListItemView } from "mvc/dataset/dataset-li"; import BASE_MVC from "mvc/base-mvc"; import _l from "utils/localization"; -//============================================================================== -var FoldoutListItemView = LIST_ITEM.FoldoutListItemView; - -var ListItemView = LIST_ITEM.ListItemView; /** @class Read only view for DatasetCollection. */ var DCListItemView = FoldoutListItemView.extend( @@ -189,9 +187,9 @@ DCEListItemView.prototype.templates = (() => { /** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation * (a dataset contained in a dataset collection). */ -var DatasetDCEListItemView = DATASET_LI.DatasetListItemView.extend( +var DatasetDCEListItemView = DatasetListItemView.extend( /** @lends DatasetDCEListItemView.prototype */ { - className: `${DATASET_LI.DatasetListItemView.prototype.className} dataset-collection-element`, + className: `${DatasetListItemView.prototype.className} dataset-collection-element`, /** set up */ initialize: function(attributes) { @@ -199,7 +197,7 @@ var DatasetDCEListItemView = DATASET_LI.DatasetListItemView.extend( this.logger = this.model.logger = attributes.logger; } this.log("DatasetDCEListItemView.initialize:", attributes); - DATASET_LI.DatasetListItemView.prototype.initialize.call(this, attributes); + DatasetListItemView.prototype.initialize.call(this, attributes); }, /** In this override, only get details if in the ready state. @@ -210,7 +208,7 @@ var DatasetDCEListItemView = DATASET_LI.DatasetListItemView.extend( if (view.model.inReadyState() && !view.model.hasDetails()) { return view.model.fetch({ silent: true }); } - return jQuery.when(); + return $.when(); }, // ......................................................................... misc @@ -239,7 +237,7 @@ DatasetDCEListItemView.prototype.templates = (() => { "element" ); - return _.extend({}, DATASET_LI.DatasetListItemView.prototype.templates, { + return _.extend({}, DatasetListItemView.prototype.templates, { titleBar: titleBarTemplate }); })(); diff --git a/client/galaxy/scripts/mvc/collection/collection-view.js b/client/galaxy/scripts/mvc/collection/collection-view.js index 68419881def..ac49b034789 100644 --- a/client/galaxy/scripts/mvc/collection/collection-view.js +++ b/client/galaxy/scripts/mvc/collection/collection-view.js @@ -1,9 +1,7 @@ import _ from "underscore"; import { getAppRoot } from "onload/loadConfig"; import LIST_VIEW from "mvc/list/list-view"; -import DC_MODEL from "mvc/collection/collection-model"; import DC_LI from "mvc/collection/collection-li"; -import BASE_MVC from "mvc/base-mvc"; import _l from "utils/localization"; var logNamespace = "collections"; @@ -56,7 +54,6 @@ var CollectionView = _super.extend( var panel = this; this.handleWarning($newRender); panel.log("_queueNewRender:", $newRender, speed); - // TODO: jquery@1.12 doesn't change display when the elem has display: flex // this causes display: block for those elems after the use of show/hide animations // animations are removed from this view for now until fixed diff --git a/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js b/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js index 06b01b48445..7b303b528aa 100644 --- a/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js +++ b/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js @@ -83,7 +83,7 @@ var DatasetListItemEdit = _super.extend( } // disable if still uploading or new - } else if (_.contains([STATES.UPLOAD, STATES.NEW], this.model.get("state"))) { + } else if ([STATES.UPLOAD, STATES.NEW].includes(this.model.get("state"))) { editBtnData.disabled = true; editBtnData.title = _l("This dataset is not yet editable"); } @@ -119,10 +119,13 @@ var DatasetListItemEdit = _super.extend( var state = this.model.get("state"); - if (!this.model.isDeletedOrPurged() && _.contains([STATES.OK, STATES.FAILED_METADATA], state)) { + if (!this.model.isDeletedOrPurged()) { + //Enable tagging+annotation regardless of job state (see issue #6330) this._renderTags($details); this._renderAnnotation($details); - this._makeDbkeyEditLink($details); + if ([STATES.OK, STATES.FAILED_METADATA].includes(state)) { + this._makeDbkeyEditLink($details); + } } this._setUpBehaviors($details); diff --git a/client/galaxy/scripts/mvc/dataset/dataset-li.js b/client/galaxy/scripts/mvc/dataset/dataset-li.js index 5fa3614c6f0..d12fa457005 100644 --- a/client/galaxy/scripts/mvc/dataset/dataset-li.js +++ b/client/galaxy/scripts/mvc/dataset/dataset-li.js @@ -20,7 +20,7 @@ var _super = LIST_ITEM.ListItemView; /** @class Read only list view for either LDDAs, HDAs, or HDADCEs. * Roughly, any DatasetInstance (and not a raw Dataset). */ -var DatasetListItemView = _super.extend( +export var DatasetListItemView = _super.extend( /** @lends DatasetListItemView.prototype */ { _logNamespace: logNamespace, diff --git a/client/galaxy/scripts/mvc/history/hdca-li.js b/client/galaxy/scripts/mvc/history/hdca-li.js index f7a89692287..8b5383ba526 100644 --- a/client/galaxy/scripts/mvc/history/hdca-li.js +++ b/client/galaxy/scripts/mvc/history/hdca-li.js @@ -1,7 +1,7 @@ +import _ from "underscore"; import STATES from "mvc/dataset/states"; import DC_LI from "mvc/collection/collection-li"; import DC_VIEW from "mvc/collection/collection-view"; -import BASE_MVC from "mvc/base-mvc"; import HISTORY_ITEM_LI from "mvc/history/history-item-li"; import _l from "utils/localization"; @@ -17,7 +17,8 @@ var HDCAListItemView = _super.extend( _setUpListeners: function() { _super.prototype._setUpListeners.call(this); var renderListen = (model, options) => { - this.render(); + // We want this to swap immediately without extra animations. + this.render(0); }; if (this.model.jobStatesSummary) { this.listenTo(this.model.jobStatesSummary, "change", renderListen); @@ -64,9 +65,7 @@ var HDCAListItemView = _super.extend( stateDescription: function() { var collection = this.model; - var elementCount = collection.get("element_count"); var jobStateSource = collection.get("job_source_type"); - var collectionType = this.model.get("collection_type"); var collectionTypeDescription = DC_VIEW.collectionTypeDescription(collection); var simpleDescription = DC_VIEW.collectionDescription(collection); var jobStatesSummary = collection.jobStatesSummary; diff --git a/client/galaxy/scripts/mvc/history/history-item-li.js b/client/galaxy/scripts/mvc/history/history-item-li.js index 42ab15671d0..0208ffbfda9 100644 --- a/client/galaxy/scripts/mvc/history/history-item-li.js +++ b/client/galaxy/scripts/mvc/history/history-item-li.js @@ -1,7 +1,9 @@ import Utils from "utils/utils"; function _templateNametag(tag) { - return `${_.escape(tag.slice(5))}`; + return `${_.escape( + tag.slice(5) + )}`; } function nametagTemplate(historyItem) { diff --git a/client/galaxy/scripts/mvc/list/list-item.js b/client/galaxy/scripts/mvc/list/list-item.js index 8633ad9cd60..3f1d0b0430a 100644 --- a/client/galaxy/scripts/mvc/list/list-item.js +++ b/client/galaxy/scripts/mvc/list/list-item.js @@ -1,5 +1,7 @@ +import $ from "jquery"; +import Backbone from "backbone"; +import _ from "underscore"; import BASE_MVC from "mvc/base-mvc"; -import _l from "utils/localization"; var logNamespace = "list"; //============================================================================== @@ -142,7 +144,7 @@ var ExpandableView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({ if (!this.model.hasDetails()) { return this.model.fetch(); } - return jQuery.when(); + return $.when(); }, /** Inner fn called when expand (public) has fetched the details */ @@ -182,7 +184,7 @@ var ExpandableView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({ * * Designed as a base class for history panel contents - but usable elsewhere (I hope). */ -var ListItemView = ExpandableView.extend( +export var ListItemView = ExpandableView.extend( BASE_MVC.mixin(BASE_MVC.SelectableViewMixin, BASE_MVC.DraggableViewMixin, { tagName: "div", className: "list-item", @@ -380,7 +382,7 @@ ListItemView.prototype.templates = (() => { * * _renderDetails does the work of creating this.details: a sub-view that shows the nested list */ -var FoldoutListItemView = ListItemView.extend({ +export var FoldoutListItemView = ListItemView.extend({ /** If 'foldout': show the sub-panel inside the expanded item * If 'drilldown': only fire events and handle by pub-sub * (allow the panel containing this item to attach it, hide itself, etc.) diff --git a/client/galaxy/scripts/mvc/list/list-view.js b/client/galaxy/scripts/mvc/list/list-view.js index 009b2fe0470..25bb73ed901 100644 --- a/client/galaxy/scripts/mvc/list/list-view.js +++ b/client/galaxy/scripts/mvc/list/list-view.js @@ -1,3 +1,6 @@ +import $ from "jquery"; +import Backbone from "backbone"; +import _ from "underscore"; import LIST_ITEM from "mvc/list/list-item"; import LoadingIndicator from "ui/loading-indicator"; import BASE_MVC from "mvc/base-mvc"; diff --git a/client/galaxy/scripts/mvc/ui/ui-select-default.js b/client/galaxy/scripts/mvc/ui/ui-select-default.js index e3b29a6bd66..6e4281d6a60 100644 --- a/client/galaxy/scripts/mvc/ui/ui-select-default.js +++ b/client/galaxy/scripts/mvc/ui/ui-select-default.js @@ -208,9 +208,9 @@ var View = Backbone.View.extend({ ${_.reduce( filteredTags.slice(0, 5), (memo, tag) => { - return `${memo} 
${_.escape( - tag - )}
`; + return `${memo} 
${_.escape(tag)}
`; }, "" )} diff --git a/client/galaxy/scripts/utils/utils.js b/client/galaxy/scripts/utils/utils.js index 89ce6ec3f5d..7d9bf09043a 100644 --- a/client/galaxy/scripts/utils/utils.js +++ b/client/galaxy/scripts/utils/utils.js @@ -358,7 +358,8 @@ export function setWindowTitle(title) { * @returns {integer} */ function hashFnv32a(str) { - var i, l, + var i, + l, hval = 0x811c9dc5; for (i = 0, l = str.length; i < l; i++) { @@ -380,10 +381,8 @@ function hashFnv32a(str) { * Assumes r, g, b are in the set [0, 1] */ function contrastingColor(r, g, b) { - var o = ((r * 255 * 299) + - (g * 255 * 587) + - (b * 255 * 114)) / 1000; - return (o > 125) ? 'black' : 'white'; + var o = (r * 255 * 299 + g * 255 * 587 + b * 255 * 114) / 1000; + return o > 125 ? "black" : "white"; } /** @@ -397,26 +396,26 @@ function contrastingColor(r, g, b) { * @param {number} l The lightness * @return {Array} The RGB representation */ -function hslToRgb(h, s, l){ +function hslToRgb(h, s, l) { var r, g, b; - if(s == 0){ + if (s == 0) { r = g = b = l; // achromatic - }else{ - var hue2rgb = function hue2rgb(p, q, t){ - if(t < 0) t += 1; - if(t > 1) t -= 1; - if(t < 1/6) return p + (q - p) * 6 * t; - if(t < 1/2) return q; - if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + } else { + var hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; - } + }; var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3); + r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); + b = hue2rgb(p, q, h - 1 / 3); } return [r, g, b]; @@ -431,12 +430,11 @@ export function generateTagStyle(tag) { var brColor = `hsl(${hue}, 100%, ${lightness - 40}%)`; var [r, g, b] = hslToRgb(hue, 1.0, lightness / 100); - var fgColor = contrastingColor(r, g, b) + var fgColor = contrastingColor(r, g, b); - return `background-color: ${bgColor}; color: ${fgColor}; border: 1px solid ${brColor}` + return `background-color: ${bgColor}; color: ${fgColor}; border: 1px solid ${brColor}`; } - export default { cssLoadFile: cssLoadFile, cssGetAttribute: cssGetAttribute, diff --git a/config/datatypes_conf.xml.sample b/config/datatypes_conf.xml.sample index 29daee09b6f..7fe5ab9c57e 100644 --- a/config/datatypes_conf.xml.sample +++ b/config/datatypes_conf.xml.sample @@ -538,6 +538,7 @@ + diff --git a/config/tool_conf.xml.sample b/config/tool_conf.xml.sample index 575d19786ff..f77edc40d82 100644 --- a/config/tool_conf.xml.sample +++ b/config/tool_conf.xml.sample @@ -121,10 +121,6 @@ - - - - diff --git a/doc/source/dev/build_a_job_runner.rst b/doc/source/dev/build_a_job_runner.rst index a34c7a0f638..30e97a8d6c7 100644 --- a/doc/source/dev/build_a_job_runner.rst +++ b/doc/source/dev/build_a_job_runner.rst @@ -120,7 +120,7 @@ B: Update the dictionary structure in kwargs. :: - kwargs['runner_param_specs'].update(runner_param_specs) + kwargs.update({'runner_param_specs': runner_param_specs}) C: Now call the parent constructor to assign the values. diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py index 19ec0f80962..8da7603ad4d 100644 --- a/lib/galaxy/datatypes/binary.py +++ b/lib/galaxy/datatypes/binary.py @@ -126,6 +126,18 @@ class Cel(Binary): return False +class MashSketch(Binary): + """ + Mash Sketch file. + Sketches are used by the MinHash algorithm to allow fast distance estimations + with low storage and memory requirements. To make a sketch, each k-mer in a sequence + is hashed, which creates a pseudo-random identifier. By sorting these identifiers (hashes), + a small subset from the top of the sorted list can represent the entire sequence (these are min-hashes). + The more similar another sequence is, the more min-hashes it is likely to share. + """ + file_ext = "msh" + + class CompressedArchive(Binary): """ Class describing an compressed binary file diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index 95474dbcf02..81568791562 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -1441,11 +1441,9 @@ class JobWrapper(HasResourceParameters): # why not re-use self.param_dict here? param_dict = dict([(p.name, p.value) for p in job.parameters]) param_dict = self.tool.params_from_strings(param_dict, self.app) - # Create generated output children and primary datasets and add to param_dict + # Create generated output children and primary datasets and dynamic outputs. tool_working_directory = self.tool_working_directory - collected_datasets = { - 'primary': self.tool.collect_primary_datasets(out_data, self.get_tool_provided_job_metadata(), tool_working_directory, input_ext, input_dbkey) - } + self.tool.collect_primary_datasets(out_data, self.get_tool_provided_job_metadata(), tool_working_directory, input_ext, input_dbkey) self.tool.collect_dynamic_outputs( out_collections, self.get_tool_provided_job_metadata(), @@ -1454,7 +1452,6 @@ class JobWrapper(HasResourceParameters): job=job, input_dbkey=input_dbkey, ) - param_dict.update({'__collected_datasets__': collected_datasets}) # Certain tools require tasks to be completed after job execution # ( this used to be performed in the "exec_after_process" hook, but hooks are deprecated ). self.tool.exec_after_process(self.app, inp_data, out_data, param_dict, job=job) diff --git a/lib/galaxy/tools/filter_from_file.xml b/lib/galaxy/tools/filter_from_file.xml index 6dbb28277a4..defcba39147 100644 --- a/lib/galaxy/tools/filter_from_file.xml +++ b/lib/galaxy/tools/filter_from_file.xml @@ -81,9 +81,11 @@ .. class:: infomark - This tool will take an input list and a text file with identifiers to - filter the list with. It will build two new lists - one "filtered" to - contain only the supplied identifiers and one of the discarded elements. + This tool will take an input list and a text file with + names (i.e. identifiers). It will split the input list into + two new lists - one filtered to contain only the list members + whose names are listed in the text file, and one containing + all the other elements. This tool will create new history datasets from your collection but your quota usage will not increase. diff --git a/lib/galaxy/tools/parameters/output_collect.py b/lib/galaxy/tools/parameters/output_collect.py index 8beb2b353d4..5bdd62c061f 100644 --- a/lib/galaxy/tools/parameters/output_collect.py +++ b/lib/galaxy/tools/parameters/output_collect.py @@ -613,6 +613,7 @@ def collect_primary_datasets(tool, output, tool_provided_metadata, job_working_d extra_files_path_joined = os.path.join(job_working_directory, extra_files_path) for root, dirs, files in os.walk(extra_files_path_joined): extra_dir = os.path.join(primary_data.extra_files_path, root.replace(extra_files_path_joined, '', 1).lstrip(os.path.sep)) + extra_dir = os.path.normpath(extra_dir) for f in files: app.object_store.update_from_file( primary_data.dataset, @@ -620,7 +621,6 @@ def collect_primary_datasets(tool, output, tool_provided_metadata, job_working_d alt_name=f, file_name=os.path.join(root, f), create=True, - dir_only=True, preserve_symlinks=True ) metadata_dict = new_primary_datasets_attributes.get('metadata', None) @@ -631,8 +631,6 @@ def collect_primary_datasets(tool, output, tool_provided_metadata, job_working_d else: primary_data.set_meta() primary_data.set_peek() - sa_session.add(primary_data) - sa_session.flush() outdata.history.add_dataset(primary_data) # Add dataset to return dict primary_datasets[name][designation] = primary_data @@ -651,7 +649,8 @@ def collect_primary_datasets(tool, output, tool_provided_metadata, job_working_d outdata.set_meta() outdata.set_peek() sa_session.add(outdata) - sa_session.flush() + + sa_session.flush() return primary_datasets diff --git a/lib/galaxy/tools/verify/__init__.py b/lib/galaxy/tools/verify/__init__.py index 8f41eaafcbb..7ad36c8322e 100644 --- a/lib/galaxy/tools/verify/__init__.py +++ b/lib/galaxy/tools/verify/__init__.py @@ -69,6 +69,9 @@ def verify( errmsg += str(err) raise AssertionError(errmsg) + if attributes is None: + attributes = {} + if filename is not None: local_name = get_filename(filename) temp_name = make_temp_fname(fname=filename) @@ -88,8 +91,6 @@ def verify( else: log.debug('## GALAXY_TEST_SAVE=%s. saved %s' % (keep_outputs_dir, ofn)) try: - if attributes is None: - attributes = {} compare = attributes.get('compare', 'diff') if attributes.get('ftype', None) in ['bam', 'qname_sorted.bam', 'qname_input_sorted.bam', 'unsorted.bam']: local_fh, temp_name = _bam_to_sam(local_name, temp_name) @@ -110,10 +111,6 @@ def verify( files_contains(local_name, temp_name, attributes=attributes) else: raise Exception('Unimplemented Compare type: %s' % compare) - if verify_extra_files: - extra_files = attributes.get('extra_files', None) - if extra_files: - verify_extra_files(extra_files) except AssertionError as err: errmsg = '%s different than expected, difference (using %s):\n' % (item_label, compare) errmsg += "( %s v. %s )\n" % (local_name, temp_name) @@ -123,6 +120,11 @@ def verify( if 'GALAXY_TEST_NO_CLEANUP' not in os.environ: os.remove(temp_name) + if verify_extra_files: + extra_files = attributes.get('extra_files', None) + if extra_files: + verify_extra_files(extra_files) + def make_temp_fname(fname=None): """Safe temp name - preserve the file extension for tools that interpret it.""" diff --git a/lib/galaxy/webapps/galaxy/api/display_applications.py b/lib/galaxy/webapps/galaxy/api/display_applications.py new file mode 100644 index 00000000000..d41ad8057e9 --- /dev/null +++ b/lib/galaxy/webapps/galaxy/api/display_applications.py @@ -0,0 +1,61 @@ +""" +API operations on annotations. +""" +import logging + +from galaxy import queue_worker +from galaxy.web import expose_api, require_admin +from galaxy.web.base.controller import BaseAPIController + +log = logging.getLogger(__name__) + + +class DisplayApplicationsController(BaseAPIController): + + @expose_api + def index(self, trans, **kwd): + """ + GET /api/display_applications/ + + Returns the list of display applications. + + :returns: list of available display applications + :rtype: list + """ + response = [] + for display_app in trans.app.datatypes_registry.display_applications.values(): + response.append({ + 'id' : display_app.id, + 'name': display_app.name, + 'version': display_app.version, + 'filename_': display_app._filename, + 'links': [{'name': l.name} for l in display_app.links.values()] + }) + return response + + @expose_api + @require_admin + def reload(self, trans, payload={}, **kwd): + """ + POST /api/display_applications/reload + + Reloads the list of display applications. + + :param ids: list containing ids of display to be reloaded + :type ids: list + """ + ids = payload.get('ids') + queue_worker.send_control_task(trans.app, + 'reload_display_application', + noop_self=True, + kwargs={'display_application_ids': ids}) + reloaded, failed = trans.app.datatypes_registry.reload_display_applications(ids) + if not reloaded and failed: + message = 'Unable to reload any of the %i requested display applications ("%s").' % (len(failed), '", "'.join(failed)) + elif failed: + message = 'Reloaded %i display applications ("%s"), but failed to reload %i display applications ("%s").' % (len(reloaded), '", "'.join(reloaded), len(failed), '", "'.join(failed)) + elif not reloaded: + message = 'You need to request at least one display application to reload.' + else: + message = 'Reloaded %i requested display applications ("%s").' % (len(reloaded), '", "'.join(reloaded)) + return {'message': message, 'reloaded': reloaded, 'failed': failed} diff --git a/lib/galaxy/webapps/galaxy/buildapp.py b/lib/galaxy/webapps/galaxy/buildapp.py index 7d24c804f1a..18dc202f427 100644 --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -104,6 +104,7 @@ def app_factory(global_conf, load_app_kwds={}, **kwargs): webapp.add_client_route('/admin/data_manager{path_info:.*}', 'admin') webapp.add_client_route('/admin/error_stack', 'admin') webapp.add_client_route('/admin/users', 'admin') + webapp.add_client_route('/admin/display_applications', 'admin') webapp.add_client_route('/admin/roles', 'admin') webapp.add_client_route('/admin/forms', 'admin') webapp.add_client_route('/admin/groups', 'admin') @@ -555,6 +556,22 @@ def populate_api_routes(webapp, app): action='get_api_key', conditions=dict(method=["GET"])) + # ====================================== + # ====== DISPLAY APPLICATIONS API ====== + # ====================================== + + webapp.mapper.connect('index', + '/api/display_applications', + controller='display_applications', + action='index', + conditions=dict(method=["GET"])) + + webapp.mapper.connect('reload', + '/api/display_applications/reload', + controller='display_applications', + action='reload', + conditions=dict(method=["POST"])) + # ===================== # ===== TOURS API ===== # ===================== diff --git a/lib/galaxy/webapps/galaxy/controllers/admin.py b/lib/galaxy/webapps/galaxy/controllers/admin.py index 72109145d61..b06bfa4841e 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -902,29 +902,6 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP message=message, status=status) - @web.expose - @web.require_admin - def display_applications(self, trans, **kwd): - return trans.fill_template('admin/view_display_applications.mako', display_applications=trans.app.datatypes_registry.display_applications) - - @web.expose - @web.require_admin - def reload_display_application(self, trans, **kwd): - galaxy.queue_worker.send_control_task(trans.app, - 'reload_display_application', - noop_self=True, - kwargs={'display_application_ids': kwd.get('id')}) - reloaded, failed = trans.app.datatypes_registry.reload_display_applications(kwd.get('id')) - if not reloaded and failed: - return trans.show_error_message('Unable to reload any of the %i requested display applications ("%s").' - % (len(failed), '", "'.join(failed))) - if failed: - return trans.show_warn_message('Reloaded %i display applications ("%s"), but failed to reload %i display applications ("%s").' - % (len(reloaded), '", "'.join(reloaded), len(failed), '", "'.join(failed))) - if not reloaded: - return trans.show_warn_message('You need to request at least one display application to reload.') - return trans.show_ok_message('Reloaded %i requested display applications ("%s").' % (len(reloaded), '", "'.join(reloaded))) - @web.expose @web.require_admin def center(self, trans, **kwd): diff --git a/templates/webapps/galaxy/admin/view_display_applications.mako b/templates/webapps/galaxy/admin/view_display_applications.mako deleted file mode 100644 index 27c0d822169..00000000000 --- a/templates/webapps/galaxy/admin/view_display_applications.mako +++ /dev/null @@ -1,48 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="/message.mako" import="render_msg" /> - -%if message: - ${render_msg( message, status )} -%endif - -
-
There are currently ${len( display_applications )} - - display applications loaded.
-
- - - - - - - - - - <% ctr = 0 %> - %for display_app in display_applications.values(): - %if ctr % 2 == 1: - - %else: - - %endif - - - - - - - - <% ctr += 1 %> - %endfor -
ReloadNameIDVersionLinksFilename
- - - - ${ display_app.name | h }${ display_app.id | h }${ display_app.version | h }
    - %for link in display_app.links.values(): -
  • ${ link.name | h }
  • - %endfor -
${ display_app._filename | h }
-
-
diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index 112103d7e85..e2060ddce3b 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -28,6 +28,9 @@ + + + diff --git a/test/functional/tools/tool_provided_metadata_10.xml b/test/functional/tools/tool_provided_metadata_10.xml new file mode 100644 index 00000000000..fce8be2f042 --- /dev/null +++ b/test/functional/tools/tool_provided_metadata_10.xml @@ -0,0 +1,38 @@ + + + + echo "1" > sample1.report.tsv; + cp $c1 galaxy.json; + + + {"sample": { +"datasets": [ +{"filename": "sample1.report.tsv", "name": "cool name 1", "ext": "txt", "info": "cool 1 info", "dbkey": "hg19", "metadata": {"data_lines": 10}} +] +}} + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/functional/tools/tool_provided_metadata_11.xml b/test/functional/tools/tool_provided_metadata_11.xml new file mode 100644 index 00000000000..415816ac9c4 --- /dev/null +++ b/test/functional/tools/tool_provided_metadata_11.xml @@ -0,0 +1,41 @@ + + + + mkdir sample1data; + echo "1" > sample1.report.tsv; + echo "foo line" > sample1data/foo; + echo "moo cow bar" > sample1data/bar; + cp $c1 galaxy.json; + + + {"type": "new_primary_dataset", "filename": "sample1.report.tsv", "name": "cool name 1", "ext": "txt", "info": "cool 1 info", "dbkey": "hg19", "extra_files": "sample1data"} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/functional/tools/tool_provided_metadata_12.xml b/test/functional/tools/tool_provided_metadata_12.xml new file mode 100644 index 00000000000..c3887785075 --- /dev/null +++ b/test/functional/tools/tool_provided_metadata_12.xml @@ -0,0 +1,45 @@ + + + + mkdir sample1data; + echo "1" > sample1.report.tsv; + echo "foo line" > sample1data/foo; + echo "moo cow bar" > sample1data/bar; + cp $c1 galaxy.json; + + + {"sample": { +"datasets": [ +{"filename": "sample1.report.tsv", "name": "cool name 1", "ext": "txt", "info": "cool 1 info", "dbkey": "hg19", "extra_files": "sample1data"} +] +}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/selenium_tests/test_admin_app.py b/test/selenium_tests/test_admin_app.py index feec319a0a3..a2db96290cc 100644 --- a/test/selenium_tests/test_admin_app.py +++ b/test/selenium_tests/test_admin_app.py @@ -23,8 +23,7 @@ class AdminAppTestCase(SeleniumTestCase): self.screenshot("admin_data_tables") admin_component.index.display_applications.wait_for_and_click() - with self.main_panel(): - admin_component.display_applications_grid.wait_for_visible() + self.assert_warning_message("No display applications available.") self.screenshot("admin_display_applications") admin_component.index.jobs.wait_for_and_click()