diff --git a/static/maps/mvc/collection/collection-model.js.map b/static/maps/mvc/collection/collection-model.js.map
index 40901deefc80..bfa0545b03b4 100644
--- a/static/maps/mvc/collection/collection-model.js.map
+++ b/static/maps/mvc/collection/collection-model.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/collection/collection-model.js"],"names":["DatasetCollectionElementMixin","defaults","model_class","element_identifier","element_index","element_type","_mergeObject","attributes","_","extend","object","element_id","id","options","this","idAttribute","apply","arguments","response","DatasetCollectionElement","Backbone","Model","_baseMvc2","default","LoggableMixin","_logNamespace","DCECollection","Collection","model","toString","length","join","DatasetDCE","_datasetModel2","DatasetAssociation","url","has","Galaxy","root","mixin","console","warn","prototype","_downloadQueryParameters","get","constructor","debug","call","elements","DatasetDCECollection","DatasetCollection","collection_type","deleted","collectionClass","initialize","_createElementsModel","log","unset","silent","self","each","element","index","parent_hdca_id","toJSON","json","inReadyState","populated","isDeletedOrPurged","hasDetails","getVisibleContents","filters","parse","parsed","create_time","Date","update_time","delete","jQuery","when","save","undelete","searchAttributes","idAndName","ListDatasetCollection","NestedDCDCE","objStr","NestedDCDCECollection","NestedPairDCDCE","PairDatasetCollection","NestedPairDCDCECollection","ListPairedDatasetCollection","NestedListDCDCE","NestedListDCDCECollection","ListOfListsDatasetCollection"],"mappings":"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","file":"../../../scripts/mvc/collection/collection-model.js","sourcesContent":["import DATASET_MODEL from \"mvc/dataset/dataset-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/*\nNotes:\n\nTerminology:\n DatasetCollection/DC : a container of datasets or nested DatasetCollections\n Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection\n HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history\n\n\nThis all seems too complex unfortunately:\n\n- Terminology collision between DatasetCollections (DCs) and Backbone Collections.\n- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*\n either a dataset or a nested DC. This would make the hierarchy much taller. I've\n decided to merge the contained JSON with the DC element json - making the 'has a'\n relation into an 'is a' relation. This seems simpler to me and allowed a lot of\n DRY in both models and views, but may make tracking or tracing within these models\n more difficult (since DatasetCollectionElements are now *also* DatasetAssociations\n or DatasetCollections (nested)). This also violates the rule of thumb about\n favoring aggregation over inheritance.\n- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.\n These each should a) be usable on their own, b) be usable in the context of\n nesting within a collection model (at least in the case of ListPaired), and\n c) be usable within the context of other container models (like History or\n LibraryFolder, etc.). I've tried to separate/extract classes in order to\n handle those three situations, but it's proven difficult to do in a simple,\n readable manner.\n- Ideally, histories and libraries would inherit from the same server models as\n dataset collections do since they are (in essence) dataset collections themselves -\n making the whole nested structure simpler. This would be a large, error-prone\n refactoring and migration.\n\nMany of the classes and heirarchy are meant as extension points so, while the\nrelations and flow may be difficult to understand initially, they'll allow us to\nhandle the growth or flux dataset collection in the future (w/o actually implementing\nany YAGNI).\n\n*/\n//_________________________________________________________________________________________________ ELEMENTS\n/** @class mixin for Dataset collection elements.\n * When collection elements are passed from the API, the underlying element is\n * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).\n * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues\n * effectively changing a DCE from a container to a subclass (has a --> is a).\n */\nvar DatasetCollectionElementMixin = {\n /** default attributes used by elements in a dataset collection */\n defaults: {\n model_class: \"DatasetCollectionElement\",\n element_identifier: null,\n element_index: null,\n element_type: null\n },\n\n /** merge the attributes of the sub-object 'object' into this model */\n _mergeObject: function(attributes) {\n // if we don't preserve and correct ids here, the element id becomes the object id\n // and collision in backbone's _byId will occur and only\n _.extend(attributes, attributes.object, {\n element_id: attributes.id\n });\n delete attributes.object;\n return attributes;\n },\n\n /** override to merge this.object into this */\n constructor: function(attributes, options) {\n // console.debug( '\\t DatasetCollectionElement.constructor:', attributes, options );\n attributes = this._mergeObject(attributes);\n this.idAttribute = \"element_id\";\n Backbone.Model.apply(this, arguments);\n },\n\n /** when the model is fetched, merge this.object into this */\n parse: function(response, options) {\n var attributes = response;\n attributes = this._mergeObject(attributes);\n return attributes;\n }\n};\n\n/** @class Concrete class of Generic DatasetCollectionElement */\nvar DatasetCollectionElement = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(DatasetCollectionElementMixin)\n .extend({ _logNamespace: \"collections\" });\n\n//==============================================================================\n/** @class Base/Abstract Backbone collection for Generic DCEs. */\nvar DCECollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends DCECollection.prototype */ {\n _logNamespace: \"collections\",\n\n model: DatasetCollectionElement,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetCollectionElementCollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a dataset collection element that is a dataset (HDA).\n */\nvar DatasetDCE = DATASET_MODEL.DatasetAssociation.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends DatasetDCE.prototype */ {\n /** url fn */\n url: function() {\n // won't always be an hda\n if (!this.has(\"history_id\")) {\n console.warn(\"no endpoint for non-hdas within a collection yet\");\n // (a little silly since this api endpoint *also* points at hdas)\n return `${Galaxy.root}api/datasets`;\n }\n return `${Galaxy.root}api/histories/${this.get(\"history_id\")}/contents/${this.get(\"id\")}`;\n },\n\n defaults: _.extend(\n {},\n DATASET_MODEL.DatasetAssociation.prototype.defaults,\n DatasetCollectionElementMixin.defaults\n ),\n\n _downloadQueryParameters: function() {\n return `?to_ext=${this.get(\"file_ext\")}&hdca_id=${this.get(\n \"parent_hdca_id\"\n )}&element_identifier=${this.get(\"element_identifier\")}`;\n },\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually for now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t DatasetDCE.constructor:\", attributes, options);\n //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function() {\n return this.elements && this.elements.length;\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.get(\"element_identifier\");\n return [\"DatasetDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).\n */\nvar DatasetDCECollection = DCECollection.extend(\n /** @lends DatasetDCECollection.prototype */ {\n model: DatasetDCE,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//_________________________________________________________________________________________________ COLLECTIONS\n/** @class Backbone model for Dataset Collections.\n * The DC API returns an array of JSON objects under the attribute elements.\n * This model:\n * - removes that array/attribute ('elements') from the model,\n * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),\n * - passes that json onto the bbone collection\n * - caches the bbone collection in this.elements\n */\nvar DatasetCollection = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(BASE_MVC.SearchableModelMixin)\n .extend(\n /** @lends DatasetCollection.prototype */ {\n _logNamespace: \"collections\",\n\n /** default attributes for a model */\n defaults: {\n /* 'list', 'paired', or 'list:paired' */\n collection_type: null,\n //??\n deleted: false\n },\n\n /** Which class to use for elements */\n collectionClass: DCECollection,\n\n /** set up: create elements instance var and (on changes to elements) update them */\n initialize: function(model, options) {\n this.debug(`${this}(DatasetCollection).initialize:`, model, options, this);\n this.elements = this._createElementsModel();\n this.on(\"change:elements\", function() {\n this.log(\"change:elements\");\n //TODO: prob. better to update the collection instead of re-creating it\n this.elements = this._createElementsModel();\n });\n },\n\n /** move elements model attribute to full collection */\n _createElementsModel: function() {\n this.debug(`${this}._createElementsModel`, this.collectionClass, this.get(\"elements\"), this.elements);\n //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?\n var elements = this.get(\"elements\") || [];\n this.unset(\"elements\", { silent: true });\n var self = this;\n _.each(elements, (element, index) => {\n _.extend(element, {\n parent_hdca_id: self.get(\"id\")\n });\n });\n this.elements = new this.collectionClass(elements);\n //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );\n return this.elements;\n },\n\n // ........................................................................ common queries\n /** pass the elements back within the model json when this is serialized */\n toJSON: function() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n if (this.elements) {\n json.elements = this.elements.toJSON();\n }\n return json;\n },\n\n /** Is this collection in a 'ready' state no processing (for the collection) is left\n * to do on the server.\n */\n inReadyState: function() {\n var populated = this.get(\"populated\");\n return this.isDeletedOrPurged() || populated;\n },\n\n //TODO:?? the following are the same interface as DatasetAssociation - can we combine?\n /** Does the DC contain any elements yet? Is a fetch() required? */\n hasDetails: function() {\n return this.elements.length !== 0;\n },\n\n /** Given the filters, what models in this.elements would be returned? */\n getVisibleContents: function(filters) {\n // filters unused for now\n return this.elements;\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Is this collection deleted or purged? */\n isDeletedOrPurged: function() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n // ........................................................................ searchable\n /** searchable attributes for collections */\n searchAttributes: [\"name\", \"tags\"],\n\n // ........................................................................ misc\n /** String representation */\n toString: function() {\n var idAndName = [this.get(\"id\"), this.get(\"name\") || this.get(\"element_identifier\")];\n return `DatasetCollection(${idAndName.join(\",\")})`;\n }\n }\n );\n\n//==============================================================================\n/** Model for a DatasetCollection containing datasets (non-nested).\n */\nvar ListDatasetCollection = DatasetCollection.extend(\n /** @lends ListDatasetCollection.prototype */ {\n /** override since we know the collection will only contain datasets */\n collectionClass: DatasetDCECollection,\n\n /** String representation. */\n toString: function() {\n return `List${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).\n */\nvar PairDatasetCollection = ListDatasetCollection.extend(\n /** @lends PairDatasetCollection.prototype */ {\n /** String representation. */\n toString: function() {\n return `Pair${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//_________________________________________________________________________________________________ NESTED COLLECTIONS\n// this is where things get weird, man. Weird.\n//TODO: it might be possible to compact all the following...I think.\n//==============================================================================\n/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection\n * (a nested collection). Currently only list:paired.\n */\nvar NestedDCDCE = DatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedDCDCE.prototype */ {\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).\n */\nvar NestedDCDCECollection = DCECollection.extend(\n /** @lends NestedDCDCECollection.prototype */ {\n /** This is a collection of nested collections */\n model: NestedDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.\n */\nvar NestedPairDCDCE = PairDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedPairDCDCE.prototype */ {\n //TODO:?? possibly rename to NestedDatasetCollection?\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedPairDCDCE.constructor:\", attributes, options);\n //DatasetCollection.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedPairDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection for a backbone collection containing paired dataset collections.\n */\nvar NestedPairDCDCECollection = NestedDCDCECollection.extend(\n /** @lends PairDCDCECollection.prototype */ {\n /** We know this collection is composed of only nested pair collections */\n model: NestedPairDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedPairDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).\n */\nvar ListPairedDatasetCollection = DatasetCollection.extend(\n /** @lends ListPairedDatasetCollection.prototype */ {\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedPairDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListPairedDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a list dataset collection within a list:list dataset collection. */\nvar NestedListDCDCE = ListDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedListDCDCE.prototype */ {\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedListDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedListDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing list dataset collections. */\nvar NestedListDCDCECollection = NestedDCDCECollection.extend({\n /** We know this collection is composed of only nested pair collections */\n model: NestedListDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedListDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains other lists. */\nvar ListOfListsDatasetCollection = DatasetCollection.extend({\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedListDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n ListDatasetCollection: ListDatasetCollection,\n PairDatasetCollection: PairDatasetCollection,\n ListPairedDatasetCollection: ListPairedDatasetCollection,\n ListOfListsDatasetCollection: ListOfListsDatasetCollection\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/collection/collection-model.js"],"names":["DatasetCollectionElementMixin","defaults","model_class","element_identifier","element_index","element_type","_mergeObject","attributes","_","extend","object","element_id","id","options","this","idAttribute","apply","arguments","response","DatasetCollectionElement","Backbone","Model","_baseMvc2","default","LoggableMixin","_logNamespace","DCECollection","Collection","model","toString","length","join","DatasetDCE","_datasetModel2","DatasetAssociation","url","has","Galaxy","root","mixin","console","warn","prototype","_downloadQueryParameters","get","elementIdentifier","fileExt","constructor","debug","call","hasDetails","elements","DatasetDCECollection","DatasetCollection","SearchableModelMixin","collection_type","deleted","collectionClass","initialize","_createElementsModel","log","silent","unset","self","element","index","parent_hdca_id","toJSON","json","inReadyState","populated","isDeletedOrPurged","getVisibleContents","filters","parse","parsed","create_time","Date","update_time","delete","jQuery","when","save","undelete","searchAttributes","idAndName","ListDatasetCollection","PairDatasetCollection","NestedDCDCE","NestedPairDCDCE","NestedPairDCDCECollection","NestedDCDCECollection","ListPairedDatasetCollection","NestedListDCDCE","ListOfListsDatasetCollection","NestedListDCDCECollection"],"mappings":"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","file":"../../../scripts/mvc/collection/collection-model.js","sourcesContent":["import DATASET_MODEL from \"mvc/dataset/dataset-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/*\nNotes:\n\nTerminology:\n DatasetCollection/DC : a container of datasets or nested DatasetCollections\n Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection\n HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history\n\n\nThis all seems too complex unfortunately:\n\n- Terminology collision between DatasetCollections (DCs) and Backbone Collections.\n- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*\n either a dataset or a nested DC. This would make the hierarchy much taller. I've\n decided to merge the contained JSON with the DC element json - making the 'has a'\n relation into an 'is a' relation. This seems simpler to me and allowed a lot of\n DRY in both models and views, but may make tracking or tracing within these models\n more difficult (since DatasetCollectionElements are now *also* DatasetAssociations\n or DatasetCollections (nested)). This also violates the rule of thumb about\n favoring aggregation over inheritance.\n- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.\n These each should a) be usable on their own, b) be usable in the context of\n nesting within a collection model (at least in the case of ListPaired), and\n c) be usable within the context of other container models (like History or\n LibraryFolder, etc.). I've tried to separate/extract classes in order to\n handle those three situations, but it's proven difficult to do in a simple,\n readable manner.\n- Ideally, histories and libraries would inherit from the same server models as\n dataset collections do since they are (in essence) dataset collections themselves -\n making the whole nested structure simpler. This would be a large, error-prone\n refactoring and migration.\n\nMany of the classes and heirarchy are meant as extension points so, while the\nrelations and flow may be difficult to understand initially, they'll allow us to\nhandle the growth or flux dataset collection in the future (w/o actually implementing\nany YAGNI).\n\n*/\n//_________________________________________________________________________________________________ ELEMENTS\n/** @class mixin for Dataset collection elements.\n * When collection elements are passed from the API, the underlying element is\n * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).\n * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues\n * effectively changing a DCE from a container to a subclass (has a --> is a).\n */\nvar DatasetCollectionElementMixin = {\n /** default attributes used by elements in a dataset collection */\n defaults: {\n model_class: \"DatasetCollectionElement\",\n element_identifier: null,\n element_index: null,\n element_type: null\n },\n\n /** merge the attributes of the sub-object 'object' into this model */\n _mergeObject: function(attributes) {\n // if we don't preserve and correct ids here, the element id becomes the object id\n // and collision in backbone's _byId will occur and only\n _.extend(attributes, attributes.object, {\n element_id: attributes.id\n });\n delete attributes.object;\n return attributes;\n },\n\n /** override to merge this.object into this */\n constructor: function(attributes, options) {\n // console.debug( '\\t DatasetCollectionElement.constructor:', attributes, options );\n attributes = this._mergeObject(attributes);\n this.idAttribute = \"element_id\";\n Backbone.Model.apply(this, arguments);\n },\n\n /** when the model is fetched, merge this.object into this */\n parse: function(response, options) {\n var attributes = response;\n attributes = this._mergeObject(attributes);\n return attributes;\n }\n};\n\n/** @class Concrete class of Generic DatasetCollectionElement */\nvar DatasetCollectionElement = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(DatasetCollectionElementMixin)\n .extend({ _logNamespace: \"collections\" });\n\n//==============================================================================\n/** @class Base/Abstract Backbone collection for Generic DCEs. */\nvar DCECollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends DCECollection.prototype */ {\n _logNamespace: \"collections\",\n\n model: DatasetCollectionElement,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetCollectionElementCollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a dataset collection element that is a dataset (HDA).\n */\nvar DatasetDCE = DATASET_MODEL.DatasetAssociation.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends DatasetDCE.prototype */ {\n /** url fn */\n url: function() {\n // won't always be an hda\n if (!this.has(\"history_id\")) {\n console.warn(\"no endpoint for non-hdas within a collection yet\");\n // (a little silly since this api endpoint *also* points at hdas)\n return `${Galaxy.root}api/datasets`;\n }\n return `${Galaxy.root}api/histories/${this.get(\"history_id\")}/contents/${this.get(\"id\")}`;\n },\n\n defaults: _.extend(\n {},\n DATASET_MODEL.DatasetAssociation.prototype.defaults,\n DatasetCollectionElementMixin.defaults\n ),\n\n _downloadQueryParameters: function() {\n var fileExt = this.get(\"file_ext\");\n var elementIdentifier = this.get(\"element_identifier\");\n var parentHdcaId = this.get(\"parent_hdca_id\");\n return `?to_ext=${fileExt}&hdca_id=${parentHdcaId}&element_identifier=${elementIdentifier}`;\n },\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually for now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t DatasetDCE.constructor:\", attributes, options);\n //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function() {\n return this.elements && this.elements.length;\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.get(\"element_identifier\");\n return `DatasetDCE({objStr})`;\n }\n }\n )\n);\n\n//==============================================================================\n/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).\n */\nvar DatasetDCECollection = DCECollection.extend(\n /** @lends DatasetDCECollection.prototype */ {\n model: DatasetDCE,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//_________________________________________________________________________________________________ COLLECTIONS\n/** @class Backbone model for Dataset Collections.\n * The DC API returns an array of JSON objects under the attribute elements.\n * This model:\n * - removes that array/attribute ('elements') from the model,\n * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),\n * - passes that json onto the bbone collection\n * - caches the bbone collection in this.elements\n */\nvar DatasetCollection = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(BASE_MVC.SearchableModelMixin)\n .extend(\n /** @lends DatasetCollection.prototype */ {\n _logNamespace: \"collections\",\n\n /** default attributes for a model */\n defaults: {\n /* 'list', 'paired', or 'list:paired' */\n collection_type: null,\n //??\n deleted: false\n },\n\n /** Which class to use for elements */\n collectionClass: DCECollection,\n\n /** set up: create elements instance var and (on changes to elements) update them */\n initialize: function(model, options) {\n this.debug(`${this}(DatasetCollection).initialize:`, model, options, this);\n this.elements = this._createElementsModel();\n this.on(\"change:elements\", function() {\n this.log(\"change:elements\");\n //TODO: prob. better to update the collection instead of re-creating it\n this.elements = this._createElementsModel();\n });\n },\n\n /** move elements model attribute to full collection */\n _createElementsModel: function() {\n this.debug(`${this}._createElementsModel`, this.collectionClass, this.get(\"elements\"), this.elements);\n //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?\n var elements = this.get(\"elements\") || [];\n this.unset(\"elements\", { silent: true });\n var self = this;\n _.each(elements, (element, index) => {\n _.extend(element, {\n parent_hdca_id: self.get(\"id\")\n });\n });\n this.elements = new this.collectionClass(elements);\n //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );\n return this.elements;\n },\n\n // ........................................................................ common queries\n /** pass the elements back within the model json when this is serialized */\n toJSON: function() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n if (this.elements) {\n json.elements = this.elements.toJSON();\n }\n return json;\n },\n\n /** Is this collection in a 'ready' state no processing (for the collection) is left\n * to do on the server.\n */\n inReadyState: function() {\n var populated = this.get(\"populated\");\n return this.isDeletedOrPurged() || populated;\n },\n\n //TODO:?? the following are the same interface as DatasetAssociation - can we combine?\n /** Does the DC contain any elements yet? Is a fetch() required? */\n hasDetails: function() {\n return this.elements.length !== 0;\n },\n\n /** Given the filters, what models in this.elements would be returned? */\n getVisibleContents: function(filters) {\n // filters unused for now\n return this.elements;\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Is this collection deleted or purged? */\n isDeletedOrPurged: function() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n // ........................................................................ searchable\n /** searchable attributes for collections */\n searchAttributes: [\"name\", \"tags\"],\n\n // ........................................................................ misc\n /** String representation */\n toString: function() {\n var idAndName = [this.get(\"id\"), this.get(\"name\") || this.get(\"element_identifier\")];\n return `DatasetCollection(${idAndName.join(\",\")})`;\n }\n }\n );\n\n//==============================================================================\n/** Model for a DatasetCollection containing datasets (non-nested).\n */\nvar ListDatasetCollection = DatasetCollection.extend(\n /** @lends ListDatasetCollection.prototype */ {\n /** override since we know the collection will only contain datasets */\n collectionClass: DatasetDCECollection,\n\n /** String representation. */\n toString: function() {\n return `List${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).\n */\nvar PairDatasetCollection = ListDatasetCollection.extend(\n /** @lends PairDatasetCollection.prototype */ {\n /** String representation. */\n toString: function() {\n return `Pair${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//_________________________________________________________________________________________________ NESTED COLLECTIONS\n// this is where things get weird, man. Weird.\n//TODO: it might be possible to compact all the following...I think.\n//==============================================================================\n/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection\n * (a nested collection). Currently only list:paired.\n */\nvar NestedDCDCE = DatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedDCDCE.prototype */ {\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).\n */\nvar NestedDCDCECollection = DCECollection.extend(\n /** @lends NestedDCDCECollection.prototype */ {\n /** This is a collection of nested collections */\n model: NestedDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.\n */\nvar NestedPairDCDCE = PairDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedPairDCDCE.prototype */ {\n //TODO:?? possibly rename to NestedDatasetCollection?\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedPairDCDCE.constructor:\", attributes, options);\n //DatasetCollection.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedPairDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection for a backbone collection containing paired dataset collections.\n */\nvar NestedPairDCDCECollection = NestedDCDCECollection.extend(\n /** @lends PairDCDCECollection.prototype */ {\n /** We know this collection is composed of only nested pair collections */\n model: NestedPairDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedPairDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).\n */\nvar ListPairedDatasetCollection = DatasetCollection.extend(\n /** @lends ListPairedDatasetCollection.prototype */ {\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedPairDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListPairedDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a list dataset collection within a list:list dataset collection. */\nvar NestedListDCDCE = ListDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedListDCDCE.prototype */ {\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedListDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedListDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing list dataset collections. */\nvar NestedListDCDCECollection = NestedDCDCECollection.extend({\n /** We know this collection is composed of only nested pair collections */\n model: NestedListDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedListDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains other lists. */\nvar ListOfListsDatasetCollection = DatasetCollection.extend({\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedListDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n ListDatasetCollection: ListDatasetCollection,\n PairDatasetCollection: PairDatasetCollection,\n ListPairedDatasetCollection: ListPairedDatasetCollection,\n ListOfListsDatasetCollection: ListOfListsDatasetCollection\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/collection/collection-view.js.map b/static/maps/mvc/collection/collection-view.js.map
index 0a97683d0c17..f1e05083a6d0 100644
--- a/static/maps/mvc/collection/collection-view.js.map
+++ b/static/maps/mvc/collection/collection-view.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/collection/collection-view.js"],"names":["_super","_listView2","default","ModelListPanel","CollectionView","extend","_logNamespace","className","prototype","DatasetDCEViewClass","_collectionLi2","DatasetDCEListItemView","NestedDCDCEViewClass","NestedDCDCEListItemView","modelCollectionKey","initialize","attributes","call","this","logNamespace","linkTarget","panelStack","parentName","foldoutStyle","Galaxy","root","model","id","console","log","_queueNewRender","$newRender","speed","undefined","fxSpeed","panel","trigger","getVisibleContents","get","_swapNewRender","TypeError","_getItemViewOptions","options","_","_getItemViewClass","hasUser","_setUpItemViewListeners","view","drilldown","v","_collapseDrilldownPanel","push","$","add","$list","$el","append","_expandDrilldownPanel","pop","render","events","click .navigation .back","close","event","remove","toString","templates","_baseMvc2","wrapTemplate","_localization2","controlsTemplate","controls","ListCollectionView","clone","PairCollectionView","ListOfPairsCollectionView","ListOfListsCollectionView","foldoutPanelClass"],"mappings":"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","file":"../../../scripts/mvc/collection/collection-view.js","sourcesContent":["import LIST_VIEW from \"mvc/list/list-view\";\nimport DC_MODEL from \"mvc/collection/collection-model\";\nimport DC_LI from \"mvc/collection/collection-li\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"collections\";\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a dataset collection.\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar CollectionView = _super.extend(\n /** @lends CollectionView.prototype */ {\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n _logNamespace: logNamespace,\n\n className: `${_super.prototype.className} dataset-collection-panel`,\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"elements\",\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n this.hasUser = attributes.hasUser;\n /** A stack of panels that currently cover or hide this panel */\n this.panelStack = [];\n /** The text of the link to go back to the panel containing this one */\n this.parentName = attributes.parentName;\n /** foldout or drilldown */\n this.foldoutStyle = attributes.foldoutStyle || \"foldout\";\n this.downloadUrl = `${Galaxy.root}api/dataset_collections/${this.model.attributes.id}/download`;\n console.log(this);\n },\n\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n // TODO: jquery@1.12 doesn't change display when the elem has display: flex\n // this causes display: block for those elems after the use of show/hide animations\n // animations are removed from this view for now until fixed\n panel._swapNewRender($newRender);\n panel.trigger(\"rendered\", panel);\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, use model.getVisibleContents */\n _filterCollection: function() {\n //TODO: should *not* be model.getVisibleContents - visibility is not model related\n return this.model.getVisibleContents();\n },\n\n /** override to return proper view class based on element_type */\n _getItemViewClass: function(model) {\n //this.debug( this + '._getItemViewClass:', model );\n //TODO: subclasses use DCEViewClass - but are currently unused - decide\n switch (model.get(\"element_type\")) {\n case \"hda\":\n return this.DatasetDCEViewClass;\n case \"dataset_collection\":\n return this.NestedDCDCEViewClass;\n }\n throw new TypeError(\"Unknown element type:\", model.get(\"element_type\"));\n },\n\n /** override to add link target and anon */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n hasUser: this.hasUser,\n //TODO: could move to only nested: list:paired\n foldoutStyle: this.foldoutStyle\n });\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n\n // use pub-sub to: handle drilldown expansion and collapse\n panel.listenTo(view, {\n \"expanded:drilldown\": function(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n return this;\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$(\"> .controls\")\n .add(this.$list())\n .hide();\n drilldown.parentName = this.model.get(\"name\");\n this.$el.append(drilldown.render().$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function(drilldown) {\n this.panelStack.pop();\n this.render();\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .navigation .back\": \"close\"\n },\n\n /** close/remove this collection panel */\n close: function(event) {\n this.remove();\n this.trigger(\"close\");\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `CollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nCollectionView.prototype.templates = (() => {\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\"\n ],\n \"collection\"\n );\n\n return _.extend(_.clone(_super.prototype.templates), {\n controls: controlsTemplate\n });\n})();\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionView = CollectionView.extend(\n /** @lends ListCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionView = ListCollectionView.extend(\n /** @lends PairCollectionView.prototype */ {\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `PairCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListOfPairsCollectionView = CollectionView.extend(\n /** @lends ListOfPairsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfPairsCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionView = CollectionView.extend({\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n /** string rep */\n toString: function() {\n return `ListOfListsCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n});\n\n//==============================================================================\nexport default {\n CollectionView: CollectionView,\n ListCollectionView: ListCollectionView,\n PairCollectionView: PairCollectionView,\n ListOfPairsCollectionView: ListOfPairsCollectionView,\n ListOfListsCollectionView: ListOfListsCollectionView\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/collection/collection-view.js"],"names":["_super","_listView2","default","ModelListPanel","CollectionView","extend","_logNamespace","className","prototype","DatasetDCEViewClass","_collectionLi2","DatasetDCEListItemView","NestedDCDCEViewClass","NestedDCDCEListItemView","modelCollectionKey","initialize","attributes","call","this","logNamespace","linkTarget","panelStack","parentName","foldoutStyle","Galaxy","root","model","id","_queueNewRender","$newRender","speed","undefined","fxSpeed","panel","_swapNewRender","_filterCollection","downloadUrl","getVisibleContents","get","trigger","TypeError","_getItemViewOptions","options","_","_getItemViewClass","hasUser","_setUpItemViewListeners","view","drilldown","v","_collapseDrilldownPanel","push","$","add","$list","$el","append","_expandDrilldownPanel","pop","render","events","click .navigation .back","close","event","remove","toString","templates","_baseMvc2","wrapTemplate","_localization2","controlsTemplate","controls","ListCollectionView","clone","PairCollectionView","ListOfPairsCollectionView","ListOfListsCollectionView","foldoutPanelClass"],"mappings":"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","file":"../../../scripts/mvc/collection/collection-view.js","sourcesContent":["import LIST_VIEW from \"mvc/list/list-view\";\nimport DC_MODEL from \"mvc/collection/collection-model\";\nimport DC_LI from \"mvc/collection/collection-li\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"collections\";\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a dataset collection.\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar CollectionView = _super.extend(\n /** @lends CollectionView.prototype */ {\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n _logNamespace: logNamespace,\n\n className: `${_super.prototype.className} dataset-collection-panel`,\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"elements\",\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n this.hasUser = attributes.hasUser;\n /** A stack of panels that currently cover or hide this panel */\n this.panelStack = [];\n /** The text of the link to go back to the panel containing this one */\n this.parentName = attributes.parentName;\n /** foldout or drilldown */\n this.foldoutStyle = attributes.foldoutStyle || \"foldout\";\n this.downloadUrl = `${Galaxy.root}api/dataset_collections/${this.model.attributes.id}/download`;\n },\n\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n // TODO: jquery@1.12 doesn't change display when the elem has display: flex\n // this causes display: block for those elems after the use of show/hide animations\n // animations are removed from this view for now until fixed\n panel._swapNewRender($newRender);\n panel.trigger(\"rendered\", panel);\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, use model.getVisibleContents */\n _filterCollection: function() {\n //TODO: should *not* be model.getVisibleContents - visibility is not model related\n return this.model.getVisibleContents();\n },\n\n /** override to return proper view class based on element_type */\n _getItemViewClass: function(model) {\n //this.debug( this + '._getItemViewClass:', model );\n //TODO: subclasses use DCEViewClass - but are currently unused - decide\n switch (model.get(\"element_type\")) {\n case \"hda\":\n return this.DatasetDCEViewClass;\n case \"dataset_collection\":\n return this.NestedDCDCEViewClass;\n }\n throw new TypeError(\"Unknown element type:\", model.get(\"element_type\"));\n },\n\n /** override to add link target and anon */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n hasUser: this.hasUser,\n //TODO: could move to only nested: list:paired\n foldoutStyle: this.foldoutStyle\n });\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n\n // use pub-sub to: handle drilldown expansion and collapse\n panel.listenTo(view, {\n \"expanded:drilldown\": function(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n return this;\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$(\"> .controls\")\n .add(this.$list())\n .hide();\n drilldown.parentName = this.model.get(\"name\");\n this.$el.append(drilldown.render().$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function(drilldown) {\n this.panelStack.pop();\n this.render();\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .navigation .back\": \"close\"\n },\n\n /** close/remove this collection panel */\n close: function(event) {\n this.remove();\n this.trigger(\"close\");\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `CollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nCollectionView.prototype.templates = (() => {\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\n `;\n\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: BASE_MVC.wrapTemplate(\n [\n // add a warning when hidden\n \"<% if( !dataset.visible ){ %>\",\n '
',\n _l(\"This dataset has been hidden\"),\n \"
\",\n \"<% } %>\"\n ],\n \"dataset\"\n )\n });\n\n return _.extend({}, _super.prototype.templates, {\n titleBar: titleBarTemplate,\n warnings: warnings\n });\n})();\n\n//==============================================================================\nexport default {\n HDAListItemView: HDAListItemView\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/hdca-li-edit.js.map b/static/maps/mvc/history/hdca-li-edit.js.map
index 198c4435af59..66c61e4631fe 100644
--- a/static/maps/mvc/history/hdca-li-edit.js.map
+++ b/static/maps/mvc/history/hdca-li-edit.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/hdca-li-edit.js"],"names":["_super","_hdcaLi2","default","HDCAListItemView","HDCAListItemEdit","extend","_getFoldoutPanelClass","this","model","get","_collectionViewEdit2","ListCollectionViewEdit","PairCollectionViewEdit","ListOfListsCollectionViewEdit","TypeError","log","prototype","_renderPrimaryActions","_renderDeleteButton","self","deleted","_faIconButton2","title","_localization2","classes","faIcon","disabled","onclick","$el","find","trigger","toString"],"mappings":"wTAMIA,EAASC,EAAAC,QAAQC,iBAGjBC,EAAmBJ,EAAOK,QAMtBC,sBAAuB,WACnB,OAAQC,KAAKC,MAAMC,IAAI,oBACnB,IAAK,OACD,OAAOC,EAAAR,QAAaS,uBACxB,IAAK,SACD,OAAOD,EAAAR,QAAaU,uBAfxC,IAAA,cACa,OAAAF,EAAAR,QAAQC,8BACrB,IAAA,YAiBoB,OAAOO,EAAAR,QAAaW,8BAdpC,MAAA,IAAAC,UAAA,2BAAyCP,KAAAC,MAAAC,IAAA,qBAKrCH,sBAAuB,WAGX,OAFRC,KAAAQ,IAAQR,KAAR,0BAEQP,EAAAgB,UAAOC,sBAAaN,KAAAA,MAAAA,QAAAA,KAApBO,yBAIAA,oBAAO,WACX,IAAAC,EAAKZ,KACDa,EAAAb,KAAOC,MAAAC,IAAA,WARf,OAAA,EAAAY,EAAAnB,UAUAoB,MAAUR,GAAJ,EAAAS,EAAArB,SAAA,0CAAwD,EAAAqB,EAAArB,SAAA,UAhB7BsB,QAAA,aAkC7BC,OAAQ,WAfhBC,SAAAN,EACAO,QAAA,WAEIR,EAAAS,IAAAC,KAAA,wBAAAC,QAAA,YACAX,EAAAX,MAAA,aAOAuB,SAAIX,WAEAE,MAAAA,qBADGf,KAAAC,MAAA,GAAAD,KAAaC,MAAA,cAChBc,kBAOIH,iBAAAA","file":"../../../scripts/mvc/history/hdca-li-edit.js","sourcesContent":["import HDCA_LI from \"mvc/history/hdca-li\";\nimport DC_VIEW_EDIT from \"mvc/collection/collection-view-edit\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = HDCA_LI.HDCAListItemView;\n/** @class Editing view for HistoryDatasetCollectionAssociation.\n */\nvar HDCAListItemEdit = _super.extend(\n /** @lends HDCAListItemEdit.prototype */ {\n /** logger used to record this.log messages, commonly set to console */\n //logger : console,\n\n /** Override to return editable versions of the collection panels */\n _getFoldoutPanelClass: function() {\n switch (this.model.get(\"collection_type\")) {\n case \"list\":\n return DC_VIEW_EDIT.ListCollectionViewEdit;\n case \"paired\":\n return DC_VIEW_EDIT.PairCollectionViewEdit;\n case \"list:paired\":\n return DC_VIEW_EDIT.ListOfPairsCollectionViewEdit;\n case \"list:list\":\n return DC_VIEW_EDIT.ListOfListsCollectionViewEdit;\n }\n throw new TypeError(`Uknown collection_type: ${this.model.get(\"collection_type\")}`);\n },\n\n // ......................................................................... delete\n /** In this override, add the delete button. */\n _renderPrimaryActions: function() {\n this.log(`${this}._renderPrimaryActions`);\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions.call(this).concat([this._renderDeleteButton()]);\n },\n\n /** Render icon-button to delete this collection. */\n _renderDeleteButton: function() {\n var self = this;\n var deleted = this.model.get(\"deleted\");\n return faIconButton({\n title: deleted ? _l(\"Dataset collection is already deleted\") : _l(\"Delete\"),\n classes: \"delete-btn\",\n faIcon: \"fa-times\",\n disabled: deleted,\n onclick: function() {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n self.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n self.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDCAListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n HDCAListItemEdit: HDCAListItemEdit\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/history/hdca-li-edit.js"],"names":["_super","_hdcaLi2","default","HDCAListItemView","HDCAListItemEdit","extend","_getFoldoutPanelClass","collectionType","this","model","get","_collectionViewEdit2","ListCollectionViewEdit","PairCollectionViewEdit","ListOfPairsCollectionViewEdit","ListOfListsCollectionViewEdit","TypeError","_renderPrimaryActions","log","prototype","_renderDeleteButton","_this","deleted","_faIconButton2","title","_localization2","classes","faIcon","disabled","onclick","trigger","toString"],"mappings":"wTAMIA,EAASC,EAAAC,QAAQC,iBAGjBC,EAAmBJ,EAAOK,QAMtBC,sBAAuB,WACnB,IAAIC,EAAiBC,KAAKC,MAAMC,IAAI,mBACpC,OAAQH,GACJ,IAAK,OACD,OAAOI,EAAAT,QAAaU,uBACxB,IAAK,SAfrB,OAAAD,EAAAT,QAAAW,uBACIb,IAAS,cACb,OAAAW,EAAAT,QAAAY,8BAiBgB,IAAK,YAfjBV,OAAmBJ,EAAAA,QAAAe,8BAEf,MAAA,IAAAC,UAAA,4BAAAT,IAKIU,sBAAIV,WAGI,OAFRC,KAAAU,IAAQX,KAAR,0BAEQP,EAAAmB,UAAOF,sBAAaL,KAAAA,MAAAA,QAAAA,KAApBQ,yBAIAA,oBAAO,WAAA,IAAAC,EAAAb,KACXc,EAAKd,KAAAC,MAALC,IAAA,WACI,OAAA,EAAAa,EAAArB,UARRsB,MAAAF,GAAA,EAAAG,EAAAvB,SAAA,0CAAA,EAAAuB,EAAAvB,SAAA,UAUAwB,QAAUV,aAjBuBW,OAAA,WAmC7BC,SAAUN,EAflBO,QAAA,WAEAZ,EAAAA,IAAAA,KAAuB,wBAAAa,QAAW,YAC9BT,EAAAZ,MAAA,aAM4BsB,SAAA,WAC5B,MAAA,qBAiBkBvB,KAAKC,MAAL,GAAgBD,KAAKC,MAAU,cAjBjD,kBAOQL,iBAAAA","file":"../../../scripts/mvc/history/hdca-li-edit.js","sourcesContent":["import HDCA_LI from \"mvc/history/hdca-li\";\nimport DC_VIEW_EDIT from \"mvc/collection/collection-view-edit\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = HDCA_LI.HDCAListItemView;\n/** @class Editing view for HistoryDatasetCollectionAssociation.\n */\nvar HDCAListItemEdit = _super.extend(\n /** @lends HDCAListItemEdit.prototype */ {\n /** logger used to record this.log messages, commonly set to console */\n //logger : console,\n\n /** Override to return editable versions of the collection panels */\n _getFoldoutPanelClass: function() {\n var collectionType = this.model.get(\"collection_type\");\n switch (collectionType) {\n case \"list\":\n return DC_VIEW_EDIT.ListCollectionViewEdit;\n case \"paired\":\n return DC_VIEW_EDIT.PairCollectionViewEdit;\n case \"list:paired\":\n return DC_VIEW_EDIT.ListOfPairsCollectionViewEdit;\n case \"list:list\":\n return DC_VIEW_EDIT.ListOfListsCollectionViewEdit;\n }\n throw new TypeError(`Unknown collection_type: ${collectionType}`);\n },\n\n // ......................................................................... delete\n /** In this override, add the delete button. */\n _renderPrimaryActions: function() {\n this.log(`${this}._renderPrimaryActions`);\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions.call(this).concat([this._renderDeleteButton()]);\n },\n\n /** Render icon-button to delete this collection. */\n _renderDeleteButton: function() {\n var deleted = this.model.get(\"deleted\");\n return faIconButton({\n title: deleted ? _l(\"Dataset collection is already deleted\") : _l(\"Delete\"),\n classes: \"delete-btn\",\n faIcon: \"fa-times\",\n disabled: deleted,\n onclick: () => {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n this.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n this.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDCAListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n HDCAListItemEdit: HDCAListItemEdit\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/hdca-li.js.map b/static/maps/mvc/history/hdca-li.js.map
index 845368abc522..bdcd4585d300 100644
--- a/static/maps/mvc/history/hdca-li.js.map
+++ b/static/maps/mvc/history/hdca-li.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/hdca-li.js"],"names":["_super","_collectionLi2","default","DCListItemView","HDCAListItemView","extend","className","prototype","_setUpListeners","call","this","listenTo","model","change:tags change:populated change:visible","options","render","_getFoldoutPanelClass","get","_collectionView2","ListCollectionView","PairCollectionView","ListOfPairsCollectionView","TypeError","_swapNewRender","$newRender","state","_states2","OK","RUNNING","$el","addClass","toString","templates","warnings","_","hidden","_baseMvc2","_localization2","titleBarTemplate","titleBar"],"mappings":"gVAOIA,EAASC,EAAAC,QAAMC,eAGfC,EAAmBJ,EAAOK,QAEtBC,UAAcN,EAAOO,UAAUD,UAA/B,mBAGAE,gBAAiB,WACbR,EAAOO,UAAUC,gBAAgBC,KAAKC,MACtCA,KAAKC,SAASD,KAAKE,OACfC,8CAA+C,SAASD,EAAOE,GAC3DJ,KAAKK,aAXzBC,sBAAA,WAkBY,OAAQN,KAAKE,MAAMK,IAAI,oBAhB/Bb,IAAAA,OACA,OAAAc,EAAAhB,QAAAiB,mBACIb,IAAcN,SAkBF,OAAOkB,EAAAhB,QAAQkB,mBAhB3B,IAAA,cACAZ,OAAiBU,EAAAhB,QAAAmB,0BACbrB,IAAOO,YACFI,OAASO,EAAAhB,QAAKU,0BAEX,MAAA,IAAAU,UAAA,2BAAAZ,KAAAE,MAAAK,IAAA,qBAqBZM,eAAgB,SAASC,GAhBzBxB,EAAAO,UAAAgB,eAAAd,KAAAC,KAAAc,GAEI,IAAAC,EAAab,KAALA,MAAeK,IAAA,aAAvBS,EAAAxB,QAAAyB,GAAAD,EAAAxB,QAAA0B,QAIQ,OAFAlB,KAAAmB,IAAAC,SAAA,SAAOL,GAEPf,KAAAmB,KAJRE,SAAA,WAfiC,MAAA,qBAyBvBT,KAAJV,MAAIU,GAAJZ,KAAAE,MAAyC,cAzBd,OAgCjCR,EAAIqB,UAASO,UAAe,WAC5B,IAAAC,EAAAC,EAAA7B,UAAAL,EAAAO,UAAAyB,UAAAC,UACAE,OAAAC,EAAAlC,QAAS4B,cAlCwB,mCAuD7B,gDAhBR,EAAAO,EAAAnC,SAAA,mCACA,SACA6B,WAEI,gBAMZ3B,EAAiBG,EAAAA,QAAUyB,cAIX,6CACA,mCAJZ,sBAcA,kDACIM,mDAEI,SACA,+BAGA,0BACA,2FAMA,wCAUR,4DACIL,UACAM,YAFJ,UAvCJ,UA6CA,cACe,OAPJL,EAAE7B,UAAWL,EAAOO,UAAUyB,WACjCC,SAAUA,EACVM,SAAUD,IA1DsB,cAgEpClC,iBAAkBA","file":"../../../scripts/mvc/history/hdca-li.js","sourcesContent":["import STATES from \"mvc/dataset/states\";\nimport DC_LI from \"mvc/collection/collection-li\";\nimport DC_VIEW from \"mvc/collection/collection-view\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DC_LI.DCListItemView;\n/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).\n */\nvar HDCAListItemView = _super.extend(\n /** @lends HDCAListItemView.prototype */ {\n className: `${_super.prototype.className} history-content`,\n\n /** event listeners */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n this.listenTo(this.model, {\n \"change:tags change:populated change:visible\": function(model, options) {\n this.render();\n }\n });\n },\n\n /** Override to provide the proper collections panels as the foldout */\n _getFoldoutPanelClass: function() {\n switch (this.model.get(\"collection_type\")) {\n case \"list\":\n return DC_VIEW.ListCollectionView;\n case \"paired\":\n return DC_VIEW.PairCollectionView;\n case \"list:paired\":\n return DC_VIEW.ListOfPairsCollectionView;\n case \"list:list\":\n return DC_VIEW.ListOfListsCollectionView;\n }\n throw new TypeError(`Uknown collection_type: ${this.model.get(\"collection_type\")}`);\n },\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n //TODO: model currently has no state\n var state = !this.model.get(\"populated\") ? STATES.RUNNING : STATES.OK;\n //if( this.model.has( 'state' ) ){\n this.$el.addClass(`state-${state}`);\n //}\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDCAListItemView(${modelString})`;\n }\n }\n);\n\n/** underscore templates */\nHDCAListItemView.prototype.templates = (() => {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: BASE_MVC.wrapTemplate(\n [\n // add a warning when hidden\n \"<% if( !collection.visible ){ %>\",\n '
',\n _l(\"This collection has been hidden\"),\n \"
\",\n \"<% } %>\"\n ],\n \"collection\"\n )\n });\n\n // could steal this from hda-base (or use mixed content)\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n // adding the hid display to the title\n '
',\n '',\n '
',\n //TODO: remove whitespace and use margin-right\n '<%- collection.hid %> ',\n '<%- collection.name %>',\n \"
\n `;\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n HDCAListItemView: HDCAListItemView\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/hdca-model.js.map b/static/maps/mvc/history/hdca-model.js.map
index 85924a60435e..f0bddd8b7bc5 100644
--- a/static/maps/mvc/history/hdca-model.js.map
+++ b/static/maps/mvc/history/hdca-model.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/hdca-model.js"],"names":["buildHDCASave","_super","attributes","options","ListDC","this","isNew","url","urlRoot","get","hcontentMixin","call","ListDatasetCollection","_historyContentModel2","default","HistoryContentMixin","_collectionModel2","PairDC","PairDatasetCollection","ListPairedDC","ListPairedDatasetCollection","ListOfListsDC","ListOfListsDatasetCollection","HistoryListDatasetCollection","extend","defaults","_","clone","prototype","save","toString","HistoryPairDatasetCollection","history_content_type","collection_type","HistoryListPairedDatasetCollection","model_class","HistoryListOfListsDatasetCollection","join"],"mappings":"yNAsBA,SAASA,EAAcC,GACnB,OAAO,SAAeC,EAAYC,GARlCC,OASQC,KAAKC,WACLH,EAAUA,OACFI,IAASF,KAAKG,QAAUH,KAAKI,IAAI,cAAzC,aACAP,EAAaA,OAdrBQ,KAAgB,sBAEhBN,EAASO,KAAAN,KAAAH,EAASU,uEAFlBF,QAAgBG,EAAAC,QAAgBC,qBAEhCX,EAASY,EAAAF,QAASF,sBAClBK,EAASD,EAAAF,QAASI,sBAClBC,EAAeH,EAAAF,QAASM,4BACxBC,EAAgBL,EAAAF,QAASQ,6BAI7BC,EAA+BnB,EAAAoB,OAAAd,GAAAc,QAEvBC,SAAIC,EAAAF,OAAAE,EAAJC,MAAkBvB,EAAAwB,UAAAH,WACdtB,qBAAUA,qBACVA,gBAAA,OACAD,YAAAA,wCAIP2B,KARD7B,EAAAI,EAAAwB,UAAAC,MAWJC,SAAA,WACA,MAAA,UAAA1B,EAAAwB,UAAAE,SAAAnB,KAAAN,SAwBI0B,EAA+Bd,EAAOO,OAAOd,GAAec,QAbxDK,SAAM7B,EAAAA,OAAAA,EAAcI,MAAOwB,EAAAA,UARsBH,WAwB7CO,qBAAsB,qBAd1BC,gBAAA,SACAH,YAAU,wCAmBVD,KAAM7B,EAAciB,EAAOW,UAAUC,MAGrCC,SAAU,WACN,MAAA,UAAiBb,EAAOW,UAAUE,SAASnB,KAAKN,SAXG6B,EADNf,EAAAK,OAAAd,GAAAc,QAoBrDC,SAAUC,EAAEF,OAAOE,EAAEC,MAAMR,EAAaS,UAAUH,WAb9CO,qBAAA,qBACAH,gBAAM7B,cAeNmC,YAAa,wCAVZN,KAAA7B,EAAAmB,EAAAS,UAAAC,MAITC,SAAA,WACA,MAAA,UAAAX,EAAAS,UAAAE,SAAAnB,KAAAN,SAEiE+B,EADkBf,EAAAG,OAAAd,GAAAc,QAmB/EC,SAAUC,EAAEF,OAAOE,EAAEC,MAAMN,EAAcO,UAAUH,WAZnDO,qBAAA,qBACAH,gBAAM7B,YAcFmC,YAAa,wCAThBN,KAAA7B,EAAAqB,EAAAO,UAAAC,MAGLC,SAAA,WACA,OAAA,uCAAAzB,KAAAI,IAAA,QAAA,KAAA4B,KAAA,kBAEkEd,6BADmBA,EAmBjFQ,6BAA8BA,EAZ9BG,mCAAAA,EACAL,oCAAoBR","file":"../../../scripts/mvc/history/hdca-model.js","sourcesContent":["import DC_MODEL from \"mvc/collection/collection-model\";\nimport HISTORY_CONTENT from \"mvc/history/history-content-model\";\nimport _l from \"utils/localization\";\n\n/*==============================================================================\n\nModels for DatasetCollections contained within a history.\n\nTODO:\n these might be compactable to one class if some duplication with\n collection-model is used.\n\n==============================================================================*/\nvar hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;\n\nvar ListDC = DC_MODEL.ListDatasetCollection;\nvar PairDC = DC_MODEL.PairDatasetCollection;\nvar ListPairedDC = DC_MODEL.ListPairedDatasetCollection;\nvar ListOfListsDC = DC_MODEL.ListOfListsDatasetCollection;\n\n//==============================================================================\n/** Override to post to contents route w/o id. */\nfunction buildHDCASave(_super) {\n return function _save(attributes, options) {\n if (this.isNew()) {\n options = options || {};\n options.url = `${this.urlRoot + this.get(\"history_id\")}/contents`;\n attributes = attributes || {};\n attributes.type = \"dataset_collection\";\n }\n return _super.call(this, attributes, options);\n };\n}\n\n//==============================================================================\n/** @class Backbone model for List Dataset Collection within a History.\n */\nvar HistoryListDatasetCollection = ListDC.extend(hcontentMixin).extend(\n /** @lends HistoryListDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(ListDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for Pair Dataset Collection within a History.\n * @constructs\n */\nvar HistoryPairDatasetCollection = PairDC.extend(hcontentMixin).extend(\n /** @lends HistoryPairDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(PairDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(PairDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${PairDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for List of Pairs Dataset Collection within a History. */\nvar HistoryListPairedDatasetCollection = ListPairedDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListPairedDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListPairedDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListPairedDC.prototype.toString.call(this)}`;\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Lists Dataset Collection within a History. */\nvar HistoryListOfListsDatasetCollection = ListOfListsDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListOfListsDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListOfListsDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return [\"HistoryListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n HistoryListDatasetCollection: HistoryListDatasetCollection,\n HistoryPairDatasetCollection: HistoryPairDatasetCollection,\n HistoryListPairedDatasetCollection: HistoryListPairedDatasetCollection,\n HistoryListOfListsDatasetCollection: HistoryListOfListsDatasetCollection\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/history/hdca-model.js"],"names":["buildHDCASave","_super","attributes","options","ListDC","this","isNew","url","urlRoot","get","hcontentMixin","call","ListDatasetCollection","_historyContentModel2","default","HistoryContentMixin","_collectionModel2","PairDC","PairDatasetCollection","ListPairedDC","ListPairedDatasetCollection","ListOfListsDC","ListOfListsDatasetCollection","HistoryListDatasetCollection","extend","defaults","_","clone","prototype","save","toString","HistoryPairDatasetCollection","history_content_type","collection_type","HistoryListPairedDatasetCollection","model_class","HistoryListOfListsDatasetCollection"],"mappings":"yNAsBA,SAASA,EAAcC,GACnB,OAAO,SAAeC,EAAYC,GARlCC,OASQC,KAAKC,WACLH,EAAUA,OACFI,IAASF,KAAKG,QAAUH,KAAKI,IAAI,cAAzC,aACAP,EAAaA,OAdrBQ,KAAgB,sBAEhBN,EAASO,KAAAN,KAAAH,EAASU,uEAFlBF,QAAgBG,EAAAC,QAAgBC,qBAEhCX,EAASY,EAAAF,QAASF,sBAClBK,EAASD,EAAAF,QAASI,sBAClBC,EAAeH,EAAAF,QAASM,4BACxBC,EAAgBL,EAAAF,QAASQ,6BAI7BC,EAA+BnB,EAAAoB,OAAAd,GAAAc,QAEvBC,SAAIC,EAAAF,OAAAE,EAAJC,MAAkBvB,EAAAwB,UAAAH,WACdtB,qBAAUA,qBACVA,gBAAA,OACAD,YAAAA,wCAIP2B,KARD7B,EAAAI,EAAAwB,UAAAC,MAWJC,SAAA,WACA,MAAA,UAAA1B,EAAAwB,UAAAE,SAAAnB,KAAAN,SAwBI0B,EAA+Bd,EAAOO,OAAOd,GAAec,QAbxDK,SAAM7B,EAAAA,OAAAA,EAAcI,MAAOwB,EAAAA,UARsBH,WAwB7CO,qBAAsB,qBAd1BC,gBAAA,SACAH,YAAU,wCAmBVD,KAAM7B,EAAciB,EAAOW,UAAUC,MAGrCC,SAAU,WACN,MAAA,UAAiBb,EAAOW,UAAUE,SAASnB,KAAKN,SAXG6B,EADNf,EAAAK,OAAAd,GAAAc,QAoBrDC,SAAUC,EAAEF,OAAOE,EAAEC,MAAMR,EAAaS,UAAUH,WAb9CO,qBAAA,qBACAH,gBAAM7B,cAeNmC,YAAa,wCAVZN,KAAA7B,EAAAmB,EAAAS,UAAAC,MAITC,SAAA,WACA,MAAA,UAAAX,EAAAS,UAAAE,SAAAnB,KAAAN,SAEiE+B,EADkBf,EAAAG,OAAAd,GAAAc,QAmB/EC,SAAUC,EAAEF,OAAOE,EAAEC,MAAMN,EAAcO,UAAUH,WAZnDO,qBAAA,qBACAH,gBAAM7B,YAcFmC,YAAa,wCAThBN,KAAA7B,EAAAqB,EAAAO,UAAAC,MAGLC,SAAA,WACA,MAAA,uCAAAzB,KAAAI,IAAA,QAAA,kBAEkEc,6BADmBA,EAmBjFQ,6BAA8BA,EAZ9BG,mCAAAA,EACAL,oCAAoBR","file":"../../../scripts/mvc/history/hdca-model.js","sourcesContent":["import DC_MODEL from \"mvc/collection/collection-model\";\nimport HISTORY_CONTENT from \"mvc/history/history-content-model\";\nimport _l from \"utils/localization\";\n\n/*==============================================================================\n\nModels for DatasetCollections contained within a history.\n\nTODO:\n these might be compactable to one class if some duplication with\n collection-model is used.\n\n==============================================================================*/\nvar hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;\n\nvar ListDC = DC_MODEL.ListDatasetCollection;\nvar PairDC = DC_MODEL.PairDatasetCollection;\nvar ListPairedDC = DC_MODEL.ListPairedDatasetCollection;\nvar ListOfListsDC = DC_MODEL.ListOfListsDatasetCollection;\n\n//==============================================================================\n/** Override to post to contents route w/o id. */\nfunction buildHDCASave(_super) {\n return function _save(attributes, options) {\n if (this.isNew()) {\n options = options || {};\n options.url = `${this.urlRoot + this.get(\"history_id\")}/contents`;\n attributes = attributes || {};\n attributes.type = \"dataset_collection\";\n }\n return _super.call(this, attributes, options);\n };\n}\n\n//==============================================================================\n/** @class Backbone model for List Dataset Collection within a History.\n */\nvar HistoryListDatasetCollection = ListDC.extend(hcontentMixin).extend(\n /** @lends HistoryListDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(ListDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for Pair Dataset Collection within a History.\n * @constructs\n */\nvar HistoryPairDatasetCollection = PairDC.extend(hcontentMixin).extend(\n /** @lends HistoryPairDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(PairDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(PairDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${PairDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for List of Pairs Dataset Collection within a History. */\nvar HistoryListPairedDatasetCollection = ListPairedDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListPairedDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListPairedDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListPairedDC.prototype.toString.call(this)}`;\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Lists Dataset Collection within a History. */\nvar HistoryListOfListsDatasetCollection = ListOfListsDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListOfListsDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListOfListsDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `HistoryListOfListsDatasetCollection(${this.get(\"name\")})`;\n }\n});\n\n//==============================================================================\nexport default {\n HistoryListDatasetCollection: HistoryListDatasetCollection,\n HistoryPairDatasetCollection: HistoryPairDatasetCollection,\n HistoryListPairedDatasetCollection: HistoryListPairedDatasetCollection,\n HistoryListOfListsDatasetCollection: HistoryListOfListsDatasetCollection\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/history-content-model.js.map b/static/maps/mvc/history/history-content-model.js.map
index 0e5a8a0ad936..95b631536b97 100644
--- a/static/maps/mvc/history/history-content-model.js.map
+++ b/static/maps/mvc/history/history-content-model.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/history-content-model.js"],"names":["HistoryContentMixin","defaults","history_id","history_content_type","hid","visible","this","get","isVisible","includeDeleted","includeHidden","idAttribute","hidden","urlRoot","Galaxy","root","url","hide","options","jQuery","when","save","toString","join"],"mappings":"sQAOIA,GAEAC,UAEIC,WAAY,KAEZC,qBAAsB,KAEtBC,IAAK,KAELC,SAAS,GARbJ,YAAAA,UAIIE,OAAAA,WACA,OAAAG,KAAAC,IAAA,YASJC,UAAA,SAAAC,EAAAC,GACAC,IAAAA,GAAa,EAsBT,OANKF,IAAmBH,KAAKC,IAAI,aAAcD,KAAKC,IAAI,YAd5DC,GAAA,GAEAI,GAAQN,KAAWC,IAAA,aACfC,GAAQ,GAiBDA,GAMXK,QAAYC,OAAOC,KAAnB,iBAZIC,IAAA,WACIR,IAAAA,EAAAA,KAAAA,QAAAF,KAAAC,IAAA,cAAAC,aAAAF,KAAAC,IAAA,wBAAAC,KAAAF,KAAAC,IACH,MAEGC,OAAAA,GAmBRS,KAAM,SAASC,GAdf,OAAAZ,KAAAC,IAAA,WAGAM,KAAYC,MAAOC,SAAnB,GAAAG,GAFAC,OAAAC,QAKAJ,OAAAA,SAAKE,GACD,OAAAZ,KAAIU,IAAAA,WAGGA,OAAPI,OAeOd,KAAKe,MAAOhB,SAAS,GAAQa,IAThCI,SAAA,WACH,OAAAhB,KAAAC,IAAA,WAAAD,KAAAC,IAAA,OAAAD,KAAAC,IAAA,SAAAgB,KAAA,kBAMGvB,oBAAOmB","file":"../../../scripts/mvc/history/history-content-model.js","sourcesContent":["import STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Mixin for HistoryContents content (HDAs, HDCAs).\n */\nvar HistoryContentMixin = {\n /** default attributes for a model */\n defaults: {\n /** parent (containing) history */\n history_id: null,\n /** some content_type (HistoryContents can contain mixed model classes) */\n history_content_type: null,\n /** indicating when/what order the content was generated in the context of the history */\n hid: null,\n /** whether the user wants the content shown (visible) */\n visible: true\n },\n\n // ........................................................................ mixed content element\n // In order to be part of a MIXED bbone collection, we can't rely on the id\n // (which may collide btwn models of different classes)\n // Instead, use type_id which prefixes the history_content_type so the bbone collection can differentiate\n idAttribute: \"type_id\",\n\n // ........................................................................ common queries\n /** the more common alias of visible */\n hidden: function() {\n return !this.get(\"visible\");\n },\n\n //TODO: remove\n /** based on includeDeleted, includeHidden (gen. from the container control),\n * would this ds show in the list of ds's?\n * @param {Boolean} includeDeleted are we showing deleted hdas?\n * @param {Boolean} includeHidden are we showing hidden hdas?\n */\n isVisible: function(includeDeleted, includeHidden) {\n var isVisible = true;\n if (!includeDeleted && (this.get(\"deleted\") || this.get(\"purged\"))) {\n isVisible = false;\n }\n if (!includeHidden && !this.get(\"visible\")) {\n isVisible = false;\n }\n return isVisible;\n },\n\n // ........................................................................ ajax\n //TODO?: these are probably better done on the leaf classes\n /** history content goes through the 'api/histories' API */\n urlRoot: `${Galaxy.root}api/histories/`,\n\n /** full url spec. for this content */\n url: function() {\n var url = `${this.urlRoot + this.get(\"history_id\")}/contents/${this.get(\"history_content_type\")}s/${this.get(\n \"id\"\n )}`;\n return url;\n },\n\n /** save this content as not visible */\n hide: function(options) {\n if (!this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: false }, options);\n },\n /** save this content as visible */\n unhide: function(options) {\n if (this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: true }, options);\n },\n\n // ........................................................................ misc\n toString: function() {\n return [this.get(\"type_id\"), this.get(\"hid\"), this.get(\"name\")].join(\":\");\n }\n};\n\n//==============================================================================\nexport default {\n HistoryContentMixin: HistoryContentMixin\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/history/history-content-model.js"],"names":["HistoryContentMixin","defaults","history_id","history_content_type","hid","visible","this","get","isVisible","includeDeleted","includeHidden","idAttribute","hidden","urlRoot","Galaxy","root","url","historyContentId","historyContentType","hide","options","save","jQuery","when","unhide","historyId","join"],"mappings":"sQAOIA,GAEAC,UAEIC,WAAY,KAEZC,qBAAsB,KAEtBC,IAAK,KAELC,SAAS,GARbJ,YAAAA,UAIIE,OAAAA,WACA,OAAAG,KAAAC,IAAA,YASJC,UAAA,SAAAC,EAAAC,GACAC,IAAAA,GAAa,EAsBT,OANKF,IAAmBH,KAAKC,IAAI,aAAcD,KAAKC,IAAI,YAd5DC,GAAA,GAEAI,GAAQN,KAAWC,IAAA,aACfC,GAAQ,GAiBDA,GAMXK,QAAYC,OAAOC,KAAnB,iBAZIC,IAAA,WACIR,IAAAA,EAAAF,KAAAC,IAAA,wBAEJU,GADCX,KAAAC,IAAA,cACGD,KAAmBC,IAAKA,OACxBC,EAAAA,KAAAA,QAAAA,oCAAAU,EAAAV,KAAAS,EACH,OAAAD,GAILG,KAAA,SAAAC,GACA,OAAAd,KAAAC,IAAA,WAkBWD,KAAKe,MAAOhB,SAAS,GAASe,GAjBzCE,OAAAC,QAKIC,OAAA,SAAIN,GACJ,OAAAZ,KAAImB,IAAAA,WACAR,OAAAA,OAEJX,KAAOU,MAAPX,SAAA,GAAAe,IAIJD,SAAM,WACF,OAAIb,KAACC,IAAA,WAALD,KAA0BC,IAAA,OAAAD,KAAAC,IAAA,SAAAmB,KAAA,kBAM9BF,oBAAQxB","file":"../../../scripts/mvc/history/history-content-model.js","sourcesContent":["import STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Mixin for HistoryContents content (HDAs, HDCAs).\n */\nvar HistoryContentMixin = {\n /** default attributes for a model */\n defaults: {\n /** parent (containing) history */\n history_id: null,\n /** some content_type (HistoryContents can contain mixed model classes) */\n history_content_type: null,\n /** indicating when/what order the content was generated in the context of the history */\n hid: null,\n /** whether the user wants the content shown (visible) */\n visible: true\n },\n\n // ........................................................................ mixed content element\n // In order to be part of a MIXED bbone collection, we can't rely on the id\n // (which may collide btwn models of different classes)\n // Instead, use type_id which prefixes the history_content_type so the bbone collection can differentiate\n idAttribute: \"type_id\",\n\n // ........................................................................ common queries\n /** the more common alias of visible */\n hidden: function() {\n return !this.get(\"visible\");\n },\n\n //TODO: remove\n /** based on includeDeleted, includeHidden (gen. from the container control),\n * would this ds show in the list of ds's?\n * @param {Boolean} includeDeleted are we showing deleted hdas?\n * @param {Boolean} includeHidden are we showing hidden hdas?\n */\n isVisible: function(includeDeleted, includeHidden) {\n var isVisible = true;\n if (!includeDeleted && (this.get(\"deleted\") || this.get(\"purged\"))) {\n isVisible = false;\n }\n if (!includeHidden && !this.get(\"visible\")) {\n isVisible = false;\n }\n return isVisible;\n },\n\n // ........................................................................ ajax\n //TODO?: these are probably better done on the leaf classes\n /** history content goes through the 'api/histories' API */\n urlRoot: `${Galaxy.root}api/histories/`,\n\n /** full url spec. for this content */\n url: function() {\n var historyContentType = this.get(\"history_content_type\");\n var historyId = this.get(\"history_id\");\n var historyContentId = this.get(\"id\");\n var url = `${this.urlRoot}{this.get(\"historyId\")}/contents/${historyContentType}s/${historyContentId}`;\n return url;\n },\n\n /** save this content as not visible */\n hide: function(options) {\n if (!this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: false }, options);\n },\n /** save this content as visible */\n unhide: function(options) {\n if (this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: true }, options);\n },\n\n // ........................................................................ misc\n toString: function() {\n return [this.get(\"type_id\"), this.get(\"hid\"), this.get(\"name\")].join(\":\");\n }\n};\n\n//==============================================================================\nexport default {\n HistoryContentMixin: HistoryContentMixin\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/history-contents.js.map b/static/maps/mvc/history/history-contents.js.map
index 73b18f95ba98..c0de7cea2817 100644
--- a/static/maps/mvc/history/history-contents.js.map
+++ b/static/maps/mvc/history/history-contents.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/history-contents.js"],"names":["_super","_controlledFetchCollection2","default","PaginatedCollection","HistoryContents","extend","_baseMvc2","LoggableMixin","_logNamespace","limitPerPage","limitPerProgressiveFetch","order","urlRoot","Galaxy","root","url","this","historyId","initialize","models","options","prototype","call","setHistoryId","includeDeleted","includeHidden","model","_hdaModel2","HistoryDatasetAssociation","attrs","history","history_content_type","_hdcaModel2","HistoryListPairedDatasetCollection","HistoryListOfListsDatasetCollection","msg","collection_type","console","validationError","newId","_setUpWebStorage","initialSettings","storage","id","_historyPreferences2","HistoryPrefs","historyStorageKey","on","include-deleted","newVal","include-hidden","comparators","trigger","_","clone","name","buildComparator","ascending","name-dsc","hid","hid-asc","running","c","inReadyState","runningAndActive","filter","get","getByHid","findWhere","all","hasDetails","hidden","deleted","visibleAndUndeleted","haveDetails","setting","isBoolean","result","setIncludeHidden","fetch","details","prefs","toJSON","isEmpty","expandedIds","values","join","_buildFetchData","v","_fetchParams","concat","_buildFetchFilters","superFilters","filters","purged","defaults","contentsShown","fetchUpdated","since","update_time-ge","toISOString","visible","getTotalItemCount","self","always","fetchHidden","data","detailsFlag","remove","_filterAndUpdate","filterParams","updateWhat","fetchAllDetails","idAttribute","updateArgs","then","fetched","reduce","modelArray","currJson","i","fetchCollectionCounts","ajaxQueue","collection","_ajaxQueue2","AjaxQueue","slice","reverse","fn","isString","ajaxFn","content","deferred","progressivelyFetchDetails","offset","_options","view","keys","detailKeys","limit","reset","limitPerCall","done","response","searchAttributes","allFetched","_recursivelyFetch","jQuery","Deferred","notify","contains","copyableModelClasses","contentsJSON","model_class","copy","json","type","contentType","isCopyable","LibraryDatasetDatasetAssociation","HistoryDatasetCollectionAssociation","method","parse","fail","xhr","message","JSON","collectionType","hideSourceItems","history_id","hide_source_items","element_identifiers","elementIdentifiers","haveSearchDetails","has","attributes","matches","matchesWhat","Backbone","Collection","toString","length"],"mappings":"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","file":"../../../scripts/mvc/history/history-contents.js","sourcesContent":["import CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport HDA_MODEL from \"mvc/history/hda-model\";\nimport HDCA_MODEL from \"mvc/history/hdca-model\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport AJAX_QUEUE from \"utils/ajax-queue\";\n\n//==============================================================================\nvar _super = CONTROLLED_FETCH_COLLECTION.PaginatedCollection;\n/** @class Backbone collection for history content.\n * NOTE: history content seems like a dataset collection, but differs in that it is mixed:\n * each element can be either an HDA (dataset) or a DatasetCollection and co-exist on\n * the same level.\n * Dataset collections on the other hand are not mixed and (so far) can only contain either\n * HDAs or child dataset collections on one level.\n * This is why this does not inherit from any of the DatasetCollections (currently).\n */\nvar HistoryContents = _super.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n // ........................................................................ set up\n limitPerPage: 500,\n\n /** @type {Integer} how many contents per call to fetch when using progressivelyFetchDetails */\n limitPerProgressiveFetch: 500,\n\n /** @type {String} order used here and when fetching from server */\n order: \"hid\",\n\n /** root api url */\n urlRoot: `${Galaxy.root}api/histories`,\n\n /** complete api url */\n url: function() {\n return `${this.urlRoot}/${this.historyId}/contents`;\n },\n\n /** Set up */\n initialize: function(models, options) {\n options = options || {};\n _super.prototype.initialize.call(this, models, options);\n\n this.history = options.history || null;\n this.setHistoryId(options.historyId || null);\n /** @type {Boolean} does this collection contain and fetch deleted elements */\n this.includeDeleted = options.includeDeleted || this.includeDeleted;\n /** @type {Boolean} does this collection contain and fetch non-visible elements */\n this.includeHidden = options.includeHidden || this.includeHidden;\n\n // backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection\n // and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute\n // manually here - if we don't, contents will not merge but be replaced/swapped.\n this.model.prototype.idAttribute = \"type_id\";\n },\n\n // ........................................................................ composite collection\n /** since history content is a mix, override model fn into a factory, creating based on history_content_type */\n model: function(attrs, options) {\n if (attrs.history_content_type === \"dataset\") {\n return new HDA_MODEL.HistoryDatasetAssociation(attrs, options);\n } else if (attrs.history_content_type === \"dataset_collection\") {\n switch (attrs.collection_type) {\n case \"list\":\n return new HDCA_MODEL.HistoryListDatasetCollection(attrs, options);\n case \"paired\":\n return new HDCA_MODEL.HistoryPairDatasetCollection(attrs, options);\n case \"list:paired\":\n return new HDCA_MODEL.HistoryListPairedDatasetCollection(attrs, options);\n case \"list:list\":\n return new HDCA_MODEL.HistoryListOfListsDatasetCollection(attrs, options);\n }\n // This is a hack inside a hack:\n // Raise a plain object with validationError to fake a model.validationError\n // (since we don't have a model to use validate with)\n // (the outer hack being the mixed content/model function in this collection)\n var msg = `Unknown collection_type: ${attrs.collection_type}`;\n console.warn(msg, attrs);\n return { validationError: msg };\n }\n return {\n validationError: `Unknown history_content_type: ${attrs.history_content_type}`\n };\n },\n\n setHistoryId: function(newId) {\n this.historyId = newId;\n this._setUpWebStorage();\n },\n\n /** Set up client side storage. Currently PersistanStorage keyed under 'history:' */\n _setUpWebStorage: function(initialSettings) {\n // TODO: use initialSettings\n if (!this.historyId) {\n return;\n }\n this.storage = new HISTORY_PREFS.HistoryPrefs({\n id: HISTORY_PREFS.HistoryPrefs.historyStorageKey(this.historyId)\n });\n this.trigger(\"new-storage\", this.storage, this);\n\n this.on({\n \"include-deleted\": function(newVal) {\n this.storage.includeDeleted(newVal);\n },\n \"include-hidden\": function(newVal) {\n this.storage.includeHidden(newVal);\n }\n });\n\n this.includeDeleted = this.storage.includeDeleted() || false;\n this.includeHidden = this.storage.includeHidden() || false;\n return this;\n },\n\n // ........................................................................ common queries\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_super.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", { ascending: true }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n hid: BASE_MVC.buildComparator(\"hid\", { ascending: false }),\n \"hid-asc\": BASE_MVC.buildComparator(\"hid\", { ascending: true })\n }),\n\n /** Get every model in this collection not in a 'ready' state (running). */\n running: function() {\n return this.filter(c => !c.inReadyState());\n },\n\n /** return contents that are not ready and not deleted/hidden */\n runningAndActive: function() {\n return this.filter(\n c =>\n !c.inReadyState() &&\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** Get the model with the given hid\n * @param {Int} hid the hid to search for\n * @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found\n */\n getByHid: function(hid) {\n // note: there *can* be more than one content with a given hid, this finds the first based on order\n return this.findWhere({ hid: hid });\n },\n\n /** return true if all contents have details */\n haveDetails: function() {\n return this.all(c => c.hasDetails());\n },\n\n // ........................................................................ hidden / deleted\n /** return a new contents collection of only hidden items */\n hidden: function() {\n return this.filter(c => c.hidden());\n },\n\n /** return a new contents collection of only hidden items */\n deleted: function() {\n return this.filter(c => c.get(\"deleted\"));\n },\n\n /** return a new contents collection of only hidden items */\n visibleAndUndeleted: function() {\n return this.filter(\n c =>\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** create a setter in order to publish the change */\n setIncludeDeleted: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeDeleted) {\n this.includeDeleted = setting;\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-deleted\", setting, this);\n }\n },\n\n /** create a setter in order to publish the change */\n setIncludeHidden: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeHidden) {\n this.includeHidden = setting;\n options = options || {};\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-hidden\", setting, this);\n }\n },\n\n // ........................................................................ ajax\n // ............ controlled fetch collection\n /** override to get expanded ids from sessionStorage and pass to API as details */\n fetch: function(options) {\n options = options || {};\n if (this.historyId && !options.details) {\n var prefs = HISTORY_PREFS.HistoryPrefs.get(this.historyId).toJSON();\n if (!_.isEmpty(prefs.expandedIds)) {\n options.details = _.values(prefs.expandedIds).join(\",\");\n }\n }\n return _super.prototype.fetch.call(this, options);\n },\n\n // ............. ControlledFetch stuff\n /** override to include the API versioning flag */\n _buildFetchData: function(options) {\n return _.extend(_super.prototype._buildFetchData.call(this, options), {\n v: \"dev\"\n });\n },\n\n /** Extend to include details and version */\n _fetchParams: _super.prototype._fetchParams.concat([\n // TODO: remove (the need for) both\n /** version */\n \"v\",\n /** dataset ids to get full details of */\n \"details\"\n ]),\n\n /** override to add deleted/hidden filters */\n _buildFetchFilters: function(options) {\n var superFilters = _super.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n }\n if (!this.includeHidden) {\n filters.visible = true;\n }\n return _.defaults(superFilters, filters);\n },\n\n // ............ paginated collection\n getTotalItemCount: function() {\n return this.history.contentsShown();\n },\n\n // ............ history contents specific ajax\n /** override to filter requested contents to those updated after the Date 'since' */\n fetchUpdated: function(since, options) {\n if (since) {\n options = options || { filters: {} };\n options.remove = false;\n options.filters = {\n \"update_time-ge\": since.toISOString(),\n // workflows will produce hidden datasets (non-output datasets) that still\n // need to be updated in the collection or they'll update forever\n // we can remove the default visible filter by using an 'empty' value\n visible: \"\"\n };\n }\n return this.fetch(options);\n },\n\n /** fetch all the deleted==true contents of this collection */\n fetchDeleted: function(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n // all deleted, purged or not\n deleted: true,\n purged: undefined\n });\n options.remove = false;\n\n self.trigger(\"fetching-deleted\", self);\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-deleted-done\", self);\n });\n },\n\n /** fetch all the visible==false contents of this collection */\n fetchHidden: function(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n visible: false\n });\n options.remove = false;\n\n self.trigger(\"fetching-hidden\", self);\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-hidden-done\", self);\n });\n },\n\n /** fetch detailed model data for all contents in this collection */\n fetchAllDetails: function(options) {\n options = options || {};\n var detailsFlag = { details: \"all\" };\n options.data = _.extend(options.data || {}, detailsFlag);\n return this.fetch(options);\n },\n\n /** specialty fetch method for retrieving the element_counts of all hdcas in the history */\n fetchCollectionCounts: function(options) {\n options = options || {};\n options.keys = [\"type_id\", \"element_count\"].join(\",\");\n options.filters = _.extend(options.filters || {}, {\n history_content_type: \"dataset_collection\"\n });\n options.remove = false;\n return this.fetch(options);\n },\n\n // ............. quasi-batch ops\n // TODO: to batch\n /** helper that fetches using filterParams then calls save on each fetched using updateWhat as the save params */\n _filterAndUpdate: function(filterParams, updateWhat) {\n var self = this;\n var idAttribute = self.model.prototype.idAttribute;\n var updateArgs = [updateWhat];\n\n return self.fetch({ filters: filterParams, remove: false }).then(fetched => {\n // convert filtered json array to model array\n fetched = fetched.reduce((modelArray, currJson, i) => {\n var model = self.get(currJson[idAttribute]);\n return model ? modelArray.concat(model) : modelArray;\n }, []);\n return self.ajaxQueue(\"save\", updateArgs, fetched);\n });\n },\n\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function(ajaxFn, args, collection) {\n collection = collection || this.models;\n return new AJAX_QUEUE.AjaxQueue(\n collection\n .slice()\n .reverse()\n .map((content, i) => {\n var fn = _.isString(ajaxFn) ? content[ajaxFn] : ajaxFn;\n return () => fn.apply(content, args);\n })\n ).deferred;\n },\n\n /** fetch contents' details in batches of limitPerCall - note: only get searchable details here */\n progressivelyFetchDetails: function(options) {\n options = options || {};\n var deferred = jQuery.Deferred();\n var self = this;\n var limit = options.limitPerCall || self.limitPerProgressiveFetch;\n // TODO: only fetch tags and annotations if specifically requested\n var searchAttributes = HDA_MODEL.HistoryDatasetAssociation.prototype.searchAttributes;\n var detailKeys = searchAttributes.join(\",\");\n\n function _recursivelyFetch(offset) {\n offset = offset || 0;\n var _options = _.extend(_.clone(options), {\n view: \"summary\",\n keys: detailKeys,\n limit: limit,\n offset: offset,\n reset: offset === 0,\n remove: false\n });\n\n _.defer(() => {\n self.fetch\n .call(self, _options)\n .fail(deferred.reject)\n .done(response => {\n deferred.notify(response, limit, offset);\n if (response.length !== limit) {\n self.allFetched = true;\n deferred.resolve(response, limit, offset);\n } else {\n _recursivelyFetch(offset + limit);\n }\n });\n });\n }\n _recursivelyFetch();\n return deferred;\n },\n\n /** does some bit of JSON represent something that can be copied into this contents collection */\n isCopyable: function(contentsJSON) {\n var copyableModelClasses = [\"HistoryDatasetAssociation\", \"HistoryDatasetCollectionAssociation\"];\n return (\n _.isObject(contentsJSON) && contentsJSON.id && _.contains(copyableModelClasses, contentsJSON.model_class)\n );\n },\n\n /** copy an existing, accessible hda into this collection */\n copy: function(json) {\n // TODO: somehow showhorn all this into 'save'\n var id;\n\n var type;\n var contentType;\n if (_.isString(json)) {\n id = json;\n contentType = \"hda\";\n type = \"dataset\";\n } else {\n id = json.id;\n contentType =\n {\n HistoryDatasetAssociation: \"hda\",\n LibraryDatasetDatasetAssociation: \"ldda\",\n HistoryDatasetCollectionAssociation: \"hdca\"\n }[json.model_class] || \"hda\";\n type = contentType === \"hdca\" ? \"dataset_collection\" : \"dataset\";\n }\n var collection = this;\n\n var xhr = jQuery\n .ajax(this.url(), {\n method: \"POST\",\n contentType: \"application/json\",\n data: JSON.stringify({\n content: id,\n source: contentType,\n type: type\n })\n })\n .done(response => {\n collection.add([response], { parse: true });\n })\n .fail((error, status, message) => {\n collection.trigger(\"error\", collection, xhr, {}, \"Error copying contents\", {\n type: type,\n id: id,\n source: contentType\n });\n });\n\n return xhr;\n },\n\n /** create a new HDCA in this collection */\n createHDCA: function(elementIdentifiers, collectionType, name, hideSourceItems, options) {\n // normally collection.create returns the new model, but we need the promise from the ajax, so we fake create\n //precondition: elementIdentifiers is an array of plain js objects\n // in the proper form to create the collectionType\n var hdca = this.model({\n history_content_type: \"dataset_collection\",\n collection_type: collectionType,\n history_id: this.historyId,\n name: name,\n hide_source_items: hideSourceItems || false,\n // should probably be able to just send in a bunch of json here and restruct per class\n // note: element_identifiers is now (incorrectly) an attribute\n element_identifiers: elementIdentifiers\n // do not create the model on the client until the ajax returns\n });\n return hdca.save(options);\n },\n\n // ........................................................................ searching\n /** return true if all contents have the searchable attributes */\n haveSearchDetails: function() {\n return (\n this.allFetched &&\n this.all((\n content // null (which is a valid returned annotation value)\n ) =>\n // will return false when using content.has( 'annotation' )\n //TODO: a bit hacky - formalize\n _.has(content.attributes, \"annotation\")\n )\n );\n },\n\n /** return a new collection of contents whose attributes contain the substring matchesWhat */\n matches: function(matchesWhat) {\n return this.filter(content => content.matches(matchesWhat));\n },\n\n // ........................................................................ misc\n /** In this override, copy the historyId to the clone */\n clone: function() {\n var clone = Backbone.Collection.prototype.clone.call(this);\n clone.historyId = this.historyId;\n return clone;\n },\n\n /** String representation. */\n toString: function() {\n return [\"HistoryContents(\", [this.historyId, this.length].join(), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n HistoryContents: HistoryContents\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/history/history-contents.js"],"names":["_super","_controlledFetchCollection2","default","PaginatedCollection","HistoryContents","extend","_baseMvc2","LoggableMixin","_logNamespace","limitPerPage","limitPerProgressiveFetch","order","urlRoot","Galaxy","root","url","this","historyId","initialize","models","options","prototype","call","setHistoryId","includeDeleted","includeHidden","model","_hdaModel2","HistoryDatasetAssociation","attrs","history","history_content_type","_hdcaModel2","HistoryListPairedDatasetCollection","HistoryListOfListsDatasetCollection","msg","collection_type","console","validationError","newId","_setUpWebStorage","initialSettings","storage","id","_historyPreferences2","HistoryPrefs","historyStorageKey","on","include-deleted","newVal","include-hidden","comparators","trigger","_","clone","name","buildComparator","ascending","name-dsc","hid","hid-asc","running","c","inReadyState","runningAndActive","filter","get","getByHid","findWhere","all","hasDetails","hidden","deleted","visibleAndUndeleted","haveDetails","setting","isBoolean","result","setIncludeHidden","fetch","details","prefs","toJSON","isEmpty","expandedIds","values","join","_buildFetchData","v","_fetchParams","concat","_buildFetchFilters","superFilters","filters","purged","defaults","contentsShown","fetchUpdated","since","update_time-ge","toISOString","visible","getTotalItemCount","_this","undefined","always","fetchHidden","self","fetchDeleted","remove","detailsFlag","data","fetchCollectionCounts","_filterAndUpdate","filterParams","updateWhat","idAttribute","fetchAllDetails","then","fetched","modelArray","currJson","i","updateArgs","ajaxQueue","ajaxFn","args","collection","_ajaxQueue2","slice","reverse","map","content","fn","isString","apply","deferred","progressivelyFetchDetails","_recursivelyFetch","offset","view","keys","limit","reset","defer","Deferred","response","limitPerCall","length","searchAttributes","detailKeys","jQuery","isCopyable","contentsJSON","copyableModelClasses","model_class","type","json","contentType","LibraryDatasetDatasetAssociation","HistoryDatasetCollectionAssociation","xhr","JSON","stringify","done","parse","fail","message","method","createHDCA","elementIdentifiers","hideSourceItems","source","collectionType","history_id","hide_source_items","save","allFetched","element_identifiers","has","attributes","matches","matchesWhat","Backbone","Collection","toString"],"mappings":"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","file":"../../../scripts/mvc/history/history-contents.js","sourcesContent":["import CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport HDA_MODEL from \"mvc/history/hda-model\";\nimport HDCA_MODEL from \"mvc/history/hdca-model\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport AJAX_QUEUE from \"utils/ajax-queue\";\n\n//==============================================================================\nvar _super = CONTROLLED_FETCH_COLLECTION.PaginatedCollection;\n/** @class Backbone collection for history content.\n * NOTE: history content seems like a dataset collection, but differs in that it is mixed:\n * each element can be either an HDA (dataset) or a DatasetCollection and co-exist on\n * the same level.\n * Dataset collections on the other hand are not mixed and (so far) can only contain either\n * HDAs or child dataset collections on one level.\n * This is why this does not inherit from any of the DatasetCollections (currently).\n */\nvar HistoryContents = _super.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n // ........................................................................ set up\n limitPerPage: 500,\n\n /** @type {Integer} how many contents per call to fetch when using progressivelyFetchDetails */\n limitPerProgressiveFetch: 500,\n\n /** @type {String} order used here and when fetching from server */\n order: \"hid\",\n\n /** root api url */\n urlRoot: `${Galaxy.root}api/histories`,\n\n /** complete api url */\n url: function() {\n return `${this.urlRoot}/${this.historyId}/contents`;\n },\n\n /** Set up */\n initialize: function(models, options) {\n options = options || {};\n _super.prototype.initialize.call(this, models, options);\n\n this.history = options.history || null;\n this.setHistoryId(options.historyId || null);\n /** @type {Boolean} does this collection contain and fetch deleted elements */\n this.includeDeleted = options.includeDeleted || this.includeDeleted;\n /** @type {Boolean} does this collection contain and fetch non-visible elements */\n this.includeHidden = options.includeHidden || this.includeHidden;\n\n // backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection\n // and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute\n // manually here - if we don't, contents will not merge but be replaced/swapped.\n this.model.prototype.idAttribute = \"type_id\";\n },\n\n // ........................................................................ composite collection\n /** since history content is a mix, override model fn into a factory, creating based on history_content_type */\n model: function(attrs, options) {\n if (attrs.history_content_type === \"dataset\") {\n return new HDA_MODEL.HistoryDatasetAssociation(attrs, options);\n } else if (attrs.history_content_type === \"dataset_collection\") {\n switch (attrs.collection_type) {\n case \"list\":\n return new HDCA_MODEL.HistoryListDatasetCollection(attrs, options);\n case \"paired\":\n return new HDCA_MODEL.HistoryPairDatasetCollection(attrs, options);\n case \"list:paired\":\n return new HDCA_MODEL.HistoryListPairedDatasetCollection(attrs, options);\n case \"list:list\":\n return new HDCA_MODEL.HistoryListOfListsDatasetCollection(attrs, options);\n }\n // This is a hack inside a hack:\n // Raise a plain object with validationError to fake a model.validationError\n // (since we don't have a model to use validate with)\n // (the outer hack being the mixed content/model function in this collection)\n var msg = `Unknown collection_type: ${attrs.collection_type}`;\n console.warn(msg, attrs);\n return { validationError: msg };\n }\n return {\n validationError: `Unknown history_content_type: ${attrs.history_content_type}`\n };\n },\n\n setHistoryId: function(newId) {\n this.historyId = newId;\n this._setUpWebStorage();\n },\n\n /** Set up client side storage. Currently PersistanStorage keyed under 'history:' */\n _setUpWebStorage: function(initialSettings) {\n // TODO: use initialSettings\n if (!this.historyId) {\n return;\n }\n this.storage = new HISTORY_PREFS.HistoryPrefs({\n id: HISTORY_PREFS.HistoryPrefs.historyStorageKey(this.historyId)\n });\n this.trigger(\"new-storage\", this.storage, this);\n\n this.on({\n \"include-deleted\": function(newVal) {\n this.storage.includeDeleted(newVal);\n },\n \"include-hidden\": function(newVal) {\n this.storage.includeHidden(newVal);\n }\n });\n\n this.includeDeleted = this.storage.includeDeleted() || false;\n this.includeHidden = this.storage.includeHidden() || false;\n return this;\n },\n\n // ........................................................................ common queries\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_super.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", { ascending: true }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n hid: BASE_MVC.buildComparator(\"hid\", { ascending: false }),\n \"hid-asc\": BASE_MVC.buildComparator(\"hid\", { ascending: true })\n }),\n\n /** Get every model in this collection not in a 'ready' state (running). */\n running: function() {\n return this.filter(c => !c.inReadyState());\n },\n\n /** return contents that are not ready and not deleted/hidden */\n runningAndActive: function() {\n return this.filter(\n c =>\n !c.inReadyState() &&\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** Get the model with the given hid\n * @param {Int} hid the hid to search for\n * @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found\n */\n getByHid: function(hid) {\n // note: there *can* be more than one content with a given hid, this finds the first based on order\n return this.findWhere({ hid: hid });\n },\n\n /** return true if all contents have details */\n haveDetails: function() {\n return this.all(c => c.hasDetails());\n },\n\n // ........................................................................ hidden / deleted\n /** return a new contents collection of only hidden items */\n hidden: function() {\n return this.filter(c => c.hidden());\n },\n\n /** return a new contents collection of only hidden items */\n deleted: function() {\n return this.filter(c => c.get(\"deleted\"));\n },\n\n /** return a new contents collection of only hidden items */\n visibleAndUndeleted: function() {\n return this.filter(\n c =>\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** create a setter in order to publish the change */\n setIncludeDeleted: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeDeleted) {\n this.includeDeleted = setting;\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-deleted\", setting, this);\n }\n },\n\n /** create a setter in order to publish the change */\n setIncludeHidden: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeHidden) {\n this.includeHidden = setting;\n options = options || {};\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-hidden\", setting, this);\n }\n },\n\n // ........................................................................ ajax\n // ............ controlled fetch collection\n /** override to get expanded ids from sessionStorage and pass to API as details */\n fetch: function(options) {\n options = options || {};\n if (this.historyId && !options.details) {\n var prefs = HISTORY_PREFS.HistoryPrefs.get(this.historyId).toJSON();\n if (!_.isEmpty(prefs.expandedIds)) {\n options.details = _.values(prefs.expandedIds).join(\",\");\n }\n }\n return _super.prototype.fetch.call(this, options);\n },\n\n // ............. ControlledFetch stuff\n /** override to include the API versioning flag */\n _buildFetchData: function(options) {\n return _.extend(_super.prototype._buildFetchData.call(this, options), {\n v: \"dev\"\n });\n },\n\n /** Extend to include details and version */\n _fetchParams: _super.prototype._fetchParams.concat([\n // TODO: remove (the need for) both\n /** version */\n \"v\",\n /** dataset ids to get full details of */\n \"details\"\n ]),\n\n /** override to add deleted/hidden filters */\n _buildFetchFilters: function(options) {\n var superFilters = _super.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n }\n if (!this.includeHidden) {\n filters.visible = true;\n }\n return _.defaults(superFilters, filters);\n },\n\n // ............ paginated collection\n getTotalItemCount: function() {\n return this.history.contentsShown();\n },\n\n // ............ history contents specific ajax\n /** override to filter requested contents to those updated after the Date 'since' */\n fetchUpdated: function(since, options) {\n if (since) {\n options = options || { filters: {} };\n options.remove = false;\n options.filters = {\n \"update_time-ge\": since.toISOString(),\n // workflows will produce hidden datasets (non-output datasets) that still\n // need to be updated in the collection or they'll update forever\n // we can remove the default visible filter by using an 'empty' value\n visible: \"\"\n };\n }\n return this.fetch(options);\n },\n\n /** fetch all the deleted==true contents of this collection */\n fetchDeleted: function(options) {\n options = options || {};\n options.filters = _.extend(options.filters, {\n // all deleted, purged or not\n deleted: true,\n purged: undefined\n });\n options.remove = false;\n\n this.trigger(\"fetching-deleted\", this);\n return this.fetch(options).always(() => {\n this.trigger(\"fetching-deleted-done\", this);\n });\n },\n\n /** fetch all the visible==false contents of this collection */\n fetchHidden: function(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n visible: false\n });\n options.remove = false;\n\n self.trigger(\"fetching-hidden\", self);\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-hidden-done\", self);\n });\n },\n\n /** fetch detailed model data for all contents in this collection */\n fetchAllDetails: function(options) {\n options = options || {};\n var detailsFlag = { details: \"all\" };\n options.data = _.extend(options.data || {}, detailsFlag);\n return this.fetch(options);\n },\n\n /** specialty fetch method for retrieving the element_counts of all hdcas in the history */\n fetchCollectionCounts: function(options) {\n options = options || {};\n options.keys = [\"type_id\", \"element_count\"].join(\",\");\n options.filters = _.extend(options.filters || {}, {\n history_content_type: \"dataset_collection\"\n });\n options.remove = false;\n return this.fetch(options);\n },\n\n // ............. quasi-batch ops\n // TODO: to batch\n /** helper that fetches using filterParams then calls save on each fetched using updateWhat as the save params */\n _filterAndUpdate: function(filterParams, updateWhat) {\n var self = this;\n var idAttribute = self.model.prototype.idAttribute;\n var updateArgs = [updateWhat];\n\n return self.fetch({ filters: filterParams, remove: false }).then(fetched => {\n // convert filtered json array to model array\n fetched = fetched.reduce((modelArray, currJson, i) => {\n var model = self.get(currJson[idAttribute]);\n return model ? modelArray.concat(model) : modelArray;\n }, []);\n return self.ajaxQueue(\"save\", updateArgs, fetched);\n });\n },\n\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function(ajaxFn, args, collection) {\n collection = collection || this.models;\n return new AJAX_QUEUE.AjaxQueue(\n collection\n .slice()\n .reverse()\n .map((content, i) => {\n var fn = _.isString(ajaxFn) ? content[ajaxFn] : ajaxFn;\n return () => fn.apply(content, args);\n })\n ).deferred;\n },\n\n /** fetch contents' details in batches of limitPerCall - note: only get searchable details here */\n progressivelyFetchDetails: function(options) {\n options = options || {};\n var deferred = jQuery.Deferred();\n var self = this;\n var limit = options.limitPerCall || self.limitPerProgressiveFetch;\n // TODO: only fetch tags and annotations if specifically requested\n var searchAttributes = HDA_MODEL.HistoryDatasetAssociation.prototype.searchAttributes;\n var detailKeys = searchAttributes.join(\",\");\n\n function _recursivelyFetch(offset) {\n offset = offset || 0;\n var _options = _.extend(_.clone(options), {\n view: \"summary\",\n keys: detailKeys,\n limit: limit,\n offset: offset,\n reset: offset === 0,\n remove: false\n });\n\n _.defer(() => {\n self.fetch\n .call(self, _options)\n .fail(deferred.reject)\n .done(response => {\n deferred.notify(response, limit, offset);\n if (response.length !== limit) {\n self.allFetched = true;\n deferred.resolve(response, limit, offset);\n } else {\n _recursivelyFetch(offset + limit);\n }\n });\n });\n }\n _recursivelyFetch();\n return deferred;\n },\n\n /** does some bit of JSON represent something that can be copied into this contents collection */\n isCopyable: function(contentsJSON) {\n var copyableModelClasses = [\"HistoryDatasetAssociation\", \"HistoryDatasetCollectionAssociation\"];\n return (\n _.isObject(contentsJSON) && contentsJSON.id && _.contains(copyableModelClasses, contentsJSON.model_class)\n );\n },\n\n /** copy an existing, accessible hda into this collection */\n copy: function(json) {\n // TODO: somehow showhorn all this into 'save'\n var id;\n\n var type;\n var contentType;\n if (_.isString(json)) {\n id = json;\n contentType = \"hda\";\n type = \"dataset\";\n } else {\n id = json.id;\n contentType =\n {\n HistoryDatasetAssociation: \"hda\",\n LibraryDatasetDatasetAssociation: \"ldda\",\n HistoryDatasetCollectionAssociation: \"hdca\"\n }[json.model_class] || \"hda\";\n type = contentType === \"hdca\" ? \"dataset_collection\" : \"dataset\";\n }\n var collection = this;\n\n var xhr = jQuery\n .ajax(this.url(), {\n method: \"POST\",\n contentType: \"application/json\",\n data: JSON.stringify({\n content: id,\n source: contentType,\n type: type\n })\n })\n .done(response => {\n collection.add([response], { parse: true });\n })\n .fail((error, status, message) => {\n collection.trigger(\"error\", collection, xhr, {}, \"Error copying contents\", {\n type: type,\n id: id,\n source: contentType\n });\n });\n\n return xhr;\n },\n\n /** create a new HDCA in this collection */\n createHDCA: function(elementIdentifiers, collectionType, name, hideSourceItems, options) {\n // normally collection.create returns the new model, but we need the promise from the ajax, so we fake create\n //precondition: elementIdentifiers is an array of plain js objects\n // in the proper form to create the collectionType\n var hdca = this.model({\n history_content_type: \"dataset_collection\",\n collection_type: collectionType,\n history_id: this.historyId,\n name: name,\n hide_source_items: hideSourceItems || false,\n // should probably be able to just send in a bunch of json here and restruct per class\n // note: element_identifiers is now (incorrectly) an attribute\n element_identifiers: elementIdentifiers\n // do not create the model on the client until the ajax returns\n });\n return hdca.save(options);\n },\n\n // ........................................................................ searching\n /** return true if all contents have the searchable attributes */\n haveSearchDetails: function() {\n return (\n this.allFetched &&\n this.all((\n content // null (which is a valid returned annotation value)\n ) =>\n // will return false when using content.has( 'annotation' )\n //TODO: a bit hacky - formalize\n _.has(content.attributes, \"annotation\")\n )\n );\n },\n\n /** return a new collection of contents whose attributes contain the substring matchesWhat */\n matches: function(matchesWhat) {\n return this.filter(content => content.matches(matchesWhat));\n },\n\n // ........................................................................ misc\n /** In this override, copy the historyId to the clone */\n clone: function() {\n var clone = Backbone.Collection.prototype.clone.call(this);\n clone.historyId = this.historyId;\n return clone;\n },\n\n /** String representation. */\n toString: function() {\n return [\"HistoryContents(\", [this.historyId, this.length].join(), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n HistoryContents: HistoryContents\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/history-item-li.js.map b/static/maps/mvc/history/history-item-li.js.map
new file mode 100644
index 000000000000..956c96b0a3a5
--- /dev/null
+++ b/static/maps/mvc/history/history-item-li.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["mvc/history/history-item-li.js"],"names":["_labelIfName","tag","indexOf","_","escape","slice","nametagTemplate","historyItem","sortBy","uniq","tags","map","join"],"mappings":"0EAAA,SAASA,EAAaC,GAClB,OAA4B,GAAxBA,EAAIC,QAAQ,SACZ,kCAAyCC,EAAEC,OAAOH,EAAII,MAAM,IAA5D,UAEO,+DAKXC,gBAPI,SAAAC,GACH,MAAA,0BAAMJ,EAAAK,OAAAL,EAAAM,KAAAF,EAAAG,OACHC,IAAAX,GACHY,KAAA,IAFA","file":"../../../scripts/mvc/history/history-item-li.js","sourcesContent":["function _labelIfName(tag) {\n if (tag.indexOf(\"name:\") == 0) {\n return `${_.escape(tag.slice(5))}`;\n } else {\n return \"\";\n }\n}\n\nfunction nametagTemplate(historyItem) {\n return `${_.sortBy(_.uniq(historyItem.tags))\n .map(_labelIfName)\n .join(\"\")}`;\n}\n\nexport default {\n nametagTemplate: nametagTemplate\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/history-model.js.map b/static/maps/mvc/history/history-model.js.map
index fa47fa74a133..374140eacdd9 100644
--- a/static/maps/mvc/history/history-model.js.map
+++ b/static/maps/mvc/history/history-model.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/history-model.js"],"names":["History","Backbone","Model","extend","_baseMvc2","default","LoggableMixin","mixin","SearchableModelMixin","_logNamespace","UPDATE_DELAY","defaults","model_class","id","name","state","deleted","contents_active","urlRoot","Galaxy","root","_historyContents2","HistoryContents","tag","contentsClass","historyJSON","options","this","logger","searchAttributes","searchAliases","history","historyId","get","order","_setUpListeners","_setUpCollectionListeners","initialize","updateTimeoutId","on","clearUpdateTimeout","model","newId","contents","error","trigger","apply","arguments","contentsShown","contentsActive","active","shown","includeDeleted","includeHidden","hidden","nice_size","size","_utils2","bytesToString","_localization2","toJSON","_","prototype","call","key","user","isAnonymous","numOfUnfinishedJobs","unfinishedJobIds","length","numOfUnfinishedShownContents","runningAndActive","_fetchContentRelatedAttributes","contentRelatedAttrs","fetch","data","$","param","keys","join","refresh","self","lastUpdateTime","allFetched","fetchPage","currentPage","fetchUpdated","done","response","status","xhr","serverResponseDatetime","Date","getResponseHeader","checkForUpdates","delay","_delayThenUpdate","historyData","clearTimeout","parse","parsed","create_time","update_time","fetchWithContents","contentsOptions","then","setHistoryId","fetchContents","view","fetchCurrentPage","save","jQuery","when","purged","undelete","copy","current","allDatasets","Error","postData","all_datasets","post","setAsCurrent","getJSON","newHistory","toString","_collectionSuper","InfinitelyScrollingCollection","HistoryCollection","limitOnFirstFetch","limitPerFetch","models","log","currentHistoryId","url","setUpListeners","change:deleted","debug","remove","copied","newData","setCurrent","oldCurrentId","_buildFetchData","_buildFetchFilters","superFilters","filters","fetchFirst","silent","limit","encoded_id-in","comparators","clone","name-dsc","buildComparator","ascending","size-asc","fetchMore","currentHistory","sort","unshift","create","hdas","historyOptions","xhrOptions","collection"],"mappings":"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","file":"../../../scripts/mvc/history/history-model.js","sourcesContent":["import HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport UTILS from \"utils/utils\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Model for a Galaxy history resource - both a record of user\n * tool use and a collection of the datasets those tools produced.\n * @name History\n * @augments Backbone.Model\n */\nvar History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(\n BASE_MVC.mixin(\n BASE_MVC.SearchableModelMixin,\n /** @lends History.prototype */ {\n _logNamespace: \"history\",\n\n /** ms between fetches when checking running jobs/datasets for updates */\n UPDATE_DELAY: 4000,\n\n // values from api (may need more)\n defaults: {\n model_class: \"History\",\n id: null,\n name: \"Unnamed History\",\n state: \"new\",\n\n deleted: false,\n contents_active: {},\n contents_states: {}\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n\n contentsClass: HISTORY_CONTENTS.HistoryContents,\n\n /** What model fields to search with */\n searchAttributes: [\"name\", \"annotation\", \"tags\"],\n\n /** Adding title and singular tag */\n searchAliases: {\n title: \"name\",\n tag: \"tags\"\n },\n\n // ........................................................................ set up/tear down\n /** Set up the model\n * @param {Object} historyJSON model data for this History\n * @param {Object} options any extra settings including logger\n */\n initialize: function(historyJSON, options) {\n options = options || {};\n this.logger = options.logger || null;\n this.log(`${this}.initialize:`, historyJSON, options);\n\n /** HistoryContents collection of the HDAs contained in this history. */\n this.contents = new this.contentsClass([], {\n history: this,\n historyId: this.get(\"id\"),\n order: options.order\n });\n\n this._setUpListeners();\n this._setUpCollectionListeners();\n\n /** cached timeout id for the dataset updater */\n this.updateTimeoutId = null;\n },\n\n /** set up any event listeners for this history including those to the contained HDAs\n * events: error:contents if an error occurred with the contents collection\n */\n _setUpListeners: function() {\n // if the model's id changes ('current' or null -> an actual id), update the contents history_id\n return this.on({\n error: function(model, xhr, options, msg, details) {\n this.clearUpdateTimeout();\n },\n \"change:id\": function(model, newId) {\n if (this.contents) {\n this.contents.historyId = newId;\n }\n }\n });\n },\n\n /** event handlers for the contents submodels */\n _setUpCollectionListeners: function() {\n if (!this.contents) {\n return this;\n }\n // bubble up errors\n return this.listenTo(this.contents, {\n error: function() {\n this.trigger.apply(this, jQuery.makeArray(arguments));\n }\n });\n },\n\n // ........................................................................ derived attributes\n /** */\n contentsShown: function() {\n var contentsActive = this.get(\"contents_active\");\n var shown = contentsActive.active || 0;\n shown += this.contents.includeDeleted ? contentsActive.deleted : 0;\n shown += this.contents.includeHidden ? contentsActive.hidden : 0;\n return shown;\n },\n\n /** convert size in bytes to a more human readable version */\n nice_size: function() {\n var size = this.get(\"size\");\n return size ? UTILS.bytesToString(size, true, 2) : _l(\"(empty)\");\n },\n\n /** override to add nice_size */\n toJSON: function() {\n return _.extend(Backbone.Model.prototype.toJSON.call(this), {\n nice_size: this.nice_size()\n });\n },\n\n /** override to allow getting nice_size */\n get: function(key) {\n if (key === \"nice_size\") {\n return this.nice_size();\n }\n return Backbone.Model.prototype.get.apply(this, arguments);\n },\n\n // ........................................................................ common queries\n /** T/F is this history owned by the current user (Galaxy.user)\n * Note: that this will return false for an anon user even if the history is theirs.\n */\n ownedByCurrUser: function() {\n // no currUser\n if (!Galaxy || !Galaxy.user) {\n return false;\n }\n // user is anon or history isn't owned\n if (Galaxy.user.isAnonymous() || Galaxy.user.id !== this.get(\"user_id\")) {\n return false;\n }\n return true;\n },\n\n /** Return the number of running jobs assoc with this history (note: unknown === 0) */\n numOfUnfinishedJobs: function() {\n var unfinishedJobIds = this.get(\"non_ready_jobs\");\n return unfinishedJobIds ? unfinishedJobIds.length : 0;\n },\n\n /** Return the number of running hda/hdcas in this history (note: unknown === 0) */\n numOfUnfinishedShownContents: function() {\n return this.contents.runningAndActive().length || 0;\n },\n\n // ........................................................................ updates\n _fetchContentRelatedAttributes: function() {\n var contentRelatedAttrs = [\"size\", \"non_ready_jobs\", \"contents_active\", \"hid_counter\"];\n return this.fetch({\n data: $.param({\n keys: contentRelatedAttrs.join(\",\")\n })\n });\n },\n\n /** check for any changes since the last time we updated (or fetch all if ) */\n refresh: function(options) {\n // console.log( this + '.refresh' );\n options = options || {};\n var self = this;\n\n // note if there was no previous update time, all summary contents will be fetched\n var lastUpdateTime = self.lastUpdateTime;\n // if we don't flip this, then a fully-fetched list will not be re-checked via fetch\n this.contents.allFetched = false;\n var fetchFn =\n self.contents.currentPage !== 0\n ? () => self.contents.fetchPage(self.contents.currentPage)\n : () => self.contents.fetchUpdated(lastUpdateTime);\n // note: if there was no previous update time, all summary contents will be fetched\n return fetchFn().done((response, status, xhr) => {\n var serverResponseDatetime;\n try {\n serverResponseDatetime = new Date(xhr.getResponseHeader(\"Date\"));\n } catch (err) {}\n self.lastUpdateTime = serverResponseDatetime || new Date();\n self.checkForUpdates(options);\n });\n },\n\n /** continuously fetch updated contents every UPDATE_DELAY ms if this history's datasets or jobs are unfinished */\n checkForUpdates: function(options) {\n // console.log( this + '.checkForUpdates' );\n options = options || {};\n var delay = this.UPDATE_DELAY;\n var self = this;\n if (!self.id) {\n return;\n }\n\n function _delayThenUpdate() {\n // prevent buildup of updater timeouts by clearing previous if any, then set new and cache id\n self.clearUpdateTimeout();\n self.updateTimeoutId = setTimeout(() => {\n self.refresh(options);\n }, delay);\n }\n\n // if there are still datasets in the non-ready state, recurse into this function with the new time\n var nonReadyContentCount = this.numOfUnfinishedShownContents();\n // console.log( 'nonReadyContentCount:', nonReadyContentCount );\n if (nonReadyContentCount > 0) {\n _delayThenUpdate();\n } else {\n // no datasets are running, but currently runnning jobs may still produce new datasets\n // see if the history has any running jobs and continue to update if so\n // (also update the size for the user in either case)\n self._fetchContentRelatedAttributes().done(historyData => {\n // console.log( 'non_ready_jobs:', historyData.non_ready_jobs );\n if (self.numOfUnfinishedJobs() > 0) {\n _delayThenUpdate();\n } else {\n // otherwise, let listeners know that all updates have stopped\n self.trigger(\"ready\");\n }\n });\n }\n },\n\n /** clear the timeout and the cached timeout id */\n clearUpdateTimeout: function() {\n if (this.updateTimeoutId) {\n clearTimeout(this.updateTimeoutId);\n this.updateTimeoutId = null;\n }\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** fetch this histories data (using options) then it's contents (using contentsOptions) */\n fetchWithContents: function(options, contentsOptions) {\n options = options || {};\n var self = this;\n\n // console.log( this + '.fetchWithContents' );\n // TODO: push down to a base class\n options.view = \"dev-detailed\";\n\n // fetch history then use history data to fetch (paginated) contents\n return this.fetch(options).then(function getContents(history) {\n self.contents.history = self;\n self.contents.setHistoryId(history.id);\n return self.fetchContents(contentsOptions);\n });\n },\n\n /** fetch this histories contents, adjusting options based on the stored history preferences */\n fetchContents: function(options) {\n options = options || {};\n var self = this;\n\n // we're updating, reset the update time\n self.lastUpdateTime = new Date();\n return self.contents.fetchCurrentPage(options);\n },\n\n /** save this history, _Mark_ing it as deleted (just a flag) */\n _delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */\n purge: function(options) {\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true, purged: true }, options);\n },\n /** save this history, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Make a copy of this history on the server\n * @param {Boolean} current if true, set the copy as the new current history (default: true)\n * @param {String} name name of new history (default: none - server sets to: Copy of )\n * @fires copied passed this history and the response JSON from the copy\n * @returns {xhr}\n */\n copy: function(current, name, allDatasets) {\n current = current !== undefined ? current : true;\n if (!this.id) {\n throw new Error(\"You must set the history ID before copying it.\");\n }\n\n var postData = { history_id: this.id };\n if (current) {\n postData.current = true;\n }\n if (name) {\n postData.name = name;\n }\n if (!allDatasets) {\n postData.all_datasets = false;\n }\n postData.view = \"dev-detailed\";\n\n var history = this;\n var copy = jQuery.post(this.urlRoot, postData);\n // if current - queue to setAsCurrent before firing 'copied'\n if (current) {\n return copy.then(response => {\n var newHistory = new History(response);\n return newHistory.setAsCurrent().done(() => {\n history.trigger(\"copied\", history, response);\n });\n });\n }\n return copy.done(response => {\n history.trigger(\"copied\", history, response);\n });\n },\n\n setAsCurrent: function() {\n var history = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/set_as_current?id=${this.id}`);\n\n xhr.done(() => {\n history.trigger(\"set-as-current\", history);\n });\n return xhr;\n },\n\n // ........................................................................ misc\n toString: function() {\n return `History(${this.get(\"id\")},${this.get(\"name\")})`;\n }\n }\n )\n);\n\n//==============================================================================\nvar _collectionSuper = CONTROLLED_FETCH_COLLECTION.InfinitelyScrollingCollection;\n/** @class A collection of histories (per user)\n * that maintains the current history as the first in the collection.\n * New or copied histories become the current history.\n */\nvar HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n model: History,\n /** @type {String} initial order used by collection */\n order: \"update_time\",\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: 10,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 10,\n\n initialize: function(models, options) {\n options = options || {};\n this.log(\"HistoryCollection.initialize\", models, options);\n _collectionSuper.prototype.initialize.call(this, models, options);\n\n /** @type {boolean} should deleted histories be included */\n this.includeDeleted = options.includeDeleted || false;\n\n /** @type {String} encoded id of the history that's current */\n this.currentHistoryId = options.currentHistoryId;\n\n this.setUpListeners();\n // note: models are sent to reset *after* this fn ends; up to this point\n // the collection *is empty*\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n url: function() {\n return this.urlRoot;\n },\n\n /** set up reflexive event handlers */\n setUpListeners: function setUpListeners() {\n return this.on({\n // when a history is deleted, remove it from the collection (if optionally set to do so)\n \"change:deleted\": function(history) {\n // TODO: this becomes complicated when more filters are used\n this.debug(\"change:deleted\", this.includeDeleted, history.get(\"deleted\"));\n if (!this.includeDeleted && history.get(\"deleted\")) {\n this.remove(history);\n }\n },\n // listen for a history copy, setting it to current\n copied: function(original, newData) {\n this.setCurrent(new History(newData, []));\n },\n // when a history is made current, track the id in the collection\n \"set-as-current\": function(history) {\n var oldCurrentId = this.currentHistoryId;\n this.trigger(\"no-longer-current\", oldCurrentId);\n this.currentHistoryId = history.id;\n }\n });\n },\n\n /** override to change view */\n _buildFetchData: function(options) {\n return _.extend(_collectionSuper.prototype._buildFetchData.call(this, options), {\n view: \"dev-detailed\"\n });\n },\n\n /** override to filter out deleted and purged */\n _buildFetchFilters: function(options) {\n var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n } else {\n // force API to return both deleted and non\n //TODO: when the API is updated, remove this\n filters.deleted = null;\n }\n return _.defaults(superFilters, filters);\n },\n\n /** override to fetch current as well (as it may be outside the first 10, etc.) */\n fetchFirst: function(options) {\n var self = this;\n // TODO: batch?\n var xhr = $.when();\n if (this.currentHistoryId) {\n xhr = _collectionSuper.prototype.fetchFirst.call(self, {\n silent: true,\n limit: 1,\n filters: {\n // without these a deleted current history will return [] here and block the other xhr\n purged: \"\",\n deleted: \"\",\n \"encoded_id-in\": this.currentHistoryId\n }\n });\n }\n return xhr.then(() => {\n options = options || {};\n options.offset = 0;\n return self.fetchMore(options);\n });\n },\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_collectionSuper.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", {\n ascending: true\n }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n size: BASE_MVC.buildComparator(\"size\", {\n ascending: false\n }),\n \"size-asc\": BASE_MVC.buildComparator(\"size\", {\n ascending: true\n })\n }),\n\n /** override to always have the current history first */\n sort: function(options) {\n options = options || {};\n var silent = options.silent;\n var currentHistory = this.remove(this.get(this.currentHistoryId));\n _collectionSuper.prototype.sort.call(this, _.defaults({ silent: true }, options));\n this.unshift(currentHistory, { silent: true });\n if (!silent) {\n this.trigger(\"sort\", this, options);\n }\n return this;\n },\n\n /** create a new history and by default set it to be the current history */\n create: function create(data, hdas, historyOptions, xhrOptions) {\n //TODO: .create is actually a collection function that's overridden here\n var collection = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/create_new_current`);\n return xhr.done(newData => {\n collection.setCurrent(new History(newData, [], historyOptions || {}));\n });\n },\n\n /** set the current history to the given history, placing it first in the collection.\n * Pass standard bbone options for use in unshift.\n * @triggers new-current passed history and this collection\n */\n setCurrent: function(history, options) {\n options = options || {};\n // new histories go in the front\n this.unshift(history, options);\n this.currentHistoryId = history.get(\"id\");\n if (!options.silent) {\n this.trigger(\"new-current\", history, this);\n }\n return this;\n },\n\n toString: function toString() {\n return `HistoryCollection(${this.length},current:${this.currentHistoryId})`;\n }\n});\n\n//==============================================================================\nexport default {\n History: History,\n HistoryCollection: HistoryCollection\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/history/history-model.js"],"names":["History","Backbone","Model","extend","_baseMvc2","default","LoggableMixin","mixin","SearchableModelMixin","_logNamespace","UPDATE_DELAY","defaults","model_class","id","name","state","deleted","contents_active","urlRoot","Galaxy","root","_historyContents2","HistoryContents","tag","contentsClass","historyJSON","options","this","logger","searchAttributes","searchAliases","history","historyId","get","order","_setUpListeners","_setUpCollectionListeners","initialize","updateTimeoutId","on","clearUpdateTimeout","model","newId","contents","error","trigger","apply","arguments","contentsShown","contentsActive","active","shown","includeDeleted","includeHidden","hidden","nice_size","size","_utils2","bytesToString","_localization2","toJSON","_","prototype","call","key","user","isAnonymous","numOfUnfinishedJobs","unfinishedJobIds","length","numOfUnfinishedShownContents","runningAndActive","_fetchContentRelatedAttributes","contentRelatedAttrs","fetch","data","$","param","keys","join","refresh","_this","lastUpdateTime","currentPage","fetchUpdated","done","response","status","xhr","serverResponseDatetime","Date","getResponseHeader","err","checkForUpdates","_this2","fetchFn","delay","_delayThenUpdate","historyData","nonReadyContentCount","parse","parsed","create_time","update_time","contentsOptions","clearTimeout","view","setHistoryId","fetchContents","self","fetchCurrentPage","jQuery","when","purge","save","undelete","copy","current","allDatasets","undefined","postData","history_id","all_datasets","post","setAsCurrent","getJSON","_collectionSuper","_controlledFetchCollection2","InfinitelyScrollingCollection","HistoryCollection","limitOnFirstFetch","limitPerFetch","models","log","currentHistoryId","change:deleted","debug","remove","copied","original","newData","setCurrent","set-as-current","oldCurrentId","_buildFetchData","_buildFetchFilters","superFilters","filters","purged","fetchFirst","limit","encoded_id-in","then","offset","fetchMore","silent","name-dsc","buildComparator","ascending","size-asc","sort","comparators","clone","create","hdas","historyOptions","collection","unshift"],"mappings":"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","file":"../../../scripts/mvc/history/history-model.js","sourcesContent":["import HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport UTILS from \"utils/utils\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Model for a Galaxy history resource - both a record of user\n * tool use and a collection of the datasets those tools produced.\n * @name History\n * @augments Backbone.Model\n */\nvar History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(\n BASE_MVC.mixin(\n BASE_MVC.SearchableModelMixin,\n /** @lends History.prototype */ {\n _logNamespace: \"history\",\n\n /** ms between fetches when checking running jobs/datasets for updates */\n UPDATE_DELAY: 4000,\n\n // values from api (may need more)\n defaults: {\n model_class: \"History\",\n id: null,\n name: \"Unnamed History\",\n state: \"new\",\n\n deleted: false,\n contents_active: {},\n contents_states: {}\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n\n contentsClass: HISTORY_CONTENTS.HistoryContents,\n\n /** What model fields to search with */\n searchAttributes: [\"name\", \"annotation\", \"tags\"],\n\n /** Adding title and singular tag */\n searchAliases: {\n title: \"name\",\n tag: \"tags\"\n },\n\n // ........................................................................ set up/tear down\n /** Set up the model\n * @param {Object} historyJSON model data for this History\n * @param {Object} options any extra settings including logger\n */\n initialize: function(historyJSON, options) {\n options = options || {};\n this.logger = options.logger || null;\n this.log(`${this}.initialize:`, historyJSON, options);\n\n /** HistoryContents collection of the HDAs contained in this history. */\n this.contents = new this.contentsClass([], {\n history: this,\n historyId: this.get(\"id\"),\n order: options.order\n });\n\n this._setUpListeners();\n this._setUpCollectionListeners();\n\n /** cached timeout id for the dataset updater */\n this.updateTimeoutId = null;\n },\n\n /** set up any event listeners for this history including those to the contained HDAs\n * events: error:contents if an error occurred with the contents collection\n */\n _setUpListeners: function() {\n // if the model's id changes ('current' or null -> an actual id), update the contents history_id\n return this.on({\n error: function(model, xhr, options, msg, details) {\n this.clearUpdateTimeout();\n },\n \"change:id\": function(model, newId) {\n if (this.contents) {\n this.contents.historyId = newId;\n }\n }\n });\n },\n\n /** event handlers for the contents submodels */\n _setUpCollectionListeners: function() {\n if (!this.contents) {\n return this;\n }\n // bubble up errors\n return this.listenTo(this.contents, {\n error: function() {\n this.trigger.apply(this, jQuery.makeArray(arguments));\n }\n });\n },\n\n // ........................................................................ derived attributes\n /** */\n contentsShown: function() {\n var contentsActive = this.get(\"contents_active\");\n var shown = contentsActive.active || 0;\n shown += this.contents.includeDeleted ? contentsActive.deleted : 0;\n shown += this.contents.includeHidden ? contentsActive.hidden : 0;\n return shown;\n },\n\n /** convert size in bytes to a more human readable version */\n nice_size: function() {\n var size = this.get(\"size\");\n return size ? UTILS.bytesToString(size, true, 2) : _l(\"(empty)\");\n },\n\n /** override to add nice_size */\n toJSON: function() {\n return _.extend(Backbone.Model.prototype.toJSON.call(this), {\n nice_size: this.nice_size()\n });\n },\n\n /** override to allow getting nice_size */\n get: function(key) {\n if (key === \"nice_size\") {\n return this.nice_size();\n }\n return Backbone.Model.prototype.get.apply(this, arguments);\n },\n\n // ........................................................................ common queries\n /** T/F is this history owned by the current user (Galaxy.user)\n * Note: that this will return false for an anon user even if the history is theirs.\n */\n ownedByCurrUser: function() {\n // no currUser\n if (!Galaxy || !Galaxy.user) {\n return false;\n }\n // user is anon or history isn't owned\n if (Galaxy.user.isAnonymous() || Galaxy.user.id !== this.get(\"user_id\")) {\n return false;\n }\n return true;\n },\n\n /** Return the number of running jobs assoc with this history (note: unknown === 0) */\n numOfUnfinishedJobs: function() {\n var unfinishedJobIds = this.get(\"non_ready_jobs\");\n return unfinishedJobIds ? unfinishedJobIds.length : 0;\n },\n\n /** Return the number of running hda/hdcas in this history (note: unknown === 0) */\n numOfUnfinishedShownContents: function() {\n return this.contents.runningAndActive().length || 0;\n },\n\n // ........................................................................ updates\n _fetchContentRelatedAttributes: function() {\n var contentRelatedAttrs = [\"size\", \"non_ready_jobs\", \"contents_active\", \"hid_counter\"];\n return this.fetch({\n data: $.param({\n keys: contentRelatedAttrs.join(\",\")\n })\n });\n },\n\n /** check for any changes since the last time we updated (or fetch all if ) */\n refresh: function(options) {\n // console.log( this + '.refresh' );\n options = options || {};\n\n // note if there was no previous update time, all summary contents will be fetched\n var lastUpdateTime = this.lastUpdateTime;\n // if we don't flip this, then a fully-fetched list will not be re-checked via fetch\n this.contents.allFetched = false;\n var fetchFn =\n this.contents.currentPage !== 0\n ? () => this.contents.fetchPage(this.contents.currentPage)\n : () => this.contents.fetchUpdated(lastUpdateTime);\n // note: if there was no previous update time, all summary contents will be fetched\n return fetchFn().done((response, status, xhr) => {\n var serverResponseDatetime;\n try {\n serverResponseDatetime = new Date(xhr.getResponseHeader(\"Date\"));\n } catch (err) {}\n this.lastUpdateTime = serverResponseDatetime || new Date();\n this.checkForUpdates(options);\n });\n },\n\n /** continuously fetch updated contents every UPDATE_DELAY ms if this history's datasets or jobs are unfinished */\n checkForUpdates: function(options) {\n // console.log( this + '.checkForUpdates' );\n options = options || {};\n var delay = this.UPDATE_DELAY;\n if (!this.id) {\n return;\n }\n\n var _delayThenUpdate = () => {\n // prevent buildup of updater timeouts by clearing previous if any, then set new and cache id\n this.clearUpdateTimeout();\n this.updateTimeoutId = setTimeout(() => {\n this.refresh(options);\n }, delay);\n };\n\n // if there are still datasets in the non-ready state, recurse into this function with the new time\n var nonReadyContentCount = this.numOfUnfinishedShownContents();\n // console.log( 'nonReadyContentCount:', nonReadyContentCount );\n if (nonReadyContentCount > 0) {\n _delayThenUpdate();\n } else {\n // no datasets are running, but currently runnning jobs may still produce new datasets\n // see if the history has any running jobs and continue to update if so\n // (also update the size for the user in either case)\n this._fetchContentRelatedAttributes().done(historyData => {\n // console.log( 'non_ready_jobs:', historyData.non_ready_jobs );\n if (this.numOfUnfinishedJobs() > 0) {\n _delayThenUpdate();\n } else {\n // otherwise, let listeners know that all updates have stopped\n this.trigger(\"ready\");\n }\n });\n }\n },\n\n /** clear the timeout and the cached timeout id */\n clearUpdateTimeout: function() {\n if (this.updateTimeoutId) {\n clearTimeout(this.updateTimeoutId);\n this.updateTimeoutId = null;\n }\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** fetch this histories data (using options) then it's contents (using contentsOptions) */\n fetchWithContents: function(options, contentsOptions) {\n options = options || {};\n var self = this;\n\n // console.log( this + '.fetchWithContents' );\n // TODO: push down to a base class\n options.view = \"dev-detailed\";\n\n // fetch history then use history data to fetch (paginated) contents\n return this.fetch(options).then(function getContents(history) {\n self.contents.history = self;\n self.contents.setHistoryId(history.id);\n return self.fetchContents(contentsOptions);\n });\n },\n\n /** fetch this histories contents, adjusting options based on the stored history preferences */\n fetchContents: function(options) {\n options = options || {};\n var self = this;\n\n // we're updating, reset the update time\n self.lastUpdateTime = new Date();\n return self.contents.fetchCurrentPage(options);\n },\n\n /** save this history, _Mark_ing it as deleted (just a flag) */\n _delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */\n purge: function(options) {\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true, purged: true }, options);\n },\n /** save this history, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Make a copy of this history on the server\n * @param {Boolean} current if true, set the copy as the new current history (default: true)\n * @param {String} name name of new history (default: none - server sets to: Copy of )\n * @fires copied passed this history and the response JSON from the copy\n * @returns {xhr}\n */\n copy: function(current, name, allDatasets) {\n current = current !== undefined ? current : true;\n if (!this.id) {\n throw new Error(\"You must set the history ID before copying it.\");\n }\n\n var postData = { history_id: this.id };\n if (current) {\n postData.current = true;\n }\n if (name) {\n postData.name = name;\n }\n if (!allDatasets) {\n postData.all_datasets = false;\n }\n postData.view = \"dev-detailed\";\n\n var history = this;\n var copy = jQuery.post(this.urlRoot, postData);\n // if current - queue to setAsCurrent before firing 'copied'\n if (current) {\n return copy.then(response => {\n var newHistory = new History(response);\n return newHistory.setAsCurrent().done(() => {\n history.trigger(\"copied\", history, response);\n });\n });\n }\n return copy.done(response => {\n history.trigger(\"copied\", history, response);\n });\n },\n\n setAsCurrent: function() {\n var history = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/set_as_current?id=${this.id}`);\n\n xhr.done(() => {\n history.trigger(\"set-as-current\", history);\n });\n return xhr;\n },\n\n // ........................................................................ misc\n toString: function() {\n return `History(${this.get(\"id\")},${this.get(\"name\")})`;\n }\n }\n )\n);\n\n//==============================================================================\nvar _collectionSuper = CONTROLLED_FETCH_COLLECTION.InfinitelyScrollingCollection;\n/** @class A collection of histories (per user)\n * that maintains the current history as the first in the collection.\n * New or copied histories become the current history.\n */\nvar HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n model: History,\n /** @type {String} initial order used by collection */\n order: \"update_time\",\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: 10,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 10,\n\n initialize: function(models, options) {\n options = options || {};\n this.log(\"HistoryCollection.initialize\", models, options);\n _collectionSuper.prototype.initialize.call(this, models, options);\n\n /** @type {boolean} should deleted histories be included */\n this.includeDeleted = options.includeDeleted || false;\n\n /** @type {String} encoded id of the history that's current */\n this.currentHistoryId = options.currentHistoryId;\n\n this.setUpListeners();\n // note: models are sent to reset *after* this fn ends; up to this point\n // the collection *is empty*\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n url: function() {\n return this.urlRoot;\n },\n\n /** set up reflexive event handlers */\n setUpListeners: function setUpListeners() {\n return this.on({\n // when a history is deleted, remove it from the collection (if optionally set to do so)\n \"change:deleted\": function(history) {\n // TODO: this becomes complicated when more filters are used\n this.debug(\"change:deleted\", this.includeDeleted, history.get(\"deleted\"));\n if (!this.includeDeleted && history.get(\"deleted\")) {\n this.remove(history);\n }\n },\n // listen for a history copy, setting it to current\n copied: function(original, newData) {\n this.setCurrent(new History(newData, []));\n },\n // when a history is made current, track the id in the collection\n \"set-as-current\": function(history) {\n var oldCurrentId = this.currentHistoryId;\n this.trigger(\"no-longer-current\", oldCurrentId);\n this.currentHistoryId = history.id;\n }\n });\n },\n\n /** override to change view */\n _buildFetchData: function(options) {\n return _.extend(_collectionSuper.prototype._buildFetchData.call(this, options), {\n view: \"dev-detailed\"\n });\n },\n\n /** override to filter out deleted and purged */\n _buildFetchFilters: function(options) {\n var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n } else {\n // force API to return both deleted and non\n //TODO: when the API is updated, remove this\n filters.deleted = null;\n }\n return _.defaults(superFilters, filters);\n },\n\n /** override to fetch current as well (as it may be outside the first 10, etc.) */\n fetchFirst: function(options) {\n var self = this;\n // TODO: batch?\n var xhr = $.when();\n if (this.currentHistoryId) {\n xhr = _collectionSuper.prototype.fetchFirst.call(self, {\n silent: true,\n limit: 1,\n filters: {\n // without these a deleted current history will return [] here and block the other xhr\n purged: \"\",\n deleted: \"\",\n \"encoded_id-in\": this.currentHistoryId\n }\n });\n }\n return xhr.then(() => {\n options = options || {};\n options.offset = 0;\n return self.fetchMore(options);\n });\n },\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_collectionSuper.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", {\n ascending: true\n }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n size: BASE_MVC.buildComparator(\"size\", {\n ascending: false\n }),\n \"size-asc\": BASE_MVC.buildComparator(\"size\", {\n ascending: true\n })\n }),\n\n /** override to always have the current history first */\n sort: function(options) {\n options = options || {};\n var silent = options.silent;\n var currentHistory = this.remove(this.get(this.currentHistoryId));\n _collectionSuper.prototype.sort.call(this, _.defaults({ silent: true }, options));\n this.unshift(currentHistory, { silent: true });\n if (!silent) {\n this.trigger(\"sort\", this, options);\n }\n return this;\n },\n\n /** create a new history and by default set it to be the current history */\n create: function create(data, hdas, historyOptions, xhrOptions) {\n //TODO: .create is actually a collection function that's overridden here\n var collection = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/create_new_current`);\n return xhr.done(newData => {\n collection.setCurrent(new History(newData, [], historyOptions || {}));\n });\n },\n\n /** set the current history to the given history, placing it first in the collection.\n * Pass standard bbone options for use in unshift.\n * @triggers new-current passed history and this collection\n */\n setCurrent: function(history, options) {\n options = options || {};\n // new histories go in the front\n this.unshift(history, options);\n this.currentHistoryId = history.get(\"id\");\n if (!options.silent) {\n this.trigger(\"new-current\", history, this);\n }\n return this;\n },\n\n toString: function toString() {\n return `HistoryCollection(${this.length},current:${this.currentHistoryId})`;\n }\n});\n\n//==============================================================================\nexport default {\n History: History,\n HistoryCollection: HistoryCollection\n};\n"]}
\ No newline at end of file
diff --git a/static/maps/mvc/history/history-view.js.map b/static/maps/mvc/history/history-view.js.map
index db32cd71843a..0c22511889cf 100644
--- a/static/maps/mvc/history/history-view.js.map
+++ b/static/maps/mvc/history/history-view.js.map
@@ -1 +1 @@
-{"version":3,"sources":["mvc/history/history-view.js"],"names":["_super","_listView2","default","ModelListPanel","HistoryView","extend","_logNamespace","HDAViewClass","_hdaLi2","HDAListItemView","HDCAViewClass","_hdcaLi2","HDCAListItemView","collectionClass","_historyContents2","HistoryContents","modelCollectionKey","tagName","className","prototype","emptyMsg","_localization2","noneFoundMsg","initialize","attributes","call","this","linkTarget","detailedFetchTimeoutId","_createDefaultCollection","history","model","freeModel","_clearDetailedFetchTimeout","clearTimeout","_setUpListeners","error","xhr","options","msg","details","clearUpdateTimeout","loading-done","self","_","delay","fetchCollectionCounts","views:ready view:attached view:removed","view","_renderSelectButton","view:attached","scrollTo","loadHistory","errorHandler","contentsOptions","silent","info","historyId","setModel","_historyModel2","History","id","FETCH_COLLECTION_COUNTS_DELAY","always","render","trigger","refreshContents","refresh","$","when","_setUpCollectionListeners","collection","_toggleContentsLoadingIndicator","fetchWithContents","_showLoadingIndicator","speed","callback","$indicator","$el","text","slideDown","isUndefined","fxSpeed","remove","_buildNewRender","$newRender","$where","html","_hideLoadingIndicator","hideSelectors","find","$existing","length","title","classes","faIcon","_renderEmptyMessage","$whereTo","$emptyMsg","$emptyMessage","get","active","empty","append","contents","haveSearchDetails","views","show","$scrollContainer","$list","renderItems","_filterCollection","models","_renderSomeItems","toggle","$paginationControls","searchFor","shouldPaginate","currentPage","last","getLastPage","map","m","_createItemView","push","_renderItemView$el","_filterItem","includeHidden","hidden","includeDeleted","isDeletedOrPurged","_getItemViewClass","contentType","TypeError","_getItemViewOptions","storage","isExpanded","expanded","ownedByCurrUser","_setUpItemViewListeners","panel","listenTo","addExpanded","v","collapsed","removeExpanded","collapseAll","clearExpanded","getSelectedModels","events","clone","click > .controls .prev","click > .controls .next","change > .controls .pages","click .messages [class$=message]","_clickPrevPage","ev","_clickNextPage","_changePageSelect","page","val","currentTarget","toggleShowDeleted","undefined","setIncludeDeleted","fetchCurrentPage","renderAll","toggleShowHidden","store","setIncludeHidden","_firstSearch","inputSelector","searchInput","progressivelyFetchDetails","limit","offset","done","searchItems","clearSearch","status","readyState","isString","errorModal","message","_errorModal2","badGatewayErrorModal","ajaxErrorModal","$messages","children","fadeOut","scrollToHid","hid","scrollToItem","first","viewsWhereModel","ordinalIndicator","number","numStr","charAt","toString","templates","mainTemplate","controlsTemplate","wrapTemplate","controls","pagination","paginationTemplate","_baseMvc2","el"],"mappings":"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","file":"../../../scripts/mvc/history/history-view.js","sourcesContent":["import LIST_VIEW from \"mvc/list/list-view\";\nimport HISTORY_MODEL from \"mvc/history/history-model\";\nimport HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport HDA_LI from \"mvc/history/hda-li\";\nimport HDCA_LI from \"mvc/history/hdca-li\";\nimport USER from \"mvc/user/user-model\";\nimport ERROR_MODAL from \"mvc/ui/error-modal\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/search-input\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a history model.\n * Allows:\n * changing the loaded history\n * displaying data, info, and download\n * tracking history attrs: size, tags, annotations, name, etc.\n * Does not allow:\n * changing the name\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar HistoryView = _super.extend(\n /** @lends HistoryView.prototype */ {\n _logNamespace: \"history\",\n\n /** class to use for constructing the HDA views */\n HDAViewClass: HDA_LI.HDAListItemView,\n /** class to use for constructing the HDCA views */\n HDCAViewClass: HDCA_LI.HDCAListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: HISTORY_CONTENTS.HistoryContents,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n tagName: \"div\",\n className: `${_super.prototype.className} history-panel`,\n\n /** string to display when the collection is empty */\n emptyMsg: _l(\"This history is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: _l(\"No matching datasets found\"),\n /** string used for search placeholder */\n searchPlaceholder: _l(\"search datasets\"),\n\n /** @type {Number} ms to wait after history load to fetch/decorate hdcas with element_count */\n FETCH_COLLECTION_COUNTS_DELAY: 2000,\n\n // ......................................................................... SET UP\n /** Set up the view, bind listeners.\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n // ---- instance vars\n // control contents/behavior based on where (and in what context) the panel is being used\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n /** timeout id for detailed fetch of collection counts, etc... */\n this.detailedFetchTimeoutId = null;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function() {\n // override\n return new this.collectionClass([], {\n history: this.model\n });\n },\n\n /** In this override, clear the update timer on the model */\n freeModel: function() {\n _super.prototype.freeModel.call(this);\n if (this.model) {\n this.model.clearUpdateTimeout();\n }\n this._clearDetailedFetchTimeout();\n return this;\n },\n\n /** clear the timeout and the cached timeout id */\n _clearDetailedFetchTimeout: function() {\n if (this.detailedFetchTimeoutId) {\n clearTimeout(this.detailedFetchTimeoutId);\n this.detailedFetchTimeoutId = null;\n }\n },\n\n /** create any event listeners for the panel\n * @fires: rendered:initial on the first render\n * @fires: empty-history when switching to a history with no contents or creating a new history\n */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n this.on({\n error: function(model, xhr, options, msg, details) {\n this.errorHandler(model, xhr, options, msg, details);\n },\n \"loading-done\": function() {\n var self = this;\n // after the initial load, decorate with more time consuming fields (like HDCA element_counts)\n self.detailedFetchTimeoutId = _.delay(() => {\n self.detailedFetchTimeoutId = null;\n self.model.contents.fetchCollectionCounts();\n }, self.FETCH_COLLECTION_COUNTS_DELAY);\n },\n \"views:ready view:attached view:removed\": function(view) {\n this._renderSelectButton();\n },\n \"view:attached\": function(view) {\n this.scrollTo(0);\n }\n });\n // this.on( 'all', function(){ console.debug( arguments ); });\n },\n\n // ------------------------------------------------------------------------ loading history/hda models\n /** load the history with the given id then it's contents, sending ajax options to both */\n loadHistory: function(historyId, options, contentsOptions) {\n contentsOptions = _.extend(contentsOptions || { silent: true });\n this.info(\"loadHistory:\", historyId, options, contentsOptions);\n var self = this;\n self.setModel(new HISTORY_MODEL.History({ id: historyId }));\n\n contentsOptions.silent = true;\n self.trigger(\"loading\");\n return self.model.fetchWithContents(options, contentsOptions).always(() => {\n self.render();\n self.trigger(\"loading-done\");\n });\n },\n\n /** convenience alias to the model. Updates the item list only (not the history) */\n refreshContents: function(options) {\n if (this.model) {\n return this.model.refresh(options);\n }\n // may have callbacks - so return an empty promise\n return $.when();\n },\n\n /** Override to reset web storage when the id changes (since it needs the id) */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n return this.listenTo(this.collection, {\n // 'all' : function(){ console.log( this.collection + ':', arguments ); },\n \"fetching-more\": function() {\n this._toggleContentsLoadingIndicator(true);\n this.$emptyMessage().hide();\n },\n \"fetching-more-done\": function() {\n this._toggleContentsLoadingIndicator(false);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function(msg, speed, callback) {\n var $indicator = $('
');\n this.$el.html($indicator.text(msg).slideDown(!_.isUndefined(speed) ? speed : this.fxSpeed));\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function(speed) {\n // make speed a bit slower to compensate for slow rendering of up to 500 contents\n this.$(\".loading-indicator\").slideUp(!_.isUndefined(speed) ? speed : this.fxSpeed + 200, function() {\n $(this).remove();\n });\n },\n\n /** In this override, add a btn to toggle the selectors */\n _buildNewRender: function() {\n var $newRender = _super.prototype._buildNewRender.call(this);\n this._renderSelectButton($newRender);\n return $newRender;\n },\n\n /** button for starting select mode */\n _renderSelectButton: function($where) {\n $where = $where || this.$el;\n // do not render selector option if no actions\n if (!this.multiselectActions().length) {\n return null;\n }\n // do not render (and remove even) if nothing to select\n if (!this.views.length) {\n this.hideSelectors();\n $where.find(\".controls .actions .show-selectors-btn\").remove();\n return null;\n }\n // don't bother rendering if there's one already\n var $existing = $where.find(\".controls .actions .show-selectors-btn\");\n if ($existing.length) {\n return $existing;\n }\n\n return faIconButton({\n title: _l(\"Operations on multiple datasets\"),\n classes: \"show-selectors-btn\",\n faIcon: \"fa-check-square-o\"\n }).prependTo($where.find(\".controls .actions\"));\n },\n\n /** override to avoid showing intial empty message using contents_active */\n _renderEmptyMessage: function($whereTo) {\n var self = this;\n var $emptyMsg = self.$emptyMessage($whereTo);\n\n var empty = self.model.get(\"contents_active\").active <= 0;\n if (empty) {\n return $emptyMsg\n .empty()\n .append(self.emptyMsg)\n .show();\n } else if (self.searchFor && self.model.contents.haveSearchDetails() && !self.views.length) {\n return $emptyMsg\n .empty()\n .append(self.noneFoundMsg)\n .show();\n }\n $emptyMsg.hide();\n return $();\n },\n\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function($where) {\n // override or set via attributes.$scrollContainer\n return this.$list($where);\n },\n\n // ------------------------------------------------------------------------ subviews\n _toggleContentsLoadingIndicator: function(show) {\n if (!show) {\n this.$list()\n .find(\".contents-loading-indicator\")\n .remove();\n } else {\n this.$list().html(\n '
' + '
'\n );\n }\n },\n\n /** override to render pagination also */\n renderItems: function($whereTo) {\n // console.log( this + '.renderItems-----------------', new Date() );\n $whereTo = $whereTo || this.$el;\n var self = this;\n var $list = self.$list($whereTo);\n\n // TODO: bootstrap hack to remove orphaned tooltips\n $(\".tooltip\").remove();\n\n $list.empty();\n self.views = [];\n\n var models = self._filterCollection();\n if (models.length) {\n self._renderPagination($whereTo);\n self.views = self._renderSomeItems(models, $list);\n } else {\n // TODO: consolidate with _renderPagination above by (???) passing in models/length?\n $whereTo.find(\"> .controls .list-pagination\").empty();\n }\n self._renderEmptyMessage($whereTo).toggle(!models.length);\n\n self.trigger(\"views:ready\", self.views);\n return self.views;\n },\n\n /** render pagination controls if not searching and contents says we're paginating */\n _renderPagination: function($whereTo) {\n var $paginationControls = $whereTo.find(\"> .controls .list-pagination\");\n if (this.searchFor || !this.model.contents.shouldPaginate()) return $paginationControls.empty();\n\n $paginationControls.html(\n this.templates.pagination(\n {\n // pagination is 1-based for the user\n current: this.model.contents.currentPage + 1,\n last: this.model.contents.getLastPage() + 1\n },\n this\n )\n );\n $paginationControls.find(\"select.pages\").tooltip();\n return $paginationControls;\n },\n\n /** render a subset of the entire collection (client-side pagination) */\n _renderSomeItems: function(models, $list) {\n var self = this;\n var views = [];\n $list.append(\n models.map(m => {\n var view = self._createItemView(m);\n views.push(view);\n return self._renderItemView$el(view);\n })\n );\n return views;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** in this override, check if the contents would also display based on includeDeleted/hidden */\n _filterItem: function(model) {\n var self = this;\n var contents = self.model.contents;\n return (\n (contents.includeHidden || !model.hidden()) &&\n (contents.includeDeleted || !model.isDeletedOrPurged()) &&\n _super.prototype._filterItem.call(self, model)\n );\n },\n\n /** In this override, since history contents are mixed,\n * get the appropo view class based on history_content_type\n */\n _getItemViewClass: function(model) {\n var contentType = model.get(\"history_content_type\");\n switch (contentType) {\n case \"dataset\":\n return this.HDAViewClass;\n case \"dataset_collection\":\n return this.HDCAViewClass;\n }\n throw new TypeError(`Unknown history_content_type: ${contentType}`);\n },\n\n /** in this override, add a linktarget, and expand if id is in web storage */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n expanded: this.model.contents.storage.isExpanded(model.id),\n hasUser: this.model.ownedByCurrUser()\n });\n },\n\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n //TODO: send from content view: this.model.collection.storage.addExpanded\n // maintain a list of items whose bodies are expanded\n return panel.listenTo(view, {\n expanded: function(v) {\n panel.model.contents.storage.addExpanded(v.model);\n },\n collapsed: function(v) {\n panel.model.contents.storage.removeExpanded(v.model);\n }\n });\n },\n\n /** override to remove expandedIds from webstorage */\n collapseAll: function() {\n this.model.contents.storage.clearExpanded();\n _super.prototype.collapseAll.call(this);\n },\n\n // ------------------------------------------------------------------------ selection\n /** Override to correctly set the historyId of the new collection */\n getSelectedModels: function() {\n var collection = _super.prototype.getSelectedModels.call(this);\n collection.historyId = this.collection.historyId;\n return collection;\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click > .controls .prev\": \"_clickPrevPage\",\n \"click > .controls .next\": \"_clickNextPage\",\n \"change > .controls .pages\": \"_changePageSelect\",\n // allow (error) messages to be clicked away\n \"click .messages [class$=message]\": \"clearMessages\"\n }),\n\n _clickPrevPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchPrevPage();\n },\n\n _clickNextPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchNextPage();\n },\n\n _changePageSelect: function(ev) {\n this.model.clearUpdateTimeout();\n var page = $(ev.currentTarget).val();\n this.model.contents.fetchPage(page);\n },\n\n /** Toggle and store the deleted visibility and re-render items\n * @returns {Boolean} new setting\n */\n toggleShowDeleted: function(show, options) {\n show = show !== undefined ? show : !this.model.contents.includeDeleted;\n var self = this;\n var contents = self.model.contents;\n contents.setIncludeDeleted(show, options);\n self.trigger(\"show-deleted\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** Toggle and store whether to render explicity hidden contents\n * @returns {Boolean} new setting\n */\n toggleShowHidden: function(show, store, options) {\n // console.log( 'toggleShowHidden', show, store );\n show = show !== undefined ? show : !this.model.contents.includeHidden;\n var self = this;\n var contents = self.model.contents;\n contents.setIncludeHidden(show, options);\n self.trigger(\"show-hidden\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** On the first search, if there are no details - load them, then search */\n _firstSearch: function(searchFor) {\n var self = this;\n var inputSelector = \"> .controls .search-input\";\n this.log(\"onFirstSearch\", searchFor);\n\n // if the contents already have enough details to search, search and return now\n if (self.model.contents.haveSearchDetails()) {\n self.searchItems(searchFor);\n return;\n }\n\n // otherwise, load the details progressively here\n self.$(inputSelector).searchInput(\"toggle-loading\");\n // set this now so that only results will show during progress\n self.searchFor = searchFor;\n var xhr = self.model.contents\n .progressivelyFetchDetails({ silent: true })\n .progress((response, limit, offset) => {\n self.renderItems();\n self.trigger(\"search:loading-progress\", limit, offset);\n })\n .always(() => {\n self.$el.find(inputSelector).searchInput(\"toggle-loading\");\n })\n .done(() => {\n self.searchItems(searchFor, \"force\");\n });\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function(searchFor) {\n var self = this;\n if (!self.searchFor) return self;\n //self.log( 'onSearchClear', self );\n self.searchFor = \"\";\n self.trigger(\"search:clear\", self);\n self.$(\"> .controls .search-query\").val(\"\");\n // NOTE: silent + render prevents collection update event with merge only\n // - which causes an empty page due to event handler above\n self.model.contents.fetchCurrentPage({ silent: true }).done(() => {\n self.renderItems();\n });\n return self;\n },\n\n // ........................................................................ error handling\n /** Event handler for errors (from the panel, the history, or the history's contents)\n * Alternately use two strings for model and xhr to use custom message and title (respectively)\n * @param {Model or View} model the (Backbone) source of the error\n * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error\n * @param {Object} options the options map commonly used with bbone ajax\n */\n errorHandler: function(model, xhr, options) {\n //TODO: to mixin or base model\n // interrupted ajax or no connection\n if (xhr && xhr.status === 0 && xhr.readyState === 0) {\n // return ERROR_MODAL.offlineErrorModal();\n // fail silently\n return;\n }\n // otherwise, leave something to report in the console\n this.error(model, xhr, options);\n // and feedback to a modal\n // if sent two strings (and possibly details as 'options'), use those as message and title\n if (_.isString(model) && _.isString(xhr)) {\n var message = model;\n var title = xhr;\n return ERROR_MODAL.errorModal(message, title, options);\n }\n // bad gateway\n // TODO: possibly to global handler\n if (xhr && xhr.status === 502) {\n return ERROR_MODAL.badGatewayErrorModal();\n }\n return ERROR_MODAL.ajaxErrorModal(model, xhr, options);\n },\n\n /** Remove all messages from the panel. */\n clearMessages: function(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target.fadeOut(this.fxSpeed, function() {\n $(this).remove();\n });\n return this;\n },\n\n // ........................................................................ scrolling\n /** Scrolls the panel to show the content sub-view with the given hid.\n * @param {Integer} hid the hid of item to scroll into view\n * @returns {HistoryView} the panel\n */\n scrollToHid: function(hid) {\n return this.scrollToItem(_.first(this.viewsWhereModel({ hid: hid })));\n },\n\n // ........................................................................ misc\n /** utility for adding -st, -nd, -rd, -th to numbers */\n ordinalIndicator: function(number) {\n var numStr = `${number}`;\n switch (numStr.charAt(numStr.length - 1)) {\n case \"1\":\n return `${numStr}st`;\n case \"2\":\n return `${numStr}nd`;\n case \"3\":\n return `${numStr}rd`;\n default:\n return `${numStr}th`;\n }\n },\n\n /** Return a string rep of the history */\n toString: function() {\n return `HistoryView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryView.prototype.templates = (() => {\n var mainTemplate = BASE_MVC.wrapTemplate([\n // temp container\n \"
\",\n '',\n '
',\n '',\n \"
\"\n ]);\n\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\",\n\n // add tags and annotations\n '',\n '',\n\n '
',\n '',\n \"
\",\n\n '
',\n '
',\n '\",\n '\",\n \"
\",\n '
',\n \"
\",\n \"
\",\n '',\n \"
\"\n ],\n \"history\"\n );\n\n var paginationTemplate = BASE_MVC.wrapTemplate(\n [\n '',\n '\",\n ''\n ],\n \"pages\"\n );\n\n return _.extend(_.clone(_super.prototype.templates), {\n el: mainTemplate,\n controls: controlsTemplate,\n pagination: paginationTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n HistoryView: HistoryView\n};\n"]}
\ No newline at end of file
+{"version":3,"sources":["mvc/history/history-view.js"],"names":["_super","_listView2","default","ModelListPanel","HistoryView","extend","_logNamespace","HDAViewClass","_hdaLi2","HDAListItemView","HDCAViewClass","_hdcaLi2","HDCAListItemView","collectionClass","_historyContents2","HistoryContents","modelCollectionKey","tagName","className","prototype","emptyMsg","_localization2","noneFoundMsg","initialize","attributes","call","this","linkTarget","detailedFetchTimeoutId","_createDefaultCollection","history","model","freeModel","_clearDetailedFetchTimeout","clearTimeout","_setUpListeners","_this","error","xhr","options","msg","details","clearUpdateTimeout","loading-done","_","delay","contents","fetchCollectionCounts","view","view:attached","scrollTo","contentsOptions","_this2","silent","setModel","errorHandler","History","historyId","trigger","always","render","refreshContents","refresh","$","when","_setUpCollectionListeners","loadHistory","listenTo","collection","info","_toggleContentsLoadingIndicator","$emptyMessage","hide","_showLoadingIndicator","speed","callback","$el","$indicator","text","slideDown","isUndefined","fxSpeed","_hideLoadingIndicator","slideUp","remove","_buildNewRender","$newRender","_renderSelectButton","$where","multiselectActions","length","html","hideSelectors","find","$existing","_faIconButton2","faIcon","prependTo","$whereTo","get","active","$emptyMsg","empty","append","show","haveSearchDetails","views","title","$list","_renderEmptyMessage","searchFor","renderItems","models","_renderPagination","_renderSomeItems","toggle","_filterCollection","shouldPaginate","$paginationControls","templates","pagination","current","currentPage","tooltip","_this3","m","last","getLastPage","push","_filterItem","map","includeHidden","hidden","includeDeleted","_renderItemView$el","_getItemViewClass","contentType","_getItemViewOptions","TypeError","expanded","storage","isExpanded","id","hasUser","ownedByCurrUser","_setUpItemViewListeners","panel","v","addExpanded","removeExpanded","collapsed","clearExpanded","collapseAll","events","getSelectedModels","click > .controls .prev","click > .controls .next","change > .controls .pages","click .messages [class$=message]","_clickPrevPage","ev","fetchPrevPage","_clickNextPage","fetchNextPage","_changePageSelect","currentTarget","val","page","toggleShowDeleted","fetchPage","setIncludeDeleted","fetchCurrentPage","renderAll","undefined","setIncludeHidden","toggleShowHidden","_firstSearch","searchItems","log","searchInput","progressivelyFetchDetails","progress","response","limit","offset","_this4","inputSelector","clearSearch","done","_this5","status","readyState","isString","message","_errorModal2","errorModal","badGatewayErrorModal","ajaxErrorModal","clearMessages","$messages","children","fadeOut","scrollToHid","hid","scrollToItem","first","viewsWhereModel","ordinalIndicator","number","numStr","toString","controlsTemplate","_baseMvc2","wrapTemplate","el","controls","paginationTemplate","clone"],"mappings":"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","file":"../../../scripts/mvc/history/history-view.js","sourcesContent":["import LIST_VIEW from \"mvc/list/list-view\";\nimport HISTORY_MODEL from \"mvc/history/history-model\";\nimport HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport HDA_LI from \"mvc/history/hda-li\";\nimport HDCA_LI from \"mvc/history/hdca-li\";\nimport USER from \"mvc/user/user-model\";\nimport ERROR_MODAL from \"mvc/ui/error-modal\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/search-input\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a history model.\n * Allows:\n * changing the loaded history\n * displaying data, info, and download\n * tracking history attrs: size, tags, annotations, name, etc.\n * Does not allow:\n * changing the name\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar HistoryView = _super.extend(\n /** @lends HistoryView.prototype */ {\n _logNamespace: \"history\",\n\n /** class to use for constructing the HDA views */\n HDAViewClass: HDA_LI.HDAListItemView,\n /** class to use for constructing the HDCA views */\n HDCAViewClass: HDCA_LI.HDCAListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: HISTORY_CONTENTS.HistoryContents,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n tagName: \"div\",\n className: `${_super.prototype.className} history-panel`,\n\n /** string to display when the collection is empty */\n emptyMsg: _l(\"This history is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: _l(\"No matching datasets found\"),\n /** string used for search placeholder */\n searchPlaceholder: _l(\"search datasets\"),\n\n /** @type {Number} ms to wait after history load to fetch/decorate hdcas with element_count */\n FETCH_COLLECTION_COUNTS_DELAY: 2000,\n\n // ......................................................................... SET UP\n /** Set up the view, bind listeners.\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n // ---- instance vars\n // control contents/behavior based on where (and in what context) the panel is being used\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n /** timeout id for detailed fetch of collection counts, etc... */\n this.detailedFetchTimeoutId = null;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function() {\n // override\n return new this.collectionClass([], {\n history: this.model\n });\n },\n\n /** In this override, clear the update timer on the model */\n freeModel: function() {\n _super.prototype.freeModel.call(this);\n if (this.model) {\n this.model.clearUpdateTimeout();\n }\n this._clearDetailedFetchTimeout();\n return this;\n },\n\n /** clear the timeout and the cached timeout id */\n _clearDetailedFetchTimeout: function() {\n if (this.detailedFetchTimeoutId) {\n clearTimeout(this.detailedFetchTimeoutId);\n this.detailedFetchTimeoutId = null;\n }\n },\n\n /** create any event listeners for the panel\n * @fires: rendered:initial on the first render\n * @fires: empty-history when switching to a history with no contents or creating a new history\n */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n this.on({\n error: function(model, xhr, options, msg, details) {\n this.errorHandler(model, xhr, options, msg, details);\n },\n \"loading-done\": () => {\n // after the initial load, decorate with more time consuming fields (like HDCA element_counts)\n this.detailedFetchTimeoutId = _.delay(() => {\n this.detailedFetchTimeoutId = null;\n this.model.contents.fetchCollectionCounts();\n }, this.FETCH_COLLECTION_COUNTS_DELAY);\n },\n \"views:ready view:attached view:removed\": function(view) {\n this._renderSelectButton();\n },\n \"view:attached\": function(view) {\n this.scrollTo(0);\n }\n });\n // this.on( 'all', function(){ console.debug( arguments ); });\n },\n\n // ------------------------------------------------------------------------ loading history/hda models\n /** load the history with the given id then it's contents, sending ajax options to both */\n loadHistory: function(historyId, options, contentsOptions) {\n contentsOptions = _.extend(contentsOptions || { silent: true });\n this.info(\"loadHistory:\", historyId, options, contentsOptions);\n this.setModel(new HISTORY_MODEL.History({ id: historyId }));\n\n contentsOptions.silent = true;\n this.trigger(\"loading\");\n return this.model.fetchWithContents(options, contentsOptions).always(() => {\n this.render();\n this.trigger(\"loading-done\");\n });\n },\n\n /** convenience alias to the model. Updates the item list only (not the history) */\n refreshContents: function(options) {\n if (this.model) {\n return this.model.refresh(options);\n }\n // may have callbacks - so return an empty promise\n return $.when();\n },\n\n /** Override to reset web storage when the id changes (since it needs the id) */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n return this.listenTo(this.collection, {\n // 'all' : function(){ console.log( this.collection + ':', arguments ); },\n \"fetching-more\": function() {\n this._toggleContentsLoadingIndicator(true);\n this.$emptyMessage().hide();\n },\n \"fetching-more-done\": function() {\n this._toggleContentsLoadingIndicator(false);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function(msg, speed, callback) {\n var $indicator = $('
');\n this.$el.html($indicator.text(msg).slideDown(!_.isUndefined(speed) ? speed : this.fxSpeed));\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function(speed) {\n // make speed a bit slower to compensate for slow rendering of up to 500 contents\n this.$(\".loading-indicator\").slideUp(!_.isUndefined(speed) ? speed : this.fxSpeed + 200, function() {\n $(this).remove();\n });\n },\n\n /** In this override, add a btn to toggle the selectors */\n _buildNewRender: function() {\n var $newRender = _super.prototype._buildNewRender.call(this);\n this._renderSelectButton($newRender);\n return $newRender;\n },\n\n /** button for starting select mode */\n _renderSelectButton: function($where) {\n $where = $where || this.$el;\n // do not render selector option if no actions\n if (!this.multiselectActions().length) {\n return null;\n }\n // do not render (and remove even) if nothing to select\n if (!this.views.length) {\n this.hideSelectors();\n $where.find(\".controls .actions .show-selectors-btn\").remove();\n return null;\n }\n // don't bother rendering if there's one already\n var $existing = $where.find(\".controls .actions .show-selectors-btn\");\n if ($existing.length) {\n return $existing;\n }\n\n return faIconButton({\n title: _l(\"Operations on multiple datasets\"),\n classes: \"show-selectors-btn\",\n faIcon: \"fa-check-square-o\"\n }).prependTo($where.find(\".controls .actions\"));\n },\n\n /** override to avoid showing intial empty message using contents_active */\n _renderEmptyMessage: function($whereTo) {\n var $emptyMsg = this.$emptyMessage($whereTo);\n var empty = this.model.get(\"contents_active\").active <= 0;\n if (empty) {\n return $emptyMsg\n .empty()\n .append(this.emptyMsg)\n .show();\n } else if (this.searchFor && this.model.contents.haveSearchDetails() && !this.views.length) {\n return $emptyMsg\n .empty()\n .append(this.noneFoundMsg)\n .show();\n }\n $emptyMsg.hide();\n return $();\n },\n\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function($where) {\n // override or set via attributes.$scrollContainer\n return this.$list($where);\n },\n\n // ------------------------------------------------------------------------ subviews\n _toggleContentsLoadingIndicator: function(show) {\n if (!show) {\n this.$list()\n .find(\".contents-loading-indicator\")\n .remove();\n } else {\n this.$list().html(\n '
' + '
'\n );\n }\n },\n\n /** override to render pagination also */\n renderItems: function($whereTo) {\n // console.log( this + '.renderItems-----------------', new Date() );\n $whereTo = $whereTo || this.$el;\n var $list = this.$list($whereTo);\n\n // TODO: bootstrap hack to remove orphaned tooltips\n $(\".tooltip\").remove();\n\n $list.empty();\n this.views = [];\n\n var models = this._filterCollection();\n if (models.length) {\n this._renderPagination($whereTo);\n this.views = this._renderSomeItems(models, $list);\n } else {\n // TODO: consolidate with _renderPagination above by (???) passing in models/length?\n $whereTo.find(\"> .controls .list-pagination\").empty();\n }\n this._renderEmptyMessage($whereTo).toggle(!models.length);\n\n this.trigger(\"views:ready\", this.views);\n return this.views;\n },\n\n /** render pagination controls if not searching and contents says we're paginating */\n _renderPagination: function($whereTo) {\n var $paginationControls = $whereTo.find(\"> .controls .list-pagination\");\n if (this.searchFor || !this.model.contents.shouldPaginate()) return $paginationControls.empty();\n\n $paginationControls.html(\n this.templates.pagination(\n {\n // pagination is 1-based for the user\n current: this.model.contents.currentPage + 1,\n last: this.model.contents.getLastPage() + 1\n },\n this\n )\n );\n $paginationControls.find(\"select.pages\").tooltip();\n return $paginationControls;\n },\n\n /** render a subset of the entire collection (client-side pagination) */\n _renderSomeItems: function(models, $list) {\n var views = [];\n $list.append(\n models.map(m => {\n var view = this._createItemView(m);\n views.push(view);\n return this._renderItemView$el(view);\n })\n );\n return views;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** in this override, check if the contents would also display based on includeDeleted/hidden */\n _filterItem: function(model) {\n var contents = this.model.contents;\n return (\n (contents.includeHidden || !model.hidden()) &&\n (contents.includeDeleted || !model.isDeletedOrPurged()) &&\n _super.prototype._filterItem.call(this, model)\n );\n },\n\n /** In this override, since history contents are mixed,\n * get the appropo view class based on history_content_type\n */\n _getItemViewClass: function(model) {\n var contentType = model.get(\"history_content_type\");\n switch (contentType) {\n case \"dataset\":\n return this.HDAViewClass;\n case \"dataset_collection\":\n return this.HDCAViewClass;\n }\n throw new TypeError(`Unknown history_content_type: ${contentType}`);\n },\n\n /** in this override, add a linktarget, and expand if id is in web storage */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n expanded: this.model.contents.storage.isExpanded(model.id),\n hasUser: this.model.ownedByCurrUser()\n });\n },\n\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n //TODO: send from content view: this.model.collection.storage.addExpanded\n // maintain a list of items whose bodies are expanded\n return panel.listenTo(view, {\n expanded: function(v) {\n panel.model.contents.storage.addExpanded(v.model);\n },\n collapsed: function(v) {\n panel.model.contents.storage.removeExpanded(v.model);\n }\n });\n },\n\n /** override to remove expandedIds from webstorage */\n collapseAll: function() {\n this.model.contents.storage.clearExpanded();\n _super.prototype.collapseAll.call(this);\n },\n\n // ------------------------------------------------------------------------ selection\n /** Override to correctly set the historyId of the new collection */\n getSelectedModels: function() {\n var collection = _super.prototype.getSelectedModels.call(this);\n collection.historyId = this.collection.historyId;\n return collection;\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click > .controls .prev\": \"_clickPrevPage\",\n \"click > .controls .next\": \"_clickNextPage\",\n \"change > .controls .pages\": \"_changePageSelect\",\n // allow (error) messages to be clicked away\n \"click .messages [class$=message]\": \"clearMessages\"\n }),\n\n _clickPrevPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchPrevPage();\n },\n\n _clickNextPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchNextPage();\n },\n\n _changePageSelect: function(ev) {\n this.model.clearUpdateTimeout();\n var page = $(ev.currentTarget).val();\n this.model.contents.fetchPage(page);\n },\n\n /** Toggle and store the deleted visibility and re-render items\n * @returns {Boolean} new setting\n */\n toggleShowDeleted: function(show, options) {\n show = show !== undefined ? show : !this.model.contents.includeDeleted;\n var contents = this.model.contents;\n contents.setIncludeDeleted(show, options);\n this.trigger(\"show-deleted\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** Toggle and store whether to render explicity hidden contents\n * @returns {Boolean} new setting\n */\n toggleShowHidden: function(show, store, options) {\n // console.log( 'toggleShowHidden', show, store );\n show = show !== undefined ? show : !this.model.contents.includeHidden;\n var contents = this.model.contents;\n contents.setIncludeHidden(show, options);\n this.trigger(\"show-hidden\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** On the first search, if there are no details - load them, then search */\n _firstSearch: function(searchFor) {\n var inputSelector = \"> .controls .search-input\";\n this.log(\"onFirstSearch\", searchFor);\n\n // if the contents already have enough details to search, search and return now\n if (this.model.contents.haveSearchDetails()) {\n this.searchItems(searchFor);\n return;\n }\n\n // otherwise, load the details progressively here\n this.$(inputSelector).searchInput(\"toggle-loading\");\n // set this now so that only results will show during progress\n this.searchFor = searchFor;\n var xhr = this.model.contents\n .progressivelyFetchDetails({ silent: true })\n .progress((response, limit, offset) => {\n this.renderItems();\n this.trigger(\"search:loading-progress\", limit, offset);\n })\n .always(() => {\n this.$el.find(inputSelector).searchInput(\"toggle-loading\");\n })\n .done(() => {\n this.searchItems(searchFor, \"force\");\n });\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function(searchFor) {\n if (!this.searchFor) return this;\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n // NOTE: silent + render prevents collection update event with merge only\n // - which causes an empty page due to event handler above\n this.model.contents.fetchCurrentPage({ silent: true }).done(() => {\n this.renderItems();\n });\n return this;\n },\n\n // ........................................................................ error handling\n /** Event handler for errors (from the panel, the history, or the history's contents)\n * Alternately use two strings for model and xhr to use custom message and title (respectively)\n * @param {Model or View} model the (Backbone) source of the error\n * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error\n * @param {Object} options the options map commonly used with bbone ajax\n */\n errorHandler: function(model, xhr, options) {\n //TODO: to mixin or base model\n // interrupted ajax or no connection\n if (xhr && xhr.status === 0 && xhr.readyState === 0) {\n // return ERROR_MODAL.offlineErrorModal();\n // fail silently\n return;\n }\n // otherwise, leave something to report in the console\n this.error(model, xhr, options);\n // and feedback to a modal\n // if sent two strings (and possibly details as 'options'), use those as message and title\n if (_.isString(model) && _.isString(xhr)) {\n var message = model;\n var title = xhr;\n return ERROR_MODAL.errorModal(message, title, options);\n }\n // bad gateway\n // TODO: possibly to global handler\n if (xhr && xhr.status === 502) {\n return ERROR_MODAL.badGatewayErrorModal();\n }\n return ERROR_MODAL.ajaxErrorModal(model, xhr, options);\n },\n\n /** Remove all messages from the panel. */\n clearMessages: function(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target.fadeOut(this.fxSpeed, function() {\n $(this).remove();\n });\n return this;\n },\n\n // ........................................................................ scrolling\n /** Scrolls the panel to show the content sub-view with the given hid.\n * @param {Integer} hid the hid of item to scroll into view\n * @returns {HistoryView} the panel\n */\n scrollToHid: function(hid) {\n return this.scrollToItem(_.first(this.viewsWhereModel({ hid: hid })));\n },\n\n // ........................................................................ misc\n /** utility for adding -st, -nd, -rd, -th to numbers */\n ordinalIndicator: function(number) {\n var numStr = `${number}`;\n switch (numStr.charAt(numStr.length - 1)) {\n case \"1\":\n return `${numStr}st`;\n case \"2\":\n return `${numStr}nd`;\n case \"3\":\n return `${numStr}rd`;\n default:\n return `${numStr}th`;\n }\n },\n\n /** Return a string rep of the history */\n toString: function() {\n return `HistoryView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryView.prototype.templates = (() => {\n var mainTemplate = () =>\n `
\n \n
\n ',\n
`;\n\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
").append(t.title)))}),this.$cover[this.model.get("enabled")&&"hide"||"show"]()}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=function(e){return e&&e.__esModule?e:{default:e}}(a);t.default=e.View.extend({initialize:function(t){this.model=new e.Model({cls:"upload-ftp",class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o",class_partial:"upload-icon-button fa fa-minus-square-o",help_enabled:!0,help_text:"This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at "+t.ftp_upload_site+" using your Galaxy credentials.",collection:null,onchange:function(){},onadd:function(){},onremove:function(){}}).set(t),this.collection=this.model.get("collection"),this.setElement(this._template()),this.$content=this.$(".upload-ftp-content"),this.$wait=this.$(".upload-ftp-wait"),this.$help=this.$(".upload-ftp-help"),this.$number=this.$(".upload-ftp-number"),this.$disk=this.$(".upload-ftp-disk"),this.$body=this.$(".upload-ftp-body"),this.$warning=this.$(".upload-ftp-warning"),this.$select=this.$(".upload-ftp-select-all"),this.render()},render:function(){var e=this;this.$wait.show(),this.$content.hide(),this.$warning.hide(),this.$help.hide(),n.ajax({url:Galaxy.root+"api/remote_files",method:"GET",success:function(t){e.model.set("ftp_files",t),e._index(),e._renderTable()},error:function(){e._renderTable()}})},_renderTable:function(){var e=this,t=this.model.get("ftp_files");if(this.rows=[],t&&t.length>0){this.$body.empty();var i=0;s.each(t,function(t){e.rows.push(e._renderRow(t)),i+=t.size}),this.$number.html(t.length+" files"),this.$disk.html(o.default.bytesToString(i,!0)),this.collection&&(this.$("._has_collection").show(),this.$select.addClass(this.model.get("class_add")).off().on("click",function(){e._all()}),this._refresh()),this.$content.show()}else this.$warning.show();this.model.get("help_enabled")&&this.$help.show(),this.$wait.hide()},_renderRow:function(e){var t=this,i=this.model.attributes,s=n(this._templateRow(e)),a=s.find(".icon");if(this.$body.append(s),this.collection){var o=this.ftp_index[e.path];a.addClass(void 0===o?i.class_add:i.class_remove),s.on("click",function(){t._switch(a,e),t._refresh()})}else s.on("click",function(){i.onchange(e)});return a},_index:function(){var e=this;this.ftp_index={},this.collection&&this.collection.each(function(t){"ftp"==t.get("file_mode")&&(e.ftp_index[t.get("file_path")]=t.id)})},_all:function(){var e=this.model.attributes,t=this.model.get("ftp_files"),i=this.$select.hasClass(e.class_add);for(var n in t){var s=t[n],a=this.ftp_index[s.path];(void 0===a&&i||void 0!==a&&!i)&&this._switch(this.rows[n],s)}this._refresh()},_switch:function(e,t){e.removeClass();var i=this.model.attributes,n=this.ftp_index[t.path];if(void 0===n){var s=i.onadd(t);e.addClass(i.class_remove),this.ftp_index[t.path]=s}else i.onremove(n),e.addClass(i.class_add),this.ftp_index[t.path]=void 0},_refresh:function(){var e=s.reduce(this.ftp_index,function(e,t){return void 0!==t&&e++,e},0);this.$select.removeClass(),0==e?this.$select.addClass(this.model.get("class_add")):this.$select.addClass(e==this.rows.length?this.model.get("class_remove"):this.model.get("class_partial"))},_templateRow:function(e){return'
'+s.escape(e.path)+'
'+o.default.bytesToString(e.size)+'
'+e.ctime+"
"},_template:function(){return'
'+this.model.get("help_text")+'
Available files:
Name
Size
Created
Your FTP directory does not contain any files.
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=(s(a),i(10)),l=s(o);t.default=e.View.extend({initialize:function(t){this.model=new e.Model(t),this.setElement(""),this.render()},render:function(){var e=this.model.attributes,t=n.findWhere(e.list,{id:e.extension});this.extension_popup&&this.extension_popup.remove(),this.extension_popup=new l.default.View({placement:e.placement||"bottom",container:e.$el}),this.extension_popup.title(e.title),this.extension_popup.empty(),this.extension_popup.append(this._templateDescription(t)),this.extension_popup.show()},_templateDescription:function(e){if(e.description){var t=e.description;return e.description_url&&(t+=' (read more)'),t}return"There is no description available for this file extension."}})}).call(t,i(2),i(1))},function(e,t,i){"use strict";(function(e,t){!function(i){e.event.props.push("dataTransfer"),i.uploadpost=function(t){var n=i.extend({},{data:{},success:function(){},error:function(){},progress:function(){},url:null,maxfilesize:2048,error_filesize:"File exceeds 2GB. Please use a FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_login:"Uploads require you to log in."},t),s=n.data;if(s.error_message)return void n.error(s.error_message);var a=new FormData;for(var o in s.payload)a.append(o,s.payload[o]);var l=0;for(var o in s.files){var r=s.files[o];a.append(r.name,r.file,r.file.name),l+=r.file.size}if(l>1048576*n.maxfilesize)return void n.error(n.error_filesize);var d=new XMLHttpRequest;d.open("POST",n.url,!0),d.setRequestHeader("Accept","application/json"),d.setRequestHeader("Cache-Control","no-cache"),d.setRequestHeader("X-Requested-With","XMLHttpRequest"),d.onreadystatechange=function(){if(d.readyState==d.DONE){var t=null,i="";if(d.responseText)try{t=e.parseJSON(d.responseText),i=t.err_msg}catch(e){t=d.responseText,i=t}if(d.status<200||d.status>299){var s=d.statusText;403==d.status?s=n.error_login:0==d.status?s=n.error_server:s||(s=n.error_default),n.error(s+" ("+d.status+"). "+i)}else n.success(t)}},d.upload.addEventListener("progress",function(e){e.lengthComputable&&n.progress(Math.round(100*e.loaded/e.total))},!1),Galaxy.emit.debug("uploadbox::uploadpost()","Posting following data.",n),d.send(a)},i.fn.uploadinput=function(e){var t=this,n=i.extend({},{ondragover:function(){},ondragleave:function(){},onchange:function(){},multiple:!1},e),s=i('");return t.append(s.change(function(e){n.onchange(e.target.files),i(this).val("")})),t.on("drop",function(e){n.ondragleave(e),e.dataTransfer&&(n.onchange(e.dataTransfer.files),e.preventDefault())}),t.on("dragover",function(e){e.preventDefault(),n.ondragover(e)}),t.on("dragleave",function(e){e.stopPropagation(),n.ondragleave(e)}),{dialog:function(){s.trigger("click")}}},i.fn.uploadbox=function(e){function n(e){if(e&&e.length&&!g){var i=void 0;return t.each(e,function(e,i){"new"!==e.mode&&t.filter(f,function(t){return t.name===e.name&&t.size===e.size}).length&&(e.duplicate=!0)}),t.each(e,function(e){e.duplicate||(i=String(p++),f[i]=e,h.announce(i,f[i]),m++)}),i}}function s(e){f[e]&&(delete f[e],m--)}function a(){if(0==m||_)return _=!1,g=!1,void h.complete();g=!0;var e=-1;for(var t in f){e=t;break}f[e];s(e),i.uploadpost({url:h.url,data:h.initialize(e),success:function(t){h.success(e,t),a()},error:function(t){h.error(e,t),a()},progress:function(t){h.progress(e,t)}})}function o(){v.dialog()}function l(e){for(e in f)s(e)}function r(){g||(g=!0,a())}function d(){_=!0}function c(e){return h=i.extend({},h,e)}function u(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}var h=i.extend({},{dragover:function(){},dragleave:function(){},announce:function(e){},initialize:function(e){},progress:function(e,t){},success:function(e,t){},error:function(e,t){alert(t)},complete:function(){}},e),f={},p=0,m=0,g=!1,_=!1,v=i(this).uploadinput({multiple:!0,onchange:function(e){n(e)},ondragover:e.ondragover,ondragleave:e.ondragleave});return{select:o,add:n,remove:s,start:r,stop:d,reset:l,configure:c,compatible:u}}}(e)}).call(t,i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s,a){function o(e){return e&&e.__esModule?e:{default:e}}function l(e,t){var i=e.toJSON();return $(i,{defaultHideSourceItems:t,creationFn:function(t,i,n){return t=t.map(function(e){return{id:e.id,name:e.name,src:"dataset"===e.history_content_type?"hda":"hdca"}}),e.createHDCA(t,"list",i,n)}})}Object.defineProperty(t,"__esModule",{value:!0});var r=i(36),d=o(r),c=i(11),u=o(c),h=i(5),f=o(h),p=i(74),m=o(p),g=i(7),_=o(g),v=i(75),w=(o(v),i(4)),y=o(w);i(76);var b=e.View.extend(f.default.LoggableMixin).extend({_logNamespace:"collections",tagName:"li",className:"collection-element",initialize:function(e){this.element=e.element||{},this.selected=e.selected||!1},render:function(){this.dragStartHandler=n.bind(this._dragstart,this),this.dragEndHandler=n.bind(this._dragend,this);var e=this.$el.attr("data-element-id",this.element.id).attr("draggable",!0).html(this.template({element:this.element})).get(0);return e.addEventListener("dragstart",this.dragStartHandler,!1),e.addEventListener("dragend",this.dragEndHandler,!1),this.selected&&this.$el.addClass("selected"),this},template:n.template(['',"<%- element.name %>","",'"].join("")),select:function(e){this.$el.toggleClass("selected",e),this.trigger("select",{source:this,selected:this.$el.hasClass("selected")})},discard:function(){var e=this,t=this.$el.parent().width();this.$el.animate({"margin-right":t},"fast",function(){e.trigger("discard",{source:e}),e.destroy()})},destroy:function(){this.off(),this.$el.remove()},events:{click:"_click","click .name":"_clickName","click .discard":"_clickDiscard",dragover:"_sendToParent",drop:"_sendToParent"},_click:function(e){e.stopPropagation(),this.select(e)},_clickName:function(e){e.stopPropagation(),e.preventDefault();var t=([(0,y.default)("Enter a new name for the element"),":\n(",(0,y.default)("Note that changing the name here will not rename the dataset"),")"].join(""),prompt((0,y.default)("Enter a new name for the element")+":",this.element.name));t&&(this.element.name=t,this.render())},_clickDiscard:function(e){e.stopPropagation(),this.discard()},_dragstart:function(e){e.originalEvent&&(e=e.originalEvent),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",JSON.stringify(this.element)),this.$el.addClass("dragging"),this.$el.parent().trigger("collection-element.dragstart",[this])},_dragend:function(e){this.$el.removeClass("dragging"),this.$el.parent().trigger("collection-element.dragend",[this])},_sendToParent:function(e){this.$el.parent().trigger(e)},toString:function(){return"DatasetCollectionElementView()"}}),x=e.View.extend(f.default.LoggableMixin).extend(m.default.CollectionCreatorMixin).extend({_logNamespace:"collections",elementViewClass:b,collectionClass:d.default.HistoryListDatasetCollection,className:"list-collection-creator collection-creator flex-row-container",minElements:1,defaultAttributes:{creationFn:function(){throw new TypeError("no creation fn for creator")},oncreate:function(){},oncancel:function(){},autoscrollDist:24,highlightClr:"rgba( 64, 255, 255, 1.0 )"},footerSettings:{".hide-originals":"hideOriginals"},initialize:function(e){this.metric("ListCollectionCreator.initialize",e);var t=this;n.each(this.defaultAttributes,function(i,n){i=e[n]||i,t[n]=i}),t.initialElements=e.elements||[],this._setUpCommonSettings(e),this._instanceSetUp(),this._elementsSetUp(),this._setUpBehaviors()},_instanceSetUp:function(){this.selectedIds={},this.$dragging=null,this.blocking=!1},_elementsSetUp:function(){this.invalidElements=[],this.workingElements=[],this.elementViews=[],this.workingElements=this.initialElements.slice(0),this._ensureElementIds(),this._validateElements(),this._mangleDuplicateNames(),this._sortElements()},_ensureElementIds:function(){return this.workingElements.forEach(function(e){e.hasOwnProperty("id")||(e.id=n.uniqueId())}),this.workingElements},_validateElements:function(){var e=this;return e.invalidElements=[],this.workingElements=this.workingElements.filter(function(t){var i=e._isElementInvalid(t);return i&&e.invalidElements.push({element:t,text:i}),!i}),this.workingElements},_isElementInvalid:function(e){return"dataset"!==e.history_content_type?(0,y.default)("is not a dataset"):e.state===u.default.OK||n.contains(u.default.NOT_READY_STATES,e.state)?e.deleted||e.purged?(0,y.default)("has been deleted or purged"):null:(0,y.default)("has errored, is paused, or is not accessible")},_mangleDuplicateNames:function(){var e=1,t={};this.workingElements.forEach(function(i){for(var n=i.name;t.hasOwnProperty(n);)if(n=i.name+" ("+e+")",(e+=1)>=900)throw new Error("Safety hit in while loop - thats impressive");i.name=n,t[i.name]=!0})},_sortElements:function(e){},render:function(e,t){return this.workingElements.length .clear-selected").show():this.$(".collection-elements-controls > .clear-selected").hide()},_renderList:function(e,t){var i=this,s=a(""),o=i.$list();n.each(this.elementViews,function(e){e.destroy(),i.removeElementView(e)}),i.workingElements.forEach(function(e){var t=i._createElementView(e);s.append(t.$el)}),i._renderClearSelected(),o.empty().append(s.children()),n.invoke(i.elementViews,"render"),o.height()>o.css("max-height")?o.css("border-width","1px 0px 1px 0px"):o.css("border-width","0px")},_createElementView:function(e){var t=new this.elementViewClass({element:e,selected:n.has(this.selectedIds,e.id)});return this.elementViews.push(t),this._listenToElementView(t),t},_listenToElementView:function(e){var t=this;t.listenTo(e,{select:function(e){var i=e.source.element;e.selected?t.selectedIds[i.id]=!0:delete t.selectedIds[i.id],t.trigger("elements:select",e)},discard:function(e){t.trigger("elements:discard",e)}})},addElementView:function(e){},removeElementView:function(e){delete this.selectedIds[e.element.id],this._renderClearSelected(),this.elementViews=n.without(this.elementViews,e),this.stopListening(e)},_renderNoElementsLeft:function(){this._disableNameAndCreate(!0),this.$(".collection-elements").append(this.templates.noElementsLeft())},_elementToJSON:function(e){return e},createList:function(e){if(!this.workingElements.length){var t=(0,y.default)("No valid elements for final list")+". ";return t+=''+(0,y.default)("Cancel")+" ",t+=(0,y.default)("or"),t+=' '+(0,y.default)("start over")+".",void this._showAlert(t)}var i=this,n=this.workingElements.map(function(e){return i._elementToJSON(e)});return i.blocking=!0,i.creationFn(n,e,i.hideOriginals).always(function(){i.blocking=!1}).fail(function(e,t,n){i.trigger("error",{xhr:e,status:t,message:(0,y.default)("An error occurred while creating this collection")})}).done(function(e,t,n){i.trigger("collection:created",e,t,n),i.metric("collection:created",e),"function"==typeof i.oncreate&&i.oncreate.call(this,e,t,n)})},_setUpBehaviors:function(){return this.on("error",this._errorHandler),this.once("rendered",function(){this.trigger("rendered:initial",this)}),this.on("elements:select",function(e){this._renderClearSelected()}),this.on("elements:discard",function(e){var t=e.source.element;this.removeElementView(e.source),this.workingElements=n.without(this.workingElements,t),this.workingElements.length||this._renderNoElementsLeft()}),this},_errorHandler:function(e){this.error(e);var t=this,i=e.message||(0,y.default)("An error occurred");if(e.xhr){var n=e.xhr,s=e.message;0===n.readyState&&0===n.status?i+=": "+(0,y.default)("Galaxy could not be reached and may be updating.")+(0,y.default)(" Try again in a few minutes."):n.responseJSON?i+=":
",(0,y.default)(["Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and ","workflows in order to have analyses done on each member of the entire group. This interface allows ","you to create a collection and re-order the final collection."].join("")),"
","
","
",(0,y.default)(["Rename elements in the list by clicking on ",'the existing name.'].join("")),"
","
",(0,y.default)(["Discard elements from the final created list by clicking on the ",'"Discard" button.'].join("")),"
","
",(0,y.default)(["Reorder the list by clicking and dragging elements. Select multiple elements by clicking on ",'them and you can then move those selected by dragging the ',"entire group. Deselect them by clicking them again or by clicking the ",'the "Clear selected" link.'].join("")),"
","
",(0,y.default)(['Click the "Start over" link to begin again as if you had just opened ',"the interface."].join("")),"
","
",(0,y.default)(['Click the "Cancel" button to exit the interface.'].join("")),"
","
","
",(0,y.default)(['Once your collection is complete, enter a name and ','click "Create list".'].join("")),"
"].join("")),invalidElements:n.template([(0,y.default)("The following selections could not be included due to problems:"),"
','',"<% if( _.size( problems ) ){ %>",(0,y.default)("The following selections could not be included due to problems"),":","
<% _.each( problems, function( problem ){ %>","
<%- problem.element.name %>: <%- problem.text %>
","<% }); %>
","<% } else if( _.size( elements ) < 1 ){ %>",(0,y.default)("No datasets were selected"),".","<% } %>"," ",(0,y.default)("At least one element is needed for the collection"),". ",(0,y.default)("You may need to "),'',(0,y.default)("cancel")," ",(0,y.default)("and reselect new elements"),".","","
").append(t.title)))}),this.$cover[this.model.get("enabled")&&"hide"||"show"]()}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=function(e){return e&&e.__esModule?e:{default:e}}(a);t.default=e.View.extend({initialize:function(t){this.model=new e.Model({cls:"upload-ftp",class_add:"upload-icon-button fa fa-square-o",class_remove:"upload-icon-button fa fa-check-square-o",class_partial:"upload-icon-button fa fa-minus-square-o",help_enabled:!0,help_text:"This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at "+t.ftp_upload_site+" using your Galaxy credentials.",collection:null,onchange:function(){},onadd:function(){},onremove:function(){}}).set(t),this.collection=this.model.get("collection"),this.setElement(this._template()),this.$content=this.$(".upload-ftp-content"),this.$wait=this.$(".upload-ftp-wait"),this.$help=this.$(".upload-ftp-help"),this.$number=this.$(".upload-ftp-number"),this.$disk=this.$(".upload-ftp-disk"),this.$body=this.$(".upload-ftp-body"),this.$warning=this.$(".upload-ftp-warning"),this.$select=this.$(".upload-ftp-select-all"),this.render()},render:function(){var e=this;this.$wait.show(),this.$content.hide(),this.$warning.hide(),this.$help.hide(),n.ajax({url:Galaxy.root+"api/remote_files",method:"GET",success:function(t){e.model.set("ftp_files",t),e._index(),e._renderTable()},error:function(){e._renderTable()}})},_renderTable:function(){var e=this,t=this.model.get("ftp_files");if(this.rows=[],t&&t.length>0){this.$body.empty();var i=0;s.each(t,function(t){e.rows.push(e._renderRow(t)),i+=t.size}),this.$number.html(t.length+" files"),this.$disk.html(o.default.bytesToString(i,!0)),this.collection&&(this.$("._has_collection").show(),this.$select.addClass(this.model.get("class_add")).off().on("click",function(){e._all()}),this._refresh()),this.$content.show()}else this.$warning.show();this.model.get("help_enabled")&&this.$help.show(),this.$wait.hide()},_renderRow:function(e){var t=this,i=this.model.attributes,s=n(this._templateRow(e)),a=s.find(".icon");if(this.$body.append(s),this.collection){var o=this.ftp_index[e.path];a.addClass(void 0===o?i.class_add:i.class_remove),s.on("click",function(){t._switch(a,e),t._refresh()})}else s.on("click",function(){i.onchange(e)});return a},_index:function(){var e=this;this.ftp_index={},this.collection&&this.collection.each(function(t){"ftp"==t.get("file_mode")&&(e.ftp_index[t.get("file_path")]=t.id)})},_all:function(){var e=this.model.attributes,t=this.model.get("ftp_files"),i=this.$select.hasClass(e.class_add);for(var n in t){var s=t[n],a=this.ftp_index[s.path];(void 0===a&&i||void 0!==a&&!i)&&this._switch(this.rows[n],s)}this._refresh()},_switch:function(e,t){e.removeClass();var i=this.model.attributes,n=this.ftp_index[t.path];if(void 0===n){var s=i.onadd(t);e.addClass(i.class_remove),this.ftp_index[t.path]=s}else i.onremove(n),e.addClass(i.class_add),this.ftp_index[t.path]=void 0},_refresh:function(){var e=s.reduce(this.ftp_index,function(e,t){return void 0!==t&&e++,e},0);this.$select.removeClass(),0==e?this.$select.addClass(this.model.get("class_add")):this.$select.addClass(e==this.rows.length?this.model.get("class_remove"):this.model.get("class_partial"))},_templateRow:function(e){return'
'+s.escape(e.path)+'
'+o.default.bytesToString(e.size)+'
'+e.ctime+"
"},_template:function(){return'
'+this.model.get("help_text")+'
Available files:
Name
Size
Created
Your FTP directory does not contain any files.
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=(s(a),i(10)),l=s(o);t.default=e.View.extend({initialize:function(t){this.model=new e.Model(t),this.setElement(""),this.render()},render:function(){var e=this.model.attributes,t=n.findWhere(e.list,{id:e.extension});this.extension_popup&&this.extension_popup.remove(),this.extension_popup=new l.default.View({placement:e.placement||"bottom",container:e.$el}),this.extension_popup.title(e.title),this.extension_popup.empty(),this.extension_popup.append(this._templateDescription(t)),this.extension_popup.show()},_templateDescription:function(e){if(e.description){var t=e.description;return e.description_url&&(t+=' (read more)'),t}return"There is no description available for this file extension."}})}).call(t,i(2),i(1))},function(e,t,i){"use strict";(function(e,t){!function(i){e.event.props.push("dataTransfer"),i.uploadpost=function(t){var n=i.extend({},{data:{},success:function(){},error:function(){},progress:function(){},url:null,maxfilesize:2048,error_filesize:"File exceeds 2GB. Please use a FTP client.",error_default:"Please make sure the file is available.",error_server:"Upload request failed.",error_login:"Uploads require you to log in."},t),s=n.data;if(s.error_message)return void n.error(s.error_message);var a=new FormData;for(var o in s.payload)a.append(o,s.payload[o]);var l=0;for(var o in s.files){var r=s.files[o];a.append(r.name,r.file,r.file.name),l+=r.file.size}if(l>1048576*n.maxfilesize)return void n.error(n.error_filesize);var d=new XMLHttpRequest;d.open("POST",n.url,!0),d.setRequestHeader("Accept","application/json"),d.setRequestHeader("Cache-Control","no-cache"),d.setRequestHeader("X-Requested-With","XMLHttpRequest"),d.onreadystatechange=function(){if(d.readyState==d.DONE){var t=null,i="";if(d.responseText)try{t=e.parseJSON(d.responseText),i=t.err_msg}catch(e){t=d.responseText,i=t}if(d.status<200||d.status>299){var s=d.statusText;403==d.status?s=n.error_login:0==d.status?s=n.error_server:s||(s=n.error_default),n.error(s+" ("+d.status+"). "+i)}else n.success(t)}},d.upload.addEventListener("progress",function(e){e.lengthComputable&&n.progress(Math.round(100*e.loaded/e.total))},!1),Galaxy.emit.debug("uploadbox::uploadpost()","Posting following data.",n),d.send(a)},i.fn.uploadinput=function(e){var t=this,n=i.extend({},{ondragover:function(){},ondragleave:function(){},onchange:function(){},multiple:!1},e),s=i('");return t.append(s.change(function(e){n.onchange(e.target.files),i(this).val("")})),t.on("drop",function(e){n.ondragleave(e),e.dataTransfer&&(n.onchange(e.dataTransfer.files),e.preventDefault())}),t.on("dragover",function(e){e.preventDefault(),n.ondragover(e)}),t.on("dragleave",function(e){e.stopPropagation(),n.ondragleave(e)}),{dialog:function(){s.trigger("click")}}},i.fn.uploadbox=function(e){function n(e){if(e&&e.length&&!g){var i=void 0;return t.each(e,function(e,i){"new"!==e.mode&&t.filter(f,function(t){return t.name===e.name&&t.size===e.size}).length&&(e.duplicate=!0)}),t.each(e,function(e){e.duplicate||(i=String(p++),f[i]=e,h.announce(i,f[i]),m++)}),i}}function s(e){f[e]&&(delete f[e],m--)}function a(){if(0==m||_)return _=!1,g=!1,void h.complete();g=!0;var e=-1;for(var t in f){e=t;break}f[e];s(e),i.uploadpost({url:h.url,data:h.initialize(e),success:function(t){h.success(e,t),a()},error:function(t){h.error(e,t),a()},progress:function(t){h.progress(e,t)}})}function o(){v.dialog()}function l(e){for(e in f)s(e)}function r(){g||(g=!0,a())}function d(){_=!0}function c(e){return h=i.extend({},h,e)}function u(){return window.File&&window.FormData&&window.XMLHttpRequest&&window.FileList}var h=i.extend({},{dragover:function(){},dragleave:function(){},announce:function(e){},initialize:function(e){},progress:function(e,t){},success:function(e,t){},error:function(e,t){alert(t)},complete:function(){}},e),f={},p=0,m=0,g=!1,_=!1,v=i(this).uploadinput({multiple:!0,onchange:function(e){n(e)},ondragover:e.ondragover,ondragleave:e.ondragleave});return{select:o,add:n,remove:s,start:r,stop:d,reset:l,configure:c,compatible:u}}}(e)}).call(t,i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s,a){function o(e){return e&&e.__esModule?e:{default:e}}function l(e,t){var i=e.toJSON();return $(i,{defaultHideSourceItems:t,creationFn:function(t,i,n){return t=t.map(function(e){return{id:e.id,name:e.name,src:"dataset"===e.history_content_type?"hda":"hdca"}}),e.createHDCA(t,"list",i,n)}})}Object.defineProperty(t,"__esModule",{value:!0});var r=i(36),d=o(r),c=i(11),u=o(c),h=i(5),f=o(h),p=i(74),m=o(p),g=i(7),_=o(g),v=i(75),w=(o(v),i(4)),y=o(w);i(76);var b=e.View.extend(f.default.LoggableMixin).extend({_logNamespace:"collections",tagName:"li",className:"collection-element",initialize:function(e){this.element=e.element||{},this.selected=e.selected||!1},render:function(){this.dragStartHandler=n.bind(this._dragstart,this),this.dragEndHandler=n.bind(this._dragend,this);var e=this.$el.attr("data-element-id",this.element.id).attr("draggable",!0).html(this.template({element:this.element})).get(0);return e.addEventListener("dragstart",this.dragStartHandler,!1),e.addEventListener("dragend",this.dragEndHandler,!1),this.selected&&this.$el.addClass("selected"),this},template:n.template(['',"<%- element.name %>","",'"].join("")),select:function(e){this.$el.toggleClass("selected",e),this.trigger("select",{source:this,selected:this.$el.hasClass("selected")})},discard:function(){var e=this,t=this.$el.parent().width();this.$el.animate({"margin-right":t},"fast",function(){e.trigger("discard",{source:e}),e.destroy()})},destroy:function(){this.off(),this.$el.remove()},events:{click:"_click","click .name":"_clickName","click .discard":"_clickDiscard",dragover:"_sendToParent",drop:"_sendToParent"},_click:function(e){e.stopPropagation(),this.select(e)},_clickName:function(e){e.stopPropagation(),e.preventDefault();var t=([(0,y.default)("Enter a new name for the element"),":\n(",(0,y.default)("Note that changing the name here will not rename the dataset"),")"].join(""),prompt((0,y.default)("Enter a new name for the element")+":",this.element.name));t&&(this.element.name=t,this.render())},_clickDiscard:function(e){e.stopPropagation(),this.discard()},_dragstart:function(e){e.originalEvent&&(e=e.originalEvent),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",JSON.stringify(this.element)),this.$el.addClass("dragging"),this.$el.parent().trigger("collection-element.dragstart",[this])},_dragend:function(e){this.$el.removeClass("dragging"),this.$el.parent().trigger("collection-element.dragend",[this])},_sendToParent:function(e){this.$el.parent().trigger(e)},toString:function(){return"DatasetCollectionElementView()"}}),x=e.View.extend(f.default.LoggableMixin).extend(m.default.CollectionCreatorMixin).extend({_logNamespace:"collections",elementViewClass:b,collectionClass:d.default.HistoryListDatasetCollection,className:"list-collection-creator collection-creator flex-row-container",minElements:1,defaultAttributes:{creationFn:function(){throw new TypeError("no creation fn for creator")},oncreate:function(){},oncancel:function(){},autoscrollDist:24,highlightClr:"rgba( 64, 255, 255, 1.0 )"},footerSettings:{".hide-originals":"hideOriginals"},initialize:function(e){this.metric("ListCollectionCreator.initialize",e);var t=this;n.each(this.defaultAttributes,function(i,n){i=e[n]||i,t[n]=i}),t.initialElements=e.elements||[],this._setUpCommonSettings(e),this._instanceSetUp(),this._elementsSetUp(),this._setUpBehaviors()},_instanceSetUp:function(){this.selectedIds={},this.$dragging=null,this.blocking=!1},_elementsSetUp:function(){this.invalidElements=[],this.workingElements=[],this.elementViews=[],this.workingElements=this.initialElements.slice(0),this._ensureElementIds(),this._validateElements(),this._mangleDuplicateNames(),this._sortElements()},_ensureElementIds:function(){return this.workingElements.forEach(function(e){e.hasOwnProperty("id")||(e.id=n.uniqueId())}),this.workingElements},_validateElements:function(){var e=this;return e.invalidElements=[],this.workingElements=this.workingElements.filter(function(t){var i=e._isElementInvalid(t);return i&&e.invalidElements.push({element:t,text:i}),!i}),this.workingElements},_isElementInvalid:function(e){return"dataset"!==e.history_content_type?(0,y.default)("is not a dataset"):e.state===u.default.OK||n.contains(u.default.NOT_READY_STATES,e.state)?e.deleted||e.purged?(0,y.default)("has been deleted or purged"):null:(0,y.default)("has errored, is paused, or is not accessible")},_mangleDuplicateNames:function(){var e=1,t={};this.workingElements.forEach(function(i){for(var n=i.name;t.hasOwnProperty(n);)if(n=i.name+" ("+e+")",(e+=1)>=900)throw new Error("Safety hit in while loop - thats impressive");i.name=n,t[i.name]=!0})},_sortElements:function(e){},render:function(e,t){return this.workingElements.length .clear-selected").show():this.$(".collection-elements-controls > .clear-selected").hide()},_renderList:function(e,t){var i=this,s=a(""),o=i.$list();n.each(this.elementViews,function(e){e.destroy(),i.removeElementView(e)}),i.workingElements.forEach(function(e){var t=i._createElementView(e);s.append(t.$el)}),i._renderClearSelected(),o.empty().append(s.children()),n.invoke(i.elementViews,"render"),o.height()>o.css("max-height")?o.css("border-width","1px 0px 1px 0px"):o.css("border-width","0px")},_createElementView:function(e){var t=new this.elementViewClass({element:e,selected:n.has(this.selectedIds,e.id)});return this.elementViews.push(t),this._listenToElementView(t),t},_listenToElementView:function(e){var t=this;t.listenTo(e,{select:function(e){var i=e.source.element;e.selected?t.selectedIds[i.id]=!0:delete t.selectedIds[i.id],t.trigger("elements:select",e)},discard:function(e){t.trigger("elements:discard",e)}})},addElementView:function(e){},removeElementView:function(e){delete this.selectedIds[e.element.id],this._renderClearSelected(),this.elementViews=n.without(this.elementViews,e),this.stopListening(e)},_renderNoElementsLeft:function(){this._disableNameAndCreate(!0),this.$(".collection-elements").append(this.templates.noElementsLeft())},_elementToJSON:function(e){return e},createList:function(e){if(!this.workingElements.length){var t=(0,y.default)("No valid elements for final list")+". ";return t+=''+(0,y.default)("Cancel")+" ",t+=(0,y.default)("or"),t+=' '+(0,y.default)("start over")+".",void this._showAlert(t)}var i=this,n=this.workingElements.map(function(e){return i._elementToJSON(e)});return i.blocking=!0,i.creationFn(n,e,i.hideOriginals).always(function(){i.blocking=!1}).fail(function(e,t,n){i.trigger("error",{xhr:e,status:t,message:(0,y.default)("An error occurred while creating this collection")})}).done(function(e,t,n){i.trigger("collection:created",e,t,n),i.metric("collection:created",e),"function"==typeof i.oncreate&&i.oncreate.call(this,e,t,n)})},_setUpBehaviors:function(){return this.on("error",this._errorHandler),this.once("rendered",function(){this.trigger("rendered:initial",this)}),this.on("elements:select",function(e){this._renderClearSelected()}),this.on("elements:discard",function(e){var t=e.source.element;this.removeElementView(e.source),this.workingElements=n.without(this.workingElements,t),this.workingElements.length||this._renderNoElementsLeft()}),this},_errorHandler:function(e){this.error(e);var t=this,i=e.message||(0,y.default)("An error occurred");if(e.xhr){var n=e.xhr,s=e.message;0===n.readyState&&0===n.status?i+=": "+(0,y.default)("Galaxy could not be reached and may be updating.")+(0,y.default)(" Try again in a few minutes."):n.responseJSON?i+=":
",(0,y.default)(["Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and ","workflows in order to have analyses done on each member of the entire group. This interface allows ","you to create a collection and re-order the final collection."].join("")),"
","
","
",(0,y.default)(["Rename elements in the list by clicking on ",'the existing name.'].join("")),"
","
",(0,y.default)(["Discard elements from the final created list by clicking on the ",'"Discard" button.'].join("")),"
","
",(0,y.default)(["Reorder the list by clicking and dragging elements. Select multiple elements by clicking on ",'them and you can then move those selected by dragging the ',"entire group. Deselect them by clicking them again or by clicking the ",'the "Clear selected" link.'].join("")),"
","
",(0,y.default)(['Click the "Start over" link to begin again as if you had just opened ',"the interface."].join("")),"
","
",(0,y.default)(['Click the "Cancel" button to exit the interface.'].join("")),"
","
","
",(0,y.default)(['Once your collection is complete, enter a name and ','click "Create list".'].join("")),"
"].join("")),invalidElements:n.template([(0,y.default)("The following selections could not be included due to problems:"),"
','',"<% if( _.size( problems ) ){ %>",(0,y.default)("The following selections could not be included due to problems"),":","
<% _.each( problems, function( problem ){ %>","
<%- problem.element.name %>: <%- problem.text %>
","<% }); %>
","<% } else if( _.size( elements ) < 1 ){ %>",(0,y.default)("No datasets were selected"),".","<% } %>"," ",(0,y.default)("At least one element is needed for the collection"),". ",(0,y.default)("You may need to "),'',(0,y.default)("cancel")," ",(0,y.default)("and reselect new elements"),".","","
"],"element");return e.extend({},d.default.DatasetListItemView.prototype.templates,{titleBar:t})}();var w=g.extend({className:g.prototype.className+" dataset-collection-element",_swapNewRender:function(e){g.prototype._swapNewRender.call(this,e);var t=this.model.get("state")||"ok";return this.$el.addClass("state-"+t),this.$el},toString:function(){return"NestedDCDCEListItemView("+(this.model?""+this.model:"(no model)")+")"}});t.default={DCListItemView:g,DCEListItemView:_,DatasetDCEListItemView:v,NestedDCDCEListItemView:w}}).call(t,i(1),i(0),i(0))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(9),o=s(a),l=i(6),r=s(l),d=e.View.extend({initialize:function(t){this.model=new e.Model(t),this.url=this.model.get("url"),this.redirect=this.model.get("redirect"),this.setElement(""),this.render()},render:function(){var e=this;n.ajax({url:Galaxy.root+this.url,type:"GET"}).done(function(t){var i=n.extend({},e.model.attributes,t),s=new o.default({title:i.title,message:i.message,status:i.status||"warning",icon:i.icon,inputs:i.inputs,buttons:{submit:new r.default.Button({tooltip:i.submit_tooltip,title:i.submit_title||"Save",icon:i.submit_icon||"fa-save",cls:"btn btn-primary ui-clear-float",onclick:function(){e._submit(s)}})}});e.$el.empty().append(s.$el)}).fail(function(t){e.$el.empty().append(new r.default.Message({message:"Failed to load resource "+e.url+".",status:"danger",persistent:!0}).$el)})},_submit:function(e){var t=this;n.ajax({url:Galaxy.root+t.url,data:JSON.stringify(e.data.create()),type:"PUT",contentType:"application/json"}).done(function(i){var s={message:i.message,status:"success",persistent:!1};t.redirect?window.location=Galaxy.root+t.redirect+"?"+n.param(s):(e.data.matchModel(i,function(t,i){e.field_list[i].value(t.value)}),t._showMessage(e,s))}).fail(function(i){t._showMessage(e,{message:i.responseJSON.err_msg,status:"danger",persistent:!1})})},_showMessage:function(e,t){e.$el.parents().filter(function(){return-1!=["auto","scroll"].indexOf(n(this).css("overflow"))}).first().animate({scrollTop:0},500),e.message.update(t)}});t.default={View:d}}).call(t,i(2),i(0))},,,,,,,,,,,,,,,,,,,,,,,,,,,,function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(11),l=a(o),r=i(5),d=a(r),c=i(4),u=a(c),h=d.default.SearchableModelMixin,f=e.Model.extend(d.default.LoggableMixin).extend(d.default.mixin(h,{_logNamespace:"dataset",defaults:{state:l.default.NEW,deleted:!1,purged:!1,name:"(unnamed dataset)",accessible:!0,data_type:"",file_ext:"",file_size:0,meta_files:[],misc_blurb:"",misc_info:"",tags:[]},initialize:function(e,t){this.debug(this+"(Dataset).initialize",e,t),
//!! this state is not in trans.app.model.Dataset.states - set it here -
-this.get("accessible")||this.set("state",l.default.NOT_VIEWABLE),this.urls=this._generateUrls(),this._setUpListeners()},_generateUrls:function(){var e=this.get("id");if(!e)return{};var t={purge:"datasets/"+e+"/purge_async",display:"datasets/"+e+"/display/?preview=True",edit:"datasets/edit?dataset_id="+e,download:"datasets/"+e+"/display"+this._downloadQueryParameters(),report_error:"dataset/errors?id="+e,rerun:"tool_runner/rerun?id="+e,show_params:"datasets/"+e+"/show_params",visualization:"visualization",meta_download:"dataset/get_metadata_file?hda_id="+e+"&metadata_name="};return n.each(t,function(e,i){t[i]=Galaxy.root+e}),this.urls=t,t},_downloadQueryParameters:function(){return"?to_ext="+this.get("file_ext")},_setUpListeners:function(){this.on("change:state",function(e,t){this.log(this+" has changed state:",e,t),this.inReadyState()&&this.trigger("state:ready",e,t,this.previous("state"))}),this.on("change:id change:file_ext",function(e){this._generateUrls()})},toJSON:function(){var t=e.Model.prototype.toJSON.call(this);return n.extend(t,{urls:this.urls})},isDeletedOrPurged:function(){return this.get("deleted")||this.get("purged")},inReadyState:function(){var e=n.contains(l.default.READY_STATES,this.get("state"));return this.isDeletedOrPurged()||e},hasDetails:function(){return!this.get("accessible")||this.has("annotation")},hasData:function(){return this.get("file_size")>0},fetch:function(t){var i=this;return e.Model.prototype.fetch.call(this,t).always(function(){i._generateUrls()})},parse:function(t,i){var n=e.Model.prototype.parse.call(this,t,i);return n.create_time&&(n.create_time=new Date(n.create_time)),n.update_time&&(n.update_time=new Date(n.update_time)),n},save:function(t,i){return i=i||{},i.wait=!!n.isUndefined(i.wait)||i.wait,e.Model.prototype.save.call(this,t,i)},delete:function(e){return this.get("deleted")?s.when():this.save({deleted:!0},e)},undelete:function(e){return!this.get("deleted")||this.get("purged")?s.when():this.save({deleted:!1},e)},purge:function(e){if(this.get("purged"))return s.when();e=e||{},e.url=this.urls.purge;var t=this,i=s.ajax(e);return i.done(function(e,i,n){t.set({deleted:!0,purged:!0})}),i.fail(function(i,n,s){var a=(0,u.default)("Unable to purge dataset");i.responseJSON&&i.responseJSON.error?a=i.responseJSON.error:-1!==i.responseText.indexOf("Removal of datasets by users is not allowed in this Galaxy instance")&&(a="Removal of datasets by users is not allowed in this Galaxy instance"),i.responseText=a,t.trigger("error",t,i,e,(0,u.default)(a),{error:a})}),i},searchAttributes:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],searchAliases:{title:"name",format:"file_ext",database:"genome_build",blurb:"misc_blurb",description:"misc_blurb",info:"misc_info",tag:"tags"},toString:function(){var e=this.get("id")||"";return this.get("name")&&(e='"'+this.get("name")+'",'+e),"Dataset("+e+")"}})),p=e.Collection.extend(d.default.LoggableMixin).extend({_logNamespace:"dataset",model:f,urlRoot:Galaxy.root+"api/datasets",url:function(){return this.urlRoot},ids:function(){return this.map(function(e){return e.get("id")})},notReady:function(){return this.filter(function(e){return!e.inReadyState()})},haveDetails:function(){return this.all(function(e){return e.hasDetails()})},ajaxQueue:function(e,t){var i=s.Deferred(),n=this.length,a=[];if(!n)return i.resolve([]),i;var o=this.chain().reverse().map(function(s,l){return function(){var r=e.call(s,t);r.done(function(e){i.notify({curr:l,total:n,response:e,model:s})}),r.always(function(e){a.push(e),o.length?o.shift()():i.resolve(a)})}}).value();return o.shift()(),i},matches:function(e){return this.filter(function(t){return t.matches(e)})},toString:function(){return["DatasetAssociationCollection(",this.length,")"].join("")}});t.default={DatasetAssociation:f,DatasetAssociationCollection:p}}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var s=i(11),a=(n(s),i(5)),o=(n(a),i(4)),l=(n(o),{defaults:{history_id:null,history_content_type:null,hid:null,visible:!0},idAttribute:"type_id",hidden:function(){return!this.get("visible")},isVisible:function(e,t){var i=!0;return e||!this.get("deleted")&&!this.get("purged")||(i=!1),t||this.get("visible")||(i=!1),i},urlRoot:Galaxy.root+"api/histories/",url:function(){return this.urlRoot+this.get("history_id")+"/contents/"+this.get("history_content_type")+"s/"+this.get("id")},hide:function(t){return this.get("visible")?this.save({visible:!1},t):e.when()},unhide:function(t){return this.get("visible")?e.when():this.save({visible:!0},t)},toString:function(){return[this.get("type_id"),this.get("hid"),this.get("name")].join(":")}});t.default={HistoryContentMixin:l}}).call(t,i(0))},function(e,t,i){"use strict";(function(e){Object.defineProperty(t,"__esModule",{value:!0});var i={_validationWarning:function(e,t){"name"===e&&(e=this.$(".collection-name").add(this.$(".collection-name-prompt")),this.$(".collection-name").focus().select()),t?(e=e||this.$(".validation-warning"),e.removeClass("validation-warning")):e.addClass("validation-warning")},_changeHideOriginals:function(e){this.hideOriginals=this.$(".hide-originals").prop("checked")},_changeName:function(e){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(e){13!==e.keyCode||this.blocking||this._clickCreate()},_getName:function(){return e.escape(this.$(".collection-name").val())},_clickMoreHelp:function(e){e.stopPropagation(),this.$(".main-help").addClass("expanded"),this.$(".more-help").hide()},_clickLessHelp:function(e){e.stopPropagation(),this.$(".main-help").removeClass("expanded"),this.$(".more-help").show()},_toggleHelp:function(e){e.stopPropagation(),this.$(".main-help").toggleClass("expanded"),this.$(".more-help").toggle()},_showAlert:function(e,t){t=t||"alert-danger",this.$(".main-help").hide(),this.$(".header .alert").attr("class","alert alert-dismissable").addClass(t).show().find(".alert-message").html(e)},_hideAlert:function(e){this.$(".main-help").show(),this.$(".header .alert").hide()},_cancelCreate:function(e){"function"==typeof this.oncancel&&this.oncancel.call(this)},_clickCreate:function(e){var t=this._getName();t?this.blocking||this.createList(t):this._validationWarning("name")},_setUpCommonSettings:function(e){this.hideOriginals=e.defaultHideSourceItems||!1},_renderFooter:function(t,i){var n=this,s=this.$(".footer").empty().html(this.templates.footer());return e.each(this.footerSettings,function(e,t){n.$(t).prop("checked",n[e])}),"function"==typeof this.oncancel&&this.$(".cancel-create.btn").show(),s},_creatorTemplates:{main:e.template(['','',''].join(""))}};t.default={CollectionCreatorMixin:i}}).call(t,i(1))},function(e,t,i){"use strict";function n(e,t){var i=/(-?[0-9\.]+)/g,n=e.toString().toLowerCase()||"",s=t.toString().toLowerCase()||"",a=String.fromCharCode(0),o=n.replace(i,a+"$1"+a).split(a),l=s.replace(i,a+"$1"+a).split(a),r=new Date(n).getTime(),d=r?new Date(s).getTime():null;if(d){if(rd)return 1}for(var c,u,h=0,f=Math.max(o.length,l.length);hu)return 1}return 0}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,i){"use strict";var n=i(0),s=function(e){return e&&e.__esModule?e:{default:e}}(n),a=s.default;s.default.fn.extend({hoverhighlight:function(e,t){return e=e||"body",this.length?(a(this).each(function(){var i=a(this),n=i.data("target");n&&i.mouseover(function(i){a(n,e).css({background:t})}).mouseout(function(e){a(n).css({background:""})})}),this):this}})},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(67),d=a(r),c=i(6),u=a(c),h=i(9),f=a(h),p=i(70),m=a(p),g=i(66),_=a(g),v=i(7),w=a(v),y=i(17),b=a(y),x=i(148),C=a(x),$=e.View.extend({initialize:function(t){var i=this;this.modal=parent.Galaxy.modal||new w.default.View,this.model=t&&t.model||new e.Model(t),this.deferred=new d.default,this.setElement(n("").addClass("ui-form-composite").append(this.$message=n("")).append(this.$header=n("")).append(this.$steps=n(""))),n("body").append(this.$el),this._configure(),this.render(),n(window).resize(function(){i._refresh()})},_refresh:function(e){var t=s.reduce(this.$el.children(),function(e,t){return e+n(t).outerHeight()},0)-this.$steps.height()+90;this.$steps.css("height",n(window).height()-t)},_configure:function(){function e(e,n){for(var s,a=/\$\{(.+?)\}/g;s=a.exec(String(e));){var o=s[1];n(t.wp_inputs[o]=t.wp_inputs[o]||{label:o,name:o,type:"text",color:"hsl( "+100*++i+", 70%, 30% )",style:"ui-form-wp-source",links:[]})}}var t=this;this.forms=[],this.steps=[],this.links=[],this.parms=[],s.each(this.model.get("steps"),function(e,i){Galaxy.emit.debug("tool-form-composite::initialize()",i+" : Preparing workflow step.");var n=C.default[e.step_type],a=parseInt(i+1)+": "+(e.step_label||e.step_name);e.annotation&&(a+=" - "+e.annotation),e.step_version&&(a+=" (Galaxy Version "+e.step_version+")"),e=l.default.merge({index:i,fixed_title:s.escape(a),icon:n||"",help:null,citations:null,collapsible:!0,collapsed:i>0&&!t._isDataStep(e),sustain_version:!0,sustain_repeats:!0,sustain_conditionals:!0,narrow:!0,text_enable:"Edit",text_disable:"Undo",cls_enable:"fa fa-edit",cls_disable:"fa fa-undo",errors:e.messages,initial_errors:!0,cls:"ui-portlet-narrow",hide_operations:!0,needs_refresh:!1,always_refresh:"tool"!=e.step_type},e),t.steps[i]=e,t.links[i]=[],t.parms[i]={}}),s.each(this.steps,function(e,i){m.default.visitInputs(e.inputs,function(e,n){t.parms[i][n]=e})}),s.each(this.steps,function(e,i){s.each(e.output_connections,function(e){s.each(t.steps,function(n,s){n.step_index===e.input_step_index&&t.links[i].push(n)})})}),s.each(this.steps,function(e,i){s.each(t.steps,function(n,a){var o={};s.each(e.output_connections,function(e){n.step_index===e.input_step_index&&(o[e.input_name]=e)}),s.each(t.parms[a],function(t,n){var s=o[n];s&&(t.type="hidden",t.help=t.step_linked?t.help+", ":"",t.help+="Output dataset '"+s.output_name+"' from step "+(parseInt(i)+1),t.step_linked=t.step_linked||[],t.step_linked.push(e))})})});var i=0;this.wp_inputs={},s.each(this.steps,function(i,n){s.each(t.parms[n],function(t,n){e(t.value,function(e){e.links.push(i),t.wp_linked=!0,t.type="text",t.backdrop=!0,t.style="ui-form-wp-target"})}),s.each(i.post_job_actions,function(t){s.each(t.action_arguments,function(t){e(t,function(){})})})}),s.each(this.steps,function(e,i){if("tool"==e.step_type){var n=!0;m.default.visitInputs(e.inputs,function(i,s,a){var o=i.value&&"RuntimeValue"==i.value.__class__,r=-1!=["data","data_collection"].indexOf(i.type),d=a[i.data_ref];i.step_linked&&!t._isDataStep(i.step_linked)&&(n=!1),i.options&&(0==i.options.length&&!n||i.wp_linked)&&(i.is_workflow=!0),d&&(i.is_workflow=d.step_linked&&!t._isDataStep(d.step_linked)||i.wp_linked),(r||i.value&&"RuntimeValue"==i.value.__class__&&!i.step_linked)&&(e.collapsed=!1),o&&(i.value=i.default_value),i.flavor="workflow",o||r||"hidden"===i.type||i.wp_linked||(i.optional||!l.default.isEmpty(i.value)&&""!==i.value)&&(i.collapsible_value=i.value,i.collapsible_preview=!0)})}})},render:function(){var e=this;this.deferred.reset(),this._renderHeader(),this._renderMessage(),this._renderParameters(),this._renderHistory(),s.each(this.steps,function(t){e._renderStep(t)})},_renderHeader:function(){var e=this;this.execute_btn=new u.default.Button({icon:"fa-check",title:"Run workflow",cls:"btn btn-primary",onclick:function(){e._execute()}}),this.$header.addClass("ui-form-header").empty().append(new u.default.Label({title:"Workflow: "+this.model.get("name")}).$el).append(this.execute_btn.$el)},_renderMessage:function(){this.$message.empty(),this.model.get("has_upgrade_messages")&&this.$message.append(new u.default.Message({message:"Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.",status:"warning",persistent:!0,fade:!1}).$el);var e=this.model.get("step_version_changes");e&&e.length>0&&this.$message.append(new u.default.Message({message:"Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.",status:"warning",persistent:!0,fade:!1}).$el)},_renderParameters:function(){var e=this;this.wp_form=null,s.isEmpty(this.wp_inputs)||(this.wp_form=new f.default({title:"Workflow Parameters",inputs:this.wp_inputs,cls:"ui-portlet-narrow",onchange:function(){s.each(e.wp_form.input_list,function(t,i){s.each(t.links,function(t){e._refreshStep(t)})})}}),this._append(this.$steps.empty(),this.wp_form.$el))},_renderHistory:function(){this.history_form=new f.default({cls:"ui-portlet-narrow",title:"History Options",inputs:[{type:"conditional",name:"new_history",test_param:{name:"check",label:"Send results to a new history",type:"boolean",value:"false",help:""},cases:[{value:"true",inputs:[{name:"name",label:"History name",type:"text",value:this.model.get("name")}]}]}]}),this._append(this.$steps,this.history_form.$el)},_renderStep:function(e){var t=this,i=null;this.deferred.execute(function(a){if(t.$steps.addClass("ui-steps"),"tool"==e.step_type)e.postchange=function(t,i){var s={tool_id:e.id,tool_version:e.version,inputs:n.extend(!0,{},i.data.create())};i.wait(!0),Galaxy.emit.debug("tool-form-composite::postchange()","Sending current state.",s),l.default.request({type:"POST",url:Galaxy.root+"api/tools/"+e.id+"/build",data:s,success:function(e){i.update(e),i.wait(!1),Galaxy.emit.debug("tool-form-composite::postchange()","Received new model.",e),t.resolve()},error:function(e){Galaxy.emit.debug("tool-form-composite::postchange()","Refresh request failed.",e),t.reject()}})},i=new _.default(e),e.post_job_actions&&e.post_job_actions.length&&i.portlet.append(n("").addClass("ui-form-element-disabled").append(n("").addClass("ui-form-title").html("Job Post Actions")).append(n("").addClass("ui-form-preview").html(s.reduce(e.post_job_actions,function(e,t){return e+" "+t.short_str},""))));else{var o=-1!=["data_input","data_collection_input"].indexOf(e.step_type);s.each(e.inputs,function(e){e.flavor="module",e.hide_label=o}),i=new f.default(l.default.merge({title:e.fixed_title,onchange:function(){s.each(t.links[e.index],function(e){t._refreshStep(e)})},inputs:e.inputs&&e.inputs.length>0?e.inputs:[{type:"hidden",name:"No options available.",ignore:null}]},e))}t.forms[e.index]=i,t._append(t.$steps,i.$el),t._refresh(),e.needs_refresh&&t._refreshStep(e),i.portlet[t.show_progress?"disable":"enable"](),t.show_progress&&t.execute_btn.model.set({wait:!0,wait_text:"Preparing...",percentage:100*(e.index+1)/t.steps.length}),Galaxy.emit.debug("tool-form-composite::initialize()",e.index+" : Workflow step state ready.",e),setTimeout(function(){a.resolve()},0)})},_refreshStep:function(e){var t=this,i=this.forms[e.index];i?(s.each(t.parms[e.index],function(e,n){if(e.step_linked||e.wp_linked){var a=i.field_list[i.data.match(n)];if(a){var o=void 0;if(e.step_linked)o={values:[]},s.each(e.step_linked,function(e){if(t._isDataStep(e)){var i=t.forms[e.index].data.create().input;i&&s.each(i.values,function(e){o.values.push(e)})}}),!e.multiple&&o.values.length>0&&(o={values:[o.values[0]]});else if(e.wp_linked){o=e.value;for(var l,r=/\$\{(.+?)\}/g;l=r.exec(e.value);){var d=t.wp_form.field_list[t.wp_form.data.match(l[1])],c=d&&d.value();c&&(o=o.split(l[0]).join(c))}}void 0!==o&&a.value(o)}}}),i.trigger("change")):e.needs_refresh=!0},_refreshHistory:function(){var e=this,t=parent.Galaxy&&parent.Galaxy.currHistoryPanel&&parent.Galaxy.currHistoryPanel.model;this._refresh_history&&clearTimeout(this._refresh_history),t&&t.refresh().success(function(){0===t.numOfUnfinishedShownContents()&&(e._refresh_history=setTimeout(function(){e._refreshHistory()},t.UPDATE_DELAY))})},_execute:function(){var e=this;this.show_progress=!0,this._enabled(!1),this.deferred.execute(function(t){setTimeout(function(){t.resolve(),e._submit()},0)})},_submit:function(){var e=this,t=this.history_form.data.create(),i={new_history_name:t["new_history|name"]?t["new_history|name"]:null,history_id:t["new_history|name"]?null:this.model.get("history_id"),replacement_params:this.wp_form?this.wp_form.data.create():{},parameters:{},parameters_normalized:!0,batch:!0},s=!0;for(var a in this.forms){var o=this.forms[a],r=o.data.create(),d=e.steps[a],c=d.step_index;o.trigger("reset");for(var u in r){var h=r[u],f=o.data.match(u),p=(o.field_list[f],o.input_list[f]);if(!p.step_linked){if(!(s=this._isDataStep(d)?h&&h.values&&h.values.length>0:p.optional||p.is_workflow&&""!==h||!p.is_workflow&&null!==h)){o.highlight(f);break}i.parameters[c]=i.parameters[c]||{},i.parameters[c][u]=r[u]}}if(!s)break}s?(Galaxy.emit.debug("tool-form-composite::submit()","Validation complete.",i),l.default.request({type:"POST",url:Galaxy.root+"api/workflows/"+this.model.id+"/invocations",data:i,success:function(t){if(Galaxy.emit.debug("tool-form-composite::submit","Submission successful.",t),e.$el.children().hide(),e.$el.append(e._templateSuccess(t)),n.isArray(t)&&t.length>0){e.$el.append(n("",{id:"webhook-view"}));new b.default.WebhookView({urlRoot:Galaxy.root+"api/webhooks/workflow",toolId:i.tool_id,toolVersion:i.tool_version})}e._refreshHistory()},error:function(t){Galaxy.emit.debug("tool-form-composite::submit","Submission failed.",t);var n=!1;if(t&&t.err_data)for(var s in e.forms){var a=e.forms[s],o=t.err_data[a.model.get("step_index")];if(o){var l=a.data.matchResponse(o);for(var r in l){a.highlight(r,l[r]),n=!0;break}}}n||e.modal.show({title:"Workflow submission failed",body:e._templateError(i,t&&t.err_msg),buttons:{Close:function(){e.modal.hide()}}})},complete:function(){e._enabled(!0)}})):(e._enabled(!0),Galaxy.emit.debug("tool-form-composite::submit()","Validation failed.",i))},_append:function(e,t){e.append("").append(t)},_enabled:function(e){this.execute_btn.model.set({wait:!e,wait_text:"Sending...",percentage:-1}),this.wp_form&&this.wp_form.portlet[e?"enable":"disable"](),this.history_form&&this.history_form.portlet[e?"enable":"disable"](),s.each(this.forms,function(t){t&&t.portlet[e?"enable":"disable"]()})},_isDataStep:function(e){for(var t=n.isArray(e)?e:[e],i=0;i0?n("").addClass("donemessagelarge").append(n("").html("Successfully invoked workflow "+l.default.sanitize(this.model.get("name"))+""+(e.length>1?" "+e.length+" times":"")+".")).append(n("").append("").text("You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.")):this._templateError(e,"Invalid success response. No invocations found.")},_templateError:function(e,t){return n("").addClass("errormessagelarge").append(n("").text("The server could not complete the request. Please contact the Galaxy Team if this error persists. "+(JSON.stringify(t)||""))).append(n("").text(JSON.stringify(e,null,4)))}});t.default={View:$}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(7),l=a(o),r=i(79),d=a(r),c=i(4),u=a(c),h={defaultName:e.template("Copy of '<%- name %>'"),title:e.template((0,u.default)("Copying history")+' "<%- name %>"'),submitLabel:(0,u.default)("Copy"),errorMessage:(0,u.default)("History could not be copied."),progressive:(0,u.default)("Copying history"),activeLabel:(0,u.default)("Copy only the active, non-deleted datasets"),allLabel:(0,u.default)("Copy all datasets including deleted ones"),anonWarning:(0,u.default)("As an anonymous user, unless you login or register, you will lose your current history ")+(0,u.default)("after copying this history. "),_template:e.template(["<% if( isAnon ){ %>",'
";this.modal.$(".modal-body").empty().append(e).css({"margin-top":"8px"})},dialog:function(t,i,a){function o(){var e=t.$("#copy-modal-title").val();if(!e)return void t.$(".invalid-title").show();var n="copy-all"===t.$('input[name="copy-what"]:checked').val();t.$("button").prop("disabled",!0),l._showAjaxIndicator(),i.copy(!0,e,n).done(function(e){r.resolve(e)}).fail(function(t,s,a){var o={name:e,copyAllDatasets:n};d.default.ajaxErrorModal(i,t,o,l.errorMessage),r.rejectWith(r,arguments)}).done(function(){m&&t.hide()})}a=a||{};var l=this,r=n.Deferred(),c=a.nameFn||this.defaultName,h=c({name:i.get("name")}),f=a.allDatasets?"copy-all":"copy-non-deleted",p=!!e.isUndefined(a.allowAll)||a.allowAll,m=!!e.isUndefined(a.autoClose)||a.autoClose;this.modal=t;var g=a.closing_callback;return t.show(e.extend(a,{title:this.title({name:i.get("name")}),body:s(l._template({name:h,isAnon:Galaxy.user.isAnonymous(),allowAll:p,copyWhat:f,activeLabel:this.activeLabel,allLabel:this.allLabel,anonWarning:this.anonWarning})),buttons:e.object([[(0,u.default)("Cancel"),function(){t.hide()}],[this.submitLabel,o]]),height:"auto",closing_events:!0,closing_callback:function(e){e&&r.reject({cancelled:!0}),g&&g(e)}})),t.$("#copy-modal-title").focus().select(),t.$("#copy-modal-title").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),o())}),r}},f=e.extend({},h,{defaultName:e.template("imported: <%- name %>"),title:e.template((0,u.default)("Importing history")+' "<%- name %>"'),submitLabel:(0,u.default)("Import"),errorMessage:(0,u.default)("History could not be imported."),progressive:(0,u.default)("Importing history"),activeLabel:(0,u.default)("Import only the active, non-deleted datasets"),allLabel:(0,u.default)("Import all datasets including deleted ones"),anonWarning:(0,u.default)("As an anonymous user, unless you login or register, you will lose your current history ")+(0,u.default)("after importing this history. ")}),p=function(e,t){t=t||{};var i=window.parent.Galaxy.modal||new l.default.View({});return t.useImport?f.dialog(i,e,t):h.dialog(i,e,t)};t.default=p}).call(t,i(1),i(0),i(0))},function(e,t,i){"use strict";(function(e,n){function s(t,i,n){return Galaxy.modal.show({title:i,body:t,closing_events:!0,buttons:{Ok:function(){Galaxy.modal.hide()}}}),Galaxy.modal.$el.addClass("error-modal"),n&&(Galaxy.modal.$(".error-details").add(Galaxy.modal.$('button:contains("Details")')).remove(),e("").addClass("error-details").hide().appendTo(Galaxy.modal.$(".modal-content")).append([e("").text(p),e("").text(JSON.stringify(n,null," "))]),e('").appendTo(Galaxy.modal.$(".buttons")).click(function(){Galaxy.modal.$(".error-details").toggle()})),Galaxy.modal}function a(e,t,i){if(e){if(e=(0,u.default)(e),t=(0,u.default)(t)||(0,u.default)("Error:"),window.Galaxy&&Galaxy.modal)return s(e,t,i);alert(t+"\n\n"+e),console.log("error details:",JSON.stringify(i))}}function o(){return a((0,u.default)("You appear to be offline. Please check your connection and try again."),(0,u.default)("Offline?"))}function l(){return a((0,u.default)("Galaxy is currently unreachable. Please try again in a few minutes.")+" "+h,(0,u.default)("Cannot connect to Galaxy"))}function r(e,t,i,n,s){return n=n||f,n+=" "+h,s=s||(0,u.default)("An error occurred"),a(n,s,d(e,t,i))}function d(e,t,i){return{raven:n.result(window.Raven,"lastEventId"),userAgent:navigator.userAgent,onLine:navigator.onLine,version:n.result(Galaxy.config,"version_major"),xhr:n.omit(t,n.functions(t)),options:n.omit(i,"xhr"),url:n.result(Galaxy.lastAjax,"url"),data:n.result(Galaxy.lastAjax,"data"),model:n.result(e,"toJSON",""+e),user:n.omit(n.result(Galaxy.user,"toJSON"),"email")}}Object.defineProperty(t,"__esModule",{value:!0});var c=i(4),u=function(e){return e&&e.__esModule?e:{default:e}}(c),h=(0,u.default)("Please contact a Galaxy administrator if the problem persists."),f=(0,u.default)("An error occurred while updating information with the server."),p=(0,u.default)("The following information can assist the developers in finding the source of the error:");t.default={errorModal:a,offlineErrorModal:o,badGatewayErrorModal:l,ajaxErrorModal:r}}).call(t,i(0),i(1))},function(e,t,i){"use strict";(function(e){function n(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t.default=e,t}Object.defineProperty(t,"__esModule",{value:!0});var s=i(1),a=n(s),o=i(2),l=n(o),r=i(5),d=function(e){return e&&e.__esModule?e:{default:e}}(r),c=l.Collection.extend({initialize:function(e,t){l.Collection.prototype.initialize.call(this,e,t),this.setOrder(t.order||this.order,{silent:!0})},_setUpListeners:function(){return this.on({"changed-order":this.sort})},fetch:function(e){return e=this._buildFetchOptions(e),Galaxy.debug("fetch options:",e),l.Collection.prototype.fetch.call(this,e)},_buildFetchOptions:function(e){e=a.clone(e)||{};var t=this;e.traditional=!0,e.data=e.data||t._buildFetchData(e),Galaxy.debug("data:",e.data);var i=this._buildFetchFilters(e);return Galaxy.debug("filters:",i),a.isEmpty(i)||a.extend(e.data,this._fetchFiltersToAjaxData(i)),Galaxy.debug("data:",e.data),e},_buildFetchData:function(e){var t={};return this.order&&(t.order=this.order),a.defaults(a.pick(e,this._fetchParams),t)},_fetchParams:["order","limit","offset","view","keys"],_buildFetchFilters:function(e){return a.clone(e.filters||{})},_fetchFiltersToAjaxData:function(e){var t={q:[],qv:[]};return a.each(e,function(e,i){void 0!==e&&""!==e&&(!0===e&&(e="True"),!1===e&&(e="False"),null===e&&(e="None"),t.q.push(i),t.qv.push(e))}),t},reset:function(e,t){return this.allFetched=!1,l.Collection.prototype.reset.call(this,e,t)},order:null,comparators:{update_time:d.default.buildComparator("update_time",{ascending:!1}),"update_time-asc":d.default.buildComparator("update_time",{ascending:!0}),create_time:d.default.buildComparator("create_time",{ascending:!1}),"create_time-asc":d.default.buildComparator("create_time",{ascending:!0})},setOrder:function(e,t){t=t||{};var i=this,n=i.comparators[e];if(a.isUndefined(n))throw new Error("unknown order: "+e);if(n!==i.comparator)return i.order=e,i.comparator=n,t.silent||i.trigger("changed-order",t),i}}),u=c.extend({limitPerPage:500,initialize:function(e,t){c.prototype.initialize.call(this,e,t),this.currentPage=t.currentPage||0},getTotalItemCount:function(){return this.length},shouldPaginate:function(){return this.getTotalItemCount()>=this.limitPerPage},getLastPage:function(){return Math.floor(this.getTotalItemCount()/this.limitPerPage)},getPageCount:function(){return this.getLastPage()+1},getPageLimitOffset:function(e){return e=this.constrainPageNum(e),{limit:this.limitPerPage,offset:e*this.limitPerPage}},constrainPageNum:function(e){return Math.max(0,Math.min(e,this.getLastPage()))},fetchPage:function(e,t){var i=this;return e=i.constrainPageNum(e),i.currentPage=e,t=a.defaults(t||{},i.getPageLimitOffset(e)),i.trigger("fetching-more"),i.fetch(t).always(function(){i.trigger("fetching-more-done")})},fetchCurrentPage:function(e){return this.fetchPage(this.currentPage,e)},fetchPrevPage:function(e){return this.fetchPage(this.currentPage-1,e)},fetchNextPage:function(e){return this.fetchPage(this.currentPage+1,e)}}),h=c.extend({limitOnFirstFetch:null,limitPerFetch:100,initialize:function(e,t){c.prototype.initialize.call(this,e,t),this.limitOnFirstFetch=t.limitOnFirstFetch||this.limitOnFirstFetch,this.limitPerFetch=t.limitPerFetch||this.limitPerFetch,this.allFetched=!1,this.lastFetched=t.lastFetched||0},_buildFetchOptions:function(e){return e.remove=e.remove||!1,c.prototype._buildFetchOptions.call(this,e)},fetchFirst:function(e){return Galaxy.debug("ControlledFetchCollection.fetchFirst:",e),e=e?a.clone(e):{},this.allFetched=!1,this.lastFetched=0,this.fetchMore(a.defaults(e,{reset:!0,limit:this.limitOnFirstFetch}))},fetchMore:function(t){Galaxy.debug("ControlledFetchCollection.fetchMore:",t),t=a.clone(t||{});var i=this;if(Galaxy.debug("fetchMore, options.reset:",t.reset),!t.reset&&i.allFetched)return e.when();t.reset?t.offset=0:void 0===t.offset&&(t.offset=i.lastFetched);var n=t.limit=t.limit||i.limitPerFetch||null;return Galaxy.debug("fetchMore, limit:",n,"offset:",t.offset),i.trigger("fetching-more"),i.fetch(t).always(function(){i.trigger("fetching-more-done")}).done(function(e){var t=a.isArray(e)?e.length:0;i.lastFetched+=t,Galaxy.debug("fetchMore, lastFetched:",i.lastFetched),(!n||t1?this.renderItems():1===i.added.length?this.addItemView(n.first(i.added),e,t):1===i.removed.length?this.removeItemView(n.first(i.removed),e,t):void 0}}),this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners"),this.on({"view:selected":function(e,t){if(t&&t.shiftKey&&this.lastSelected){var i=this.viewFromModelId(this.lastSelected);i&&this.selectRange(e,i)}else t&&t.altKey&&!this.selecting&&this.showSelectors();this.selected.push(e.model.id),this.lastSelected=e.model.id},"view:de-selected":function(e,t){this.selected=n.without(this.selected,e.model.id)}})},render:function(e){this.log(this+".render",e);var t=this._buildNewRender();return this._setUpBehaviors(t),this._queueNewRender(t,e),this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var e=s(this.templates.el({},this));return this._renderControls(e),this._renderTitle(e),this._renderSubtitle(e),this._renderSearch(e),this.renderItems(e),e},_renderControls:function(e){this.debug(this+"(ListPanel)._renderControls");var t=s(this.templates.controls({},this));return e.find(".controls").replaceWith(t),t},_renderTitle:function(e){},_renderSubtitle:function(e){},_queueNewRender:function(e,t){t=void 0===t?this.fxSpeed:t;var i=this;i.log("_queueNewRender:",e,t),s(i).queue("fx",[function(e){i.$el.fadeOut(t,e)},function(t){i._swapNewRender(e),t()},function(e){i.$el.fadeIn(t,e)},function(e){i.trigger("rendered",i),e()}])},_swapNewRender:function(e){return this.$el.empty().attr("class",this.className).append(e.children()),this.selecting&&this.showSelectors(0),this},_setUpBehaviors:function(e){return e=e||this.$el,this.$controls(e).find("[title]").tooltip(),this._renderMultiselectActionMenu(e),this},_renderMultiselectActionMenu:function(e){e=e||this.$el;var t=e.find(".list-action-menu"),i=this.multiselectActions();if(!i.length)return t.empty();var n=s(['
"],"collection");return e.extend(e.clone(f.prototype.templates),{controls:t})}();var m=p.extend({DatasetDCEViewClass:r.default.DatasetDCEListItemView,toString:function(){return"ListCollectionView("+(this.model?this.model.get("name"):"")+")"}}),g=m.extend({toString:function(){return"PairCollectionView("+(this.model?this.model.get("name"):"")+")"}}),_=p.extend({NestedDCDCEViewClass:r.default.NestedDCDCEListItemView.extend({foldoutPanelClass:g}),toString:function(){return"ListOfPairsCollectionView("+(this.model?this.model.get("name"):"")+")"}}),v=p.extend({NestedDCDCEViewClass:r.default.NestedDCDCEListItemView.extend({foldoutPanelClass:g}),toString:function(){return"ListOfListsCollectionView("+(this.model?this.model.get("name"):"")+")"}});t.default={CollectionView:p,ListCollectionView:m,PairCollectionView:g,ListOfPairsCollectionView:_,ListOfListsCollectionView:v}}).call(t,i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(11),o=s(a),l=i(42),r=s(l),d=i(22),c=s(d),u=i(88),h=s(u),f=i(14),p=s(f),m=i(5),g=s(m),_=i(4),v=s(_),w=r.default.DatasetListItemView,y=w.extend({initialize:function(e){w.prototype.initialize.call(this,e),this.hasUser=e.hasUser,this.purgeAllowed=e.purgeAllowed||!1,this.tagsEditorShown=e.tagsEditorShown||!1,this.annotationEditorShown=e.annotationEditorShown||!1},_renderPrimaryActions:function(){var e=w.prototype._renderPrimaryActions.call(this);return this.model.get("state")===o.default.NOT_VIEWABLE?e:w.prototype._renderPrimaryActions.call(this).concat([this._renderEditButton(),this._renderDeleteButton()])},_renderEditButton:function(){var t=this;if(this.model.get("state")===o.default.DISCARDED||!this.model.get("accessible"))return null;var i=this.model.get("purged"),n=this.model.get("deleted"),s={title:(0,v.default)("Edit attributes"),href:Galaxy.root+"datasets/edit?dataset_id="+this.model.attributes.id,faIcon:"fa-pencil",classes:"edit-btn",onclick:function(e){Galaxy.router&&(e.preventDefault(),Galaxy.router.push("datasets/edit",{dataset_id:t.model.attributes.id}))}};return n||i?(s.disabled=!0,i?s.title=(0,v.default)("Cannot edit attributes of datasets removed from disk"):n&&(s.title=(0,v.default)("Undelete dataset to edit attributes"))):e.contains([o.default.UPLOAD,o.default.NEW],this.model.get("state"))&&(s.disabled=!0,s.title=(0,v.default)("This dataset is not yet editable")),(0,p.default)(s)},_renderDeleteButton:function(){if(!this.model.get("accessible"))return null;var e=this,t=this.model.isDeletedOrPurged();return(0,p.default)({title:t?(0,v.default)("Dataset is already deleted"):(0,v.default)("Delete"),disabled:t,faIcon:"fa-times",classes:"delete-btn",onclick:function(){e.$el.find(".icon-btn.delete-btn").trigger("mouseout"),e.model.delete()}})},_renderDetails:function(){var t=w.prototype._renderDetails.call(this),i=this.model.get("state");return!this.model.isDeletedOrPurged()&&e.contains([o.default.OK,o.default.FAILED_METADATA],i)&&(this._renderTags(t),this._renderAnnotation(t),this._makeDbkeyEditLink(t)),this._setUpBehaviors(t),t},_renderToolHelpButton:function(){var e=this.model.attributes.dataset_id,t=this.model.attributes.creating_job,i=this,s=function(t){var s='
';t.name&&t.help?(s+="Tool help for "+t.name+"",s+=t.help):s+="Tool help is unavailable for this dataset.",s+="
",i.$el.find(".details").append(n.parseHTML(s))},a=function(e){n.ajax({url:Galaxy.root+"api/tools/"+e.tool_id+"/build"}).done(function(e){s(e)}).fail(function(){s({})})};return null===Galaxy.user.id?null:(0,p.default)({title:(0,v.default)("Tool Help"),classes:"icon-btn",href:"#",faIcon:"fa-question",onclick:function(){i.$el.find(".toolhelp").length>0?i.$el.find(".toolhelp").toggle():n.ajax({url:Galaxy.root+"api/jobs/"+t}).done(function(e){a(e)}).fail(function(){console.log('Failed at recovering job information from the Galaxy API for job id "'+t+'".')})}})},_renderSecondaryActions:function(){var e=w.prototype._renderSecondaryActions.call(this);switch(this.model.get("state")){case o.default.UPLOAD:case o.default.NOT_VIEWABLE:return e;case o.default.ERROR:return e.unshift(this._renderErrButton()),e.concat([this._renderRerunButton(),this._renderToolHelpButton()]);case o.default.OK:case o.default.FAILED_METADATA:return e.concat([this._renderRerunButton(),this._renderVisualizationsButton(),this._renderToolHelpButton()])}return e.concat([this._renderRerunButton(),this._renderToolHelpButton()])},_renderErrButton:function(){var e=this;return(0,p.default)({title:(0,v.default)("View or report this error"),href:Galaxy.root+"datasets/error?dataset_id="+this.model.attributes.id,classes:"report-error-btn",faIcon:"fa-bug",onclick:function(t){Galaxy.router&&(t.preventDefault(),Galaxy.router.push("datasets/error",{dataset_id:e.model.attributes.id}))}})},_renderRerunButton:function(){var e=this.model.get("creating_job");if(this.model.get("rerunnable"))return(0,p.default)({title:(0,v.default)("Run this job again"),href:this.model.urls.rerun,classes:"rerun-btn",target:this.linkTarget,faIcon:"fa-refresh",onclick:function(t){Galaxy.router&&(t.preventDefault(),Galaxy.router.push("/",{job_id:e}))}})},_renderVisualizationsButton:function(){var t=this.model.get("visualizations");if(this.model.isDeletedOrPurged()||!this.hasUser||!this.model.hasData()||e.isEmpty(t))return null;if(!e.isObject(t[0]))return this.warn("Visualizations have been switched off"),null;var i=n(this.templates.visualizations(t,this));return i.find('[target="galaxy_main"]').attr("target",this.linkTarget),this._addScratchBookFn(i.find(".visualization-link").addBack(".visualization-link")),i},_addScratchBookFn:function(e){e.click(function(e){Galaxy.frame&&Galaxy.frame.active&&(Galaxy.frame.add({title:"Visualization",url:n(this).attr("href")}),e.preventDefault(),e.stopPropagation())})},_renderTags:function(e){if(this.hasUser){var t=this;this.tagsEditor=new c.default.TagsEditor({model:this.model,el:e.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.tagsEditorShown=!0},onhide:function(){t.tagsEditorShown=!1},$activator:(0,p.default)({title:(0,v.default)("Edit dataset tags"),classes:"tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".actions .right"))}),this.tagsEditorShown&&this.tagsEditor.toggle(!0)}},_renderAnnotation:function(e){if(this.hasUser){var t=this;this.annotationEditor=new h.default.AnnotationEditor({model:this.model,el:e.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.annotationEditorShown=!0},onhide:function(){t.annotationEditorShown=!1},$activator:(0,p.default)({title:(0,v.default)("Edit dataset annotation"),classes:"annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".actions .right"))}),this.annotationEditorShown&&this.annotationEditor.toggle(!0)}},_makeDbkeyEditLink:function(e){if("?"===this.model.get("metadata_dbkey")&&!this.model.isDeletedOrPurged()){var t=n('?').attr("href",this.model.urls.edit).attr("target","_top");e.find(".dbkey .value").replaceWith(t)}},events:e.extend(e.clone(w.prototype.events),{"click .undelete-link":"_clickUndeleteLink","click .purge-link":"_clickPurgeLink","click .edit-btn":function(e){this.trigger("edit",this,e)},"click .delete-btn":function(e){this.trigger("delete",this,e)},"click .rerun-btn":function(e){this.trigger("rerun",this,e)},"click .report-err-btn":function(e){this.trigger("report-err",this,e)},"click .visualization-btn":function(e){this.trigger("visualize",this,e)},"click .dbkey a":function(e){this.trigger("edit",this,e)}}),_clickUndeleteLink:function(e){return this.model.undelete(),!1},_clickPurgeLink:function(e){return confirm((0,v.default)("This will permanently remove the data in your dataset. Are you sure?"))&&this.model.purge(),!1},toString:function(){return"HDAEditView("+(this.model?""+this.model:"(no model)")+")"}});y.prototype.templates=function(){var t=e.extend({},w.prototype.templates.warnings,{failed_metadata:g.default.wrapTemplate(['<% if( dataset.state === "failed_metadata" ){ %>','
',"",(0,c.default)("Search did not match any tools."),"","
","
",'','','
',"",(0,c.default)("Workflows"),"","
",'
','',"
","
"].join("")},toString:function(){return"toolPanel"}}));t.default=h}).call(t,i(2),i(1))},function(e,t,i){"use strict";(function(e){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var s=i(3),a=n(s),o=i(7),l=n(o),r=i(28),d=n(r),c=i(140),u=n(c),h=i(141),f=n(h),p=i(144),m=n(p),g=i(146),_=n(g);t.default=e.View.extend({options:{nginx_upload_path:"",ftp_upload_site:"n/a",default_genome:"?",default_extension:"auto",height:500,width:900,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."}},list_extensions:[],list_genomes:[],initialize:function(e){var t=this;this.options=a.default.merge(e,this.options),this.ui_button=new u.default.View({onclick:function(e){e.preventDefault(),t.show()},onunload:function(){var e=t.ui_button.model.get("percentage",0);if(e>0&&e<100)return"Several uploads are queued."}}),this.setElement(this.ui_button.$el);var t=this;a.default.get({url:Galaxy.root+"api/datatypes?extension_only=False",success:function(e){for(var i in e)t.list_extensions.push({id:e[i].extension,text:e[i].extension,description:e[i].description,description_url:e[i].description_url,composite_files:e[i].composite_files});t.list_extensions.sort(function(e,t){var i=e.text&&e.text.toLowerCase(),n=t.text&&t.text.toLowerCase();return i>n?1:ii.text?1:e.text0){var n={file_count:e.length,dbkey:e[0].get("genome","?"),file_type:e[0].get("extension","auto")};for(var s in e){var a=e[s];if(a.set("status","running"),!(a.get("file_size")>0)){i.error_message="Upload content incomplete.",a.set("status","error"),a.set("info",i.error_message);break}var o="files_"+s+"|";switch(n[o+"type"]="upload_dataset",n[o+"space_to_tab"]=a.get("space_to_tab")&&"Yes"||null,n[o+"to_posix_lines"]=a.get("to_posix_lines")&&"Yes"||null,n[o+"dbkey"]=a.get("genome",null),n[o+"file_type"]=a.get("extension",null),a.get("file_mode")){case"new":n[o+"url_paste"]=a.get("url_paste");break;case"ftp":n[o+"ftp_files"]=a.get("file_path");break;case"local":i.files.push({name:o+"file_data",file:a.get("file_data")})}}i.payload.inputs=JSON.stringify(n)}return i}})}).call(t,i(2))},function(e,t,i){"use strict";(function(e,i){Object.defineProperty(t,"__esModule",{value:!0});var n=e.View.extend({initialize:function(t){var n=this;this.model=t&&t.model||new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",percentage:0,status:"",onunload:function(){},onclick:function(){}}).set(t),this.setElement(this._template()),this.$progress=this.$(".progress-bar"),this.listenTo(this.model,"change",this.render,this),this.render(),i(window).on("beforeunload",function(){return n.model.get("onunload")()})},render:function(){var e=this.model.attributes;this.$el.off("click").on("click",function(t){e.onclick(t)}).tooltip({title:this.model.get("tooltip"),placement:"bottom"}),this.$progress.removeClass().addClass("progress-bar").addClass("progress-bar-notransition").addClass(""!=e.status&&"progress-bar-"+e.status).css({width:e.percentage+"%"})},_template:function(){return'
'}});t.default={View:n}}).call(t,i(2),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(16)),r=a(l),d=i(142),c=a(d),u=i(32),h=a(u),f=i(33),p=a(f),m=i(10),g=a(m),_=i(13),v=a(_),w=i(6),y=a(w),b=i(143),x=a(b);i(34),t.default=e.View.extend({upload_size:0,collection:new r.default.Collection,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(e){var t=this;this.app=e,this.options=e.options,this.list_extensions=e.list_extensions,this.list_genomes=e.list_genomes,this.ui_button=e.ui_button,this.ftp_upload_site=e.currentFtp(),this.setElement(this._template()),this.$uploadbox=this.$(".upload-box"),this.$uploadtable=this.$(".upload-table"),this.btnLocal=new y.default.Button({id:"btn-local",title:"Choose local file",onclick:function(){t.uploadbox.select()},icon:"fa fa-laptop"}),this.btnFtp=new y.default.Button({id:"btn-ftp",title:"Choose FTP file",onclick:function(){t._eventFtp()},icon:"fa fa-folder-open-o"}),this.btnCreate=new y.default.Button({id:"btn-new",title:"Paste/Fetch data",onclick:function(){t._eventCreate()},icon:"fa fa-edit"}),this.btnStart=new y.default.Button({id:"btn-start",title:"Start",onclick:function(){t._eventStart()}}),this.btnStop=new y.default.Button({id:"btn-stop",title:"Pause",onclick:function(){t._eventStop()}}),this.btnReset=new y.default.Button({id:"btn-reset",title:"Reset",onclick:function(){t._eventReset()}}),this.btnClose=new y.default.Button({id:"btn-close",title:"Close",onclick:function(){t.app.modal.hide()}}),n.each([this.btnLocal,this.btnFtp,this.btnCreate,this.btnStop,this.btnReset,this.btnStart,this.btnClose],function(e){t.$(".upload-buttons").prepend(e.$el)}),this.uploadbox=this.$uploadbox.uploadbox({url:this.app.options.nginx_upload_path,announce:function(e,i){t._eventAnnounce(e,i)},initialize:function(e){return t.app.toData([t.collection.get(e)],t.history_id)},progress:function(e,i){t._eventProgress(e,i)},success:function(e,i){t._eventSuccess(e,i)},error:function(e,i){t._eventError(e,i)},complete:function(){t._eventComplete()},ondragover:function(){t.$uploadbox.addClass("highlight")},ondragleave:function(){t.$uploadbox.removeClass("highlight")}}),this.ftp=new g.default.View({title:"FTP files",container:this.btnFtp.$el}),this.select_extension=new v.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-extension"),data:n.filter(this.list_extensions,function(e){return!e.composite_files}),value:this.options.default_extension,onchange:function(e){t._changeExtension(e)}}),this.$(".upload-footer-extension-info").on("click",function(e){new p.default({$el:s(e.target),title:t.select_extension.text(),extension:t.select_extension.value(),list:t.list_extensions,placement:"top"})}).on("mousedown",function(e){e.preventDefault()}),this.select_genome=new v.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-genome"),data:this.list_genomes,value:this.options.default_genome,onchange:function(e){t._changeGenome(e)}}),this.loader=new x.default({$container:this.$uploadbox,collection:this.collection,new_content:function(e){var i=new c.default(t,{model:e});return t.$uploadtable.find("> tbody:first").append(i.$el),i.render(),i}}),this.collection.on("remove",function(e){t._eventRemove(e)}),this.render()},render:function(){var e="";e=0==this.counter.announce?this.uploadbox.compatible()?" ":"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.":0==this.counter.running?"You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed.":"Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining.",this.$(".upload-top-info").html(e);var t=0==this.counter.running&&this.counter.announce+this.counter.success+this.counter.error>0,i=0==this.counter.running&&this.counter.announce>0,n=0==this.counter.running,s=this.counter.announce+this.counter.success+this.counter.error>0;this.btnReset[t?"enable":"disable"](),this.btnStart[i?"enable":"disable"](),this.btnStart.$el[i?"addClass":"removeClass"]("btn-primary"),this.btnStop[this.counter.running>0?"enable":"disable"](),this.btnLocal[n?"enable":"disable"](),this.btnFtp[n?"enable":"disable"](),this.btnCreate[n?"enable":"disable"](),this.btnFtp.$el[this.ftp_upload_site?"show":"hide"](),this.$(".upload-table")[s?"show":"hide"](),this.$(".upload-helper")[s?"hide":"show"]()},_eventAnnounce:function(e,t){this.counter.announce++;var i=new r.default.Model({id:e,file_name:t.name,file_size:t.size,file_mode:t.mode||"local",file_path:t.path,file_data:t});this.render(),this.collection.add(i)},_eventProgress:function(e,t){var i=this.collection.get(e);i.set("percentage",t),this.ui_button.model.set("percentage",this._uploadPercentage(t,i.get("file_size")))},_eventSuccess:function(e,t){var i=this.collection.get(e);i.set({percentage:100,status:"success"}),this.ui_button.model.set("percentage",this._uploadPercentage(100,i.get("file_size"))),this.upload_completed+=100*i.get("file_size"),this.counter.announce--,this.counter.success++,this.render(),Galaxy.currHistoryPanel.refreshContents()},_eventError:function(e,t){var i=this.collection.get(e);i.set({percentage:100,status:"error",info:t}),this.ui_button.model.set({percentage:this._uploadPercentage(100,i.get("file_size")),status:"danger"}),this.upload_completed+=100*i.get("file_size"),this.counter.announce--,this.counter.error++,this.render()},_eventComplete:function(){this.collection.each(function(e){"queued"==e.get("status")&&e.set("status","init")}),this.counter.running=0,this.render()},_eventRemove:function(e){var t=e.get("status");"success"==t?this.counter.success--:"error"==t?this.counter.error--:this.counter.announce--,this.uploadbox.remove(e.id),this.render()},_eventFtp:function(){if(this.ftp.visible)this.ftp.hide();else{this.ftp.empty();var e=this;this.ftp.append(new h.default({collection:this.collection,ftp_upload_site:this.ftp_upload_site,onadd:function(t){return e.uploadbox.add([{mode:"ftp",name:t.path,size:t.size,path:t.path}])},onremove:function(t){e.collection.remove(t)}}).$el),this.ftp.show()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(0!=this.counter.announce&&0==this.counter.running){var e=this;this.upload_size=0,this.upload_completed=0,this.collection.each(function(t){"init"==t.get("status")&&(t.set("status","queued"),e.upload_size+=t.get("file_size"))}),this.ui_button.model.set({percentage:0,status:"success"}),this.counter.running=this.counter.announce,this.history_id=this.app.currentHistory(),this._uploadFtp(),this.uploadbox.start(),this.render()}},_eventStop:function(){this.counter.running>0&&(this.ui_button.model.set("status","info"),s(".upload-top-info").html("Queue will pause after completing the current file..."),this.uploadbox.stop())},_eventReset:function(){if(0==this.counter.running){this.collection.reset(),this.counter.reset(),this.uploadbox.reset(),this.select_extension.value(this.options.default_extension),this.select_genome.value(this.options.default_genome),this.ui_button.model.set("percentage",0),this.render()}},_changeExtension:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("extension")!=i.options.default_extension&&t||n.set("extension",e)})},_changeGenome:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("genome")!=i.options.default_genome&&t||n.set("genome",e)})},_uploadFtp:function(){var e=this,t=[];this.collection.each(function(i){"queued"==i.get("status")&&"ftp"==i.get("file_mode")&&(e.uploadbox.remove(i.id),t.push(i))}),t.length>0&&s.uploadpost({data:this.app.toData(t),url:this.app.options.nginx_upload_path,success:function(i){n.each(t,function(t){e._eventSuccess(t.id)})},error:function(i){n.each(t,function(t){e._eventError(t.id,i)})}})},_uploadPercentage:function(e,t){return(this.upload_completed+e*t)/this.upload_size},_template:function(){return'
Drop files here
Name
Size
Type
Genome
Settings
Status
'}})}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(16),d=(a(r),i(31)),c=a(d),u=i(10),h=a(u),f=i(13),p=a(f);t.default=e.View.extend({status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},initialize:function(e,t){var i=this;this.app=e,this.model=t.model,this.setElement(this._template(t.model)),this.$mode=this.$(".upload-mode"),this.$title=this.$(".upload-title"),this.$text=this.$(".upload-text"),this.$size=this.$(".upload-size"),this.$info_text=this.$(".upload-info-text"),this.$info_progress=this.$(".upload-info-progress"),this.$text_content=this.$(".upload-text-content"),this.$settings=this.$(".upload-settings"),this.$symbol=this.$(".upload-symbol"),this.$progress_bar=this.$(".upload-progress-bar"),this.$percentage=this.$(".upload-percentage"),this.settings=new h.default.View({title:"Upload configuration",container:this.$(".upload-settings"),placement:"bottom"});var s=this.app.select_genome.value(),a=this.app.select_extension.value();this.select_genome=new p.default.View({css:"upload-genome",data:i.app.list_genomes,container:this.$(".upload-genome"),value:s,onchange:function(e){i.model.set("genome",e)}}),this.select_extension=new p.default.View({css:"upload-extension",data:i.app.list_extensions,container:this.$(".upload-extension"),value:a,onchange:function(e){i.model.set("extension",e)}}),this.model.set({genome:s,extension:a}),this.$symbol.on("click",function(){i._removeRow()}),this.$(".upload-extension-info").on("click",function(e){i.app.showExtensionInfo({$el:n(e.target),title:i.select_extension.text(),extension:i.select_extension.value()})}).on("mousedown",function(e){e.preventDefault()}),this.$settings.on("click",function(e){i._showSettings()}).on("mousedown",function(e){e.preventDefault()}),this.$text_content.on("change input",function(e){i.model.set({url_paste:n(e.target).val(),file_size:n(e.target).val().length})}),this.listenTo(this.model,"change:percentage",function(){i._refreshPercentage()}),this.listenTo(this.model,"change:status",function(){i._refreshStatus()}),this.listenTo(this.model,"change:info",function(){i._refreshInfo()}),this.listenTo(this.model,"change:genome",function(){i._refreshGenome()}),this.listenTo(this.model,"change:extension",function(){i._refreshExtension()}),this.listenTo(this.model,"change:file_size",function(){i._refreshFileSize()})},render:function(){this._refreshType(),this._refreshPercentage(),this._refreshStatus(),this._refreshInfo(),this._refreshGenome(),this._refreshExtension(),this._refreshFileSize()},remove:function(){this.select_genome.remove(),this.select_extension.remove(),e.View.prototype.remove.apply(this)},_refreshType:function(){var e=this.model.attributes;this.$title.html(s.escape(e.file_name)),this.$size.html(l.default.bytesToString(e.file_size)),this.$mode.removeClass().addClass("upload-mode").addClass("text-primary"),"new"==e.file_mode?(this.$text.css({width:this.$el.width()-16+"px",top:this.$el.height()-8+"px"}).show(),this.$el.height(this.$el.height()-8+this.$text.height()+16),this.$mode.addClass("fa fa-edit")):"local"==e.file_mode?this.$mode.addClass("fa fa-laptop"):"ftp"==e.file_mode&&this.$mode.addClass("fa fa-folder-open-o")},_refreshExtension:function(){this.select_extension.value(this.model.get("extension"))},_refreshGenome:function(){this.select_genome.value(this.model.get("genome"))},_refreshInfo:function(){var e=this.model.get("info");e?this.$info_text.html("Failed: "+e).show():this.$info_text.hide()},_refreshPercentage:function(){var e=parseInt(this.model.get("percentage"));this.$progress_bar.css({width:e+"%"}),this.$percentage.html(100!=e?e+"%":"Adding to history...")},_refreshStatus:function(){var e=this.model.get("status");this.$symbol.removeClass().addClass("upload-symbol").addClass(this.status_classes[e]),this.model.set("enabled","init"==e);var t=this.model.get("enabled");this.$text_content.attr("disabled",!t),t?(this.select_genome.enable(),this.select_extension.enable()):(this.select_genome.disable(),this.select_extension.disable()),"success"==e&&(this.$el.addClass("success"),this.$percentage.html("100%")),"error"==e&&(this.$el.addClass("danger"),this.$info_progress.hide())},_refreshFileSize:function(){this.$size.html(l.default.bytesToString(this.model.get("file_size")))},_removeRow:function(){-1!==["init","success","error"].indexOf(this.model.get("status"))&&this.app.collection.remove(this.model)},_showSettings:function(){this.settings.visible?this.settings.hide():(this.settings.empty(),this.settings.append(new c.default(this).$el),this.settings.show())},_template:function(e){return'
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
 
0%
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,i,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=e.View.extend({initialize:function(e){this.$container=e.$container,this.collection=e.collection,this.new_content=e.new_content,this.max=e.max||50,this.content_list={},this.$message=i("").addClass("ui-limitloader").append("...only the first "+this.max+" entries are visible."),this.$container.append(this.$message),this.listenTo(this.collection,"reset",this._reset,this),this.listenTo(this.collection,"add",this._refresh,this),this.listenTo(this.collection,"remove",this._remove,this)},_done:function(){var e=n.size(this.content_list)>this.max;return this.$message[e?"show":"hide"](),e},_reset:function(){n.each(this.content_list,function(e){e.remove()}),this.content_list={},this.$message.hide()},_remove:function(e){var t=e.id,i=this.content_list[t];i&&(i.remove(),delete this.content_list[t]),this._refresh()},_refresh:function(){if(!this._done())for(var e in this.collection.models){var t=this.collection.models[e];this.content_list[t.id];if(!this.content_list[t.id]){var i=this.new_content(t);if(this.content_list[t.id]=i,this._done())break}}}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(16)),r=a(l),d=i(145),c=a(d),u=i(33),h=a(u),f=i(10),p=(a(f),i(13)),m=a(p),g=i(6),_=a(g);t.default=e.View.extend({collection:new r.default.Collection,initialize:function(e){var t=this;this.app=e,this.options=e.options,this.list_extensions=e.list_extensions,this.list_genomes=e.list_genomes,this.ftp_upload_site=e.currentFtp(),this.setElement(this._template()),this.btnStart=new _.default.Button({title:"Start",onclick:function(){t._eventStart()}}),this.btnClose=new _.default.Button({title:"Close",onclick:function(){t.app.modal.hide()}}),n.each([this.btnStart,this.btnClose],function(e){t.$(".upload-buttons").prepend(e.$el)}),this.select_extension=new m.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-extension"),data:n.filter(this.list_extensions,function(e){return e.composite_files}),onchange:function(e){t.collection.reset();var i=n.findWhere(t.list_extensions,{id:e});i&&i.composite_files&&n.each(i.composite_files,function(e){t.collection.add({id:t.collection.size(),file_desc:e.description||e.name})})}}),this.$(".upload-footer-extension-info").on("click",function(e){new h.default({$el:s(e.target),title:t.select_extension.text(),extension:t.select_extension.value(),list:t.list_extensions,placement:"top"})}).on("mousedown",function(e){e.preventDefault()}),this.select_genome=new m.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-genome"),data:this.list_genomes,value:this.options.default_genome}),this.listenTo(this.collection,"add",function(e){t._eventAnnounce(e)}),this.listenTo(this.collection,"change add",function(){t.render()}),this.select_extension.options.onchange(this.select_extension.value()),this.render()},render:function(){var e=this.collection.first();e&&"running"==e.get("status")?(this.select_genome.disable(),this.select_extension.disable()):(this.select_genome.enable(),this.select_extension.enable()),this.collection.where({status:"ready"}).length==this.collection.length&&this.collection.length>0?(this.btnStart.enable(),this.btnStart.$el.addClass("btn-primary")):(this.btnStart.disable(),this.btnStart.$el.removeClass("btn-primary")),this.$(".upload-table")[this.collection.length>0?"show":"hide"]()},_eventAnnounce:function(e){var t=new c.default(this,{model:e});this.$(".upload-table > tbody:first").append(t.$el),this.$(".upload-table")[this.collection.length>0?"show":"hide"](),t.render()},_eventStart:function(){var e=this;this.collection.each(function(t){t.set({genome:e.select_genome.value(),extension:e.select_extension.value()})}),s.uploadpost({url:this.app.options.nginx_upload_path,data:this.app.toData(this.collection.filter()),success:function(t){e._eventSuccess(t)},error:function(t){e._eventError(t)},progress:function(t){e._eventProgress(t)}})},_eventProgress:function(e){this.collection.each(function(t){t.set("percentage",e)})},_eventSuccess:function(e){this.collection.each(function(e){e.set("status","success")}),Galaxy.currHistoryPanel.refreshContents()},_eventError:function(e){this.collection.each(function(t){t.set({status:"error",info:e})})},_template:function(){return'
Description
Name
Size
Settings
Status
'}})}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(31),d=a(r),c=i(32),u=a(c),h=i(10),f=a(h),p=i(6),m=a(p),g=i(13);a(g);i(34),t.default=e.View.extend({status_classes:{init:"upload-mode fa fa-exclamation text-primary",ready:"upload-mode fa fa-check text-success",running:"upload-mode fa fa-spinner fa-spin",success:"upload-mode fa fa-check",error:"upload-mode fa fa-exclamation-triangle"},initialize:function(e,t){var i=this;this.app=e,this.model=t.model,this.setElement(this._template()),this.$source=this.$(".upload-source"),this.$settings=this.$(".upload-settings"),this.$status=this.$(".upload-status"),this.$text=this.$(".upload-text"),this.$text_content=this.$(".upload-text-content"),this.$info_text=this.$(".upload-info-text"),this.$info_progress=this.$(".upload-info-progress"),this.$file_name=this.$(".upload-file-name"),this.$file_desc=this.$(".upload-file-desc"),this.$file_size=this.$(".upload-file-size"),this.$progress_bar=this.$(".upload-progress-bar"),this.$percentage=this.$(".upload-percentage"),this.uploadinput=this.$el.uploadinput({ondragover:function(){i.model.get("enabled")&&i.$el.addClass("warning")},ondragleave:function(){i.$el.removeClass("warning")},onchange:function(e){"running"!=i.model.get("status")&&e&&e.length>0&&(i.model.reset({file_data:e[0],file_name:e[0].name,file_size:e[0].size,file_mode:e[0].mode||"local"}),i._refreshReady())}}),this.button_menu=new m.default.ButtonMenu({icon:"fa-caret-down",title:"Select",pull:"left"}),this.$source.append(this.button_menu.$el),this.button_menu.addMenu({icon:"fa-laptop",title:"Choose local file",onclick:function(){i.uploadinput.dialog()}}),this.app.ftp_upload_site&&this.button_menu.addMenu({icon:"fa-folder-open-o",title:"Choose FTP file",onclick:function(){i._showFtp()}}),this.button_menu.addMenu({icon:"fa-edit",title:"Paste/Fetch data",onclick:function(){i.model.reset({file_mode:"new",file_name:"New File"})}}),this.ftp=new f.default.View({title:"Choose FTP file:",container:this.$source.find(".ui-button-menu"),placement:"right"}),this.settings=new f.default.View({title:"Upload configuration",container:this.$settings,placement:"bottom"}),this.$text_content.on("change input",function(e){i.model.set({url_paste:n(e.target).val(),file_size:n(e.target).val().length}),i._refreshReady()}),this.$settings.on("click",function(e){i._showSettings()}).on("mousedown",function(e){e.preventDefault()}),this.listenTo(this.model,"change:percentage",function(){i._refreshPercentage()}),this.listenTo(this.model,"change:status",function(){i._refreshStatus()}),this.listenTo(this.model,"change:info",function(){i._refreshInfo()}),this.listenTo(this.model,"change:file_name",function(){i._refreshFileName()}),this.listenTo(this.model,"change:file_mode",function(){i._refreshMode()}),this.listenTo(this.model,"change:file_size",function(){i._refreshFileSize()}),this.listenTo(this.model,"remove",function(){i.remove()}),this.app.collection.on("reset",function(){i.remove()})},render:function(){this.$el.attr("id","upload-row-"+this.model.id),this.$file_name.html(s.escape(this.model.get("file_name")||"-")),this.$file_desc.html(this.model.get("file_desc")||"Unavailable"),this.$file_size.html(l.default.bytesToString(this.model.get("file_size"))),this.$status.removeClass().addClass(this.status_classes.init)},remove:function(){e.View.prototype.remove.apply(this)},_refreshReady:function(){this.app.collection.each(function(e){e.set("status",e.get("file_size")>0&&"ready"||"init")})},_refreshMode:function(){"new"==this.model.get("file_mode")?(this.height=this.$el.height(),this.$text.css({width:this.$el.width()-16+"px",top:this.$el.height()-8+"px"}).show(),this.$el.height(this.$el.height()-8+this.$text.height()+16),this.$text_content.val("").trigger("keyup")):(this.$el.height(this.height),this.$text.hide())},_refreshInfo:function(){var e=this.model.get("info");e?this.$info_text.html("Failed: "+e).show():this.$info_text.hide()},_refreshPercentage:function(){var e=parseInt(this.model.get("percentage"));0!=e?this.$progress_bar.css({width:e+"%"}):(this.$progress_bar.addClass("no-transition"),this.$progress_bar.css({width:"0%"}),this.$progress_bar[0].offsetHeight,this.$progress_bar.removeClass("no-transition")),this.$percentage.html(100!=e?e+"%":"Adding to history...")},_refreshStatus:function(){var e=this.model.get("status");this.$status.removeClass().addClass(this.status_classes[e]),this.model.set("enabled","running"!=e),this.$text_content.attr("disabled",!this.model.get("enabled")),this.$el.removeClass("success danger warning"),"running"!=e&&"ready"!=e||this.model.set("percentage",0),this.$source.find(".button")["running"==e?"addClass":"removeClass"]("disabled"),"success"==e&&(this.$el.addClass("success"),this.model.set("percentage",100),this.$percentage.html("100%")),"error"==e?(this.$el.addClass("danger"),this.model.set("percentage",0),this.$info_progress.hide(),this.$info_text.show()):(this.$info_progress.show(),this.$info_text.hide())},_refreshFileName:function(){this.$file_name.html(this.model.get("file_name")||"-")},_refreshFileSize:function(){this.$file_size.html(l.default.bytesToString(this.model.get("file_size")))},_showFtp:function(){if(this.ftp.visible)this.ftp.hide();else{var e=this;this.ftp.empty(),this.ftp.append(new u.default({ftp_upload_site:this.app.ftp_upload_site,onchange:function(t){e.ftp.hide(),"running"!=e.model.get("status")&&t&&(e.model.reset({file_mode:"ftp",file_name:t.path,file_size:t.size,file_path:t.path}),e._refreshReady())}}).$el),this.ftp.show()}},_showSettings:function(){this.settings.visible?this.settings.hide():(this.settings.empty(),this.settings.append(new d.default(this).$el),this.settings.show())},_template:function(){return'
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(16)),r=a(l),d=i(147),c=a(d),u=i(32),h=a(u),f=i(33),p=a(f),m=i(10),g=a(m),_=i(13),v=a(_),w=i(6),y=a(w),b=i(35);a(b);i(34),t.default=e.View.extend({upload_size:0,collection:new r.default.Collection,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(e){var t=this;this.app=e,this.options=e.options,this.list_extensions=e.list_extensions,this.list_genomes=e.list_genomes,this.ui_button=e.ui_button,this.ftp_upload_site=e.currentFtp(),this.setElement(this._template()),this.btnLocal=new y.default.Button({id:"btn-local",title:"Choose local files",onclick:function(){t.uploadbox.select()},icon:"fa fa-laptop"}),this.btnFtp=new y.default.Button({id:"btn-ftp",title:"Choose FTP files",onclick:function(){t._eventFtp()},icon:"fa fa-folder-open-o"}),this.btnCreate=new y.default.Button({id:"btn-new",title:"Paste/Fetch data",onclick:function(){t._eventCreate()},icon:"fa fa-edit"}),this.btnStart=new y.default.Button({id:"btn-start",title:"Start",onclick:function(){t._eventStart()}}),this.btnBuild=new y.default.Button({id:"btn-build",title:"Build",onclick:function(){t._eventBuild()}}),this.btnStop=new y.default.Button({id:"btn-stop",title:"Pause",onclick:function(){t._eventStop()}}),this.btnReset=new y.default.Button({id:"btn-reset",title:"Reset",onclick:function(){t._eventReset()}}),this.btnClose=new y.default.Button({id:"btn-close",title:"Close",onclick:function(){t.app.modal.hide()}}),n.each([this.btnLocal,this.btnFtp,this.btnCreate,this.btnStop,this.btnReset,this.btnStart,this.btnBuild,this.btnClose],function(e){t.$(".upload-buttons").prepend(e.$el)}),this.uploadbox=this.$(".upload-box").uploadbox({url:this.app.options.nginx_upload_path,announce:function(e,i){t._eventAnnounce(e,i)},initialize:function(e){return t.app.toData([t.collection.get(e)],t.history_id)},progress:function(e,i){t._eventProgress(e,i)},success:function(e,i){t._eventSuccess(e,i)},error:function(e,i){t._eventError(e,i)},complete:function(){t._eventComplete()},ondragover:function(){t.$(".upload-box").addClass("highlight")},ondragleave:function(){t.$(".upload-box").removeClass("highlight")}}),this.ftp=new g.default.View({title:"FTP files",container:this.btnFtp.$el}),this.select_extension=new v.default.View({css:"upload-footer-selection-compressed",container:this.$(".upload-footer-extension"),data:n.filter(this.list_extensions,function(e){return!e.composite_files}),value:this.options.default_extension,onchange:function(e){t.updateExtension(e)}}),this.collectionType="list",this.select_collection=new v.default.View({css:"upload-footer-selection-compressed",container:this.$(".upload-footer-collection-type"),data:[{id:"list",text:"List"},{id:"paired",text:"Paired"},{id:"list:paired",text:"List of Pairs"}],value:"list",onchange:function(e){t.updateCollectionType(e)}}),this.$(".upload-footer-extension-info").on("click",function(e){new p.default({$el:s(e.target),title:t.select_extension.text(),extension:t.select_extension.value(),list:t.list_extensions,placement:"top"})}).on("mousedown",function(e){e.preventDefault()}),this.select_genome=new v.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-genome"),data:this.list_genomes,value:this.options.default_genome,onchange:function(e){t.updateGenome(e)}}),this.collection.on("remove",function(e){t._eventRemove(e)}),this._updateScreen()},_eventAnnounce:function(e,t){this.counter.announce++;var i=new r.default.Model({id:e,file_name:t.name,file_size:t.size,file_mode:t.mode||"local",file_path:t.path,file_data:t,extension:this.select_extension.value(),genome:this.select_genome.value()});this.collection.add(i);var n=new c.default(this,{model:i});this.$(".upload-table > tbody:first").append(n.$el),this._updateScreen(),n.render()},_eventProgress:function(e,t){var i=this.collection.get(e);i.set("percentage",t),this.ui_button.model.set("percentage",this._uploadPercentage(t,i.get("file_size")))},_eventSuccess:function(e,t){var i=n.pluck(t.outputs,"hid"),s=this.collection.get(e);s.set({percentage:100,status:"success",hids:i}),this.ui_button.model.set("percentage",this._uploadPercentage(100,s.get("file_size"))),this.upload_completed+=100*s.get("file_size"),this.counter.announce--,this.counter.success++,this._updateScreen(),Galaxy.currHistoryPanel.refreshContents()},_eventError:function(e,t){var i=this.collection.get(e);i.set({percentage:100,status:"error",info:t}),this.ui_button.model.set({percentage:this._uploadPercentage(100,i.get("file_size")),status:"danger"}),this.upload_completed+=100*i.get("file_size"),this.counter.announce--,this.counter.error++,this._updateScreen()},_eventComplete:function(){this.collection.each(function(e){"queued"==e.get("status")&&e.set("status","init")}),this.counter.running=0,this._updateScreen()},_eventBuild:function(){var e=[];n.forEach(this.collection.models,function(t){e.push.apply(e,t.get("hids"))});var t=n.map(e,function(e){return Galaxy.currHistoryPanel.collection.getByHid(e)}),i=new Galaxy.currHistoryPanel.collection.constructor(t);i.historyId=Galaxy.currHistoryPanel.collection.historyId,Galaxy.currHistoryPanel.buildCollection(this.collectionType,i,!0),this.counter.running=0,this._updateScreen(),this._eventReset(),this.app.modal.hide()},_eventRemove:function(e){var t=e.get("status");"success"==t?this.counter.success--:"error"==t?this.counter.error--:this.counter.announce--,this.uploadbox.remove(e.id),this._updateScreen()},_eventFtp:function(){if(this.ftp.visible)this.ftp.hide();else{this.ftp.empty();var e=this;this.ftp.append(new h.default({collection:this.collection,ftp_upload_site:this.ftp_upload_site,onadd:function(t){return e.uploadbox.add([{mode:"ftp",name:t.path,size:t.size,path:t.path}])},onremove:function(t){e.collection.remove(t)}}).$el),this.ftp.show()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(!(0==this.counter.announce||this.counter.running>0)){var e=this;this.upload_size=0,this.upload_completed=0,this.collection.each(function(t){"init"==t.get("status")&&(t.set("status","queued"),e.upload_size+=t.get("file_size"))}),this.ui_button.model.set({percentage:0,status:"success"}),this.counter.running=this.counter.announce,this.history_id=this.app.currentHistory(),this.uploadbox.start(),this._updateScreen()}},_eventStop:function(){this.counter.running>0&&(this.ui_button.model.set("status","info"),s(".upload-top-info").html("Queue will pause after completing the current file..."),this.uploadbox.stop())},_eventReset:function(){0==this.counter.running&&(this.collection.reset(),this.counter.reset(),this.uploadbox.reset(),this.select_extension.value(this.options.default_extension),this.select_genome.value(this.options.default_genome),this.ui_button.model.set("percentage",0),this._updateScreen())},updateExtension:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("extension")!=i.options.default_extension&&t||n.set("extension",e)})},updateCollectionType:function(e){this.collectionType=e},updateGenome:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("genome")!=i.options.default_genome&&t||n.set("genome",e)})},_updateScreen:function(){var e="";e=0==this.counter.announce?this.uploadbox.compatible()?" ":"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.":0==this.counter.running?"You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed.":"Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining.",this.$(".upload-top-info").html(e);var t=0==this.counter.running&&this.counter.announce+this.counter.success+this.counter.error>0,i=0==this.counter.running&&this.counter.announce>0,n=0==this.counter.running&&0==this.counter.announce&&this.counter.success>0&&0==this.counter.error,s=0==this.counter.running,a=this.counter.announce+this.counter.success+this.counter.error>0;this.btnReset[t?"enable":"disable"](),this.btnStart[i?"enable":"disable"](),this.btnStart.$el[i?"addClass":"removeClass"]("btn-primary"),this.btnBuild[n?"enable":"disable"](),this.btnBuild.$el[n?"addClass":"removeClass"]("btn-primary"),this.btnStop[this.counter.running>0?"enable":"disable"](),this.btnLocal[s?"enable":"disable"](),this.btnFtp[s?"enable":"disable"](),this.btnCreate[s?"enable":"disable"](),this.btnFtp.$el[this.ftp_upload_site?"show":"hide"](),this.$(".upload-table")[a?"show":"hide"](),this.$(".upload-helper")[a?"hide":"show"]()},_uploadPercentage:function(e,t){return(this.upload_completed+e*t)/this.upload_size},_template:function(){return'
Drop files here
Name
Size
Status
'}})}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(16),d=(a(r),i(31)),c=a(d),u=i(10),h=a(u),f=i(13);a(f);t.default=e.View.extend({status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},initialize:function(e,t){var i=this;this.app=e,this.model=t.model,this.setElement(this._template(t.model)),this.$mode=this.$(".upload-mode"),this.$title=this.$(".upload-title-extended"),this.$text=this.$(".upload-text"),this.$size=this.$(".upload-size"),this.$info_text=this.$(".upload-info-text"),this.$info_progress=this.$(".upload-info-progress"),this.$text_content=this.$(".upload-text-content"),this.$symbol=this.$(".upload-symbol"),this.$progress_bar=this.$(".upload-progress-bar"),this.$percentage=this.$(".upload-percentage"),this.settings=new h.default.View({title:"Upload configuration",container:this.$(".upload-settings"),placement:"bottom"});this.app.select_genome.value(),this.app.select_extension.value();this.$symbol.on("click",function(){i._removeRow()}),this.$text_content.on("change input",function(e){i.model.set({url_paste:n(e.target).val(),file_size:n(e.target).val().length})}),this.listenTo(this.model,"change:percentage",function(){i._refreshPercentage()}),this.listenTo(this.model,"change:status",function(){i._refreshStatus()}),this.listenTo(this.model,"change:info",function(){i._refreshInfo()}),this.listenTo(this.model,"change:file_size",function(){i._refreshFileSize()}),this.listenTo(this.model,"remove",function(){i.remove()}),this.app.collection.on("reset",function(){i.remove()})},render:function(){var e=this.model.attributes;this.$title.html(s.escape(e.file_name)),this.$size.html(l.default.bytesToString(e.file_size)),this.$mode.removeClass().addClass("upload-mode").addClass("text-primary"),"new"==e.file_mode?(this.$text.css({width:this.$el.width()-16+"px",top:this.$el.height()-8+"px"}).show(),this.$el.height(this.$el.height()-8+this.$text.height()+16),this.$mode.addClass("fa fa-edit")):"local"==e.file_mode?this.$mode.addClass("fa fa-laptop"):"ftp"==e.file_mode&&this.$mode.addClass("fa fa-folder-open-o")},_refreshInfo:function(){var e=this.model.get("info");e?this.$info_text.html("Failed: "+e).show():this.$info_text.hide()},_refreshPercentage:function(){var e=parseInt(this.model.get("percentage"));this.$progress_bar.css({width:e+"%"}),this.$percentage.html(100!=e?e+"%":"Adding to history...")},_refreshStatus:function(){var e=this.model.get("status");this.$symbol.removeClass().addClass("upload-symbol").addClass(this.status_classes[e]),this.model.set("enabled","init"==e);var t=this.model.get("enabled");this.$text_content.attr("disabled",!t),"success"==e&&(this.$el.addClass("success"),this.$percentage.html("100%")),"error"==e&&(this.$el.addClass("danger"),this.$info_progress.hide())},_refreshFileSize:function(){this.$size.html(l.default.bytesToString(this.model.get("file_size")))},_removeRow:function(){-1!==["init","success","error"].indexOf(this.model.get("status"))&&this.app.collection.remove(this.model)},_showSettings:function(){this.settings.visible?this.settings.hide():(this.settings.empty(),this.settings.append(new c.default(this).$el),this.settings.show())},_template:function(e){return'
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={tool:"fa-wrench",data_input:"fa-file-o",data_collection_input:"fa-folder-o",subworkflow:"fa-sitemap fa-rotate-270",pause:"fa-pause"}},function(e,t,i){"use strict";(function(e){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var s=i(6),a=n(s),o=i(150),l=n(o),r=i(151),d=n(r),c=i(4),u=n(c),h=e.View.extend({initialize:function(t,i){var n=this;this.userIsAnonymous=Galaxy.user.isAnonymous(),this.allow_user_dataset_purge=i.config.allow_user_dataset_purge,this.root=i.root,this.historyView=new d.default.CurrentHistoryView({className:d.default.CurrentHistoryView.prototype.className+" middle",purgeAllowed:this.allow_user_dataset_purge,linkTarget:"galaxy_main"}),Galaxy.currHistoryPanel=this.historyView,Galaxy.currHistoryPanel.listenToGalaxy(Galaxy),this.buttonRefresh=new a.default.ButtonLink({id:"history-refresh-button",title:"Refresh history",cls:"panel-header-button",icon:"fa fa-refresh",onclick:function(){n.historyView.loadCurrentHistory()}}),this.buttonOptions=new a.default.ButtonLink({id:"history-options-button",title:"History options",cls:"panel-header-button",target:"galaxy_main",icon:"fa fa-cog",href:this.root+"root/history_options"}),this.buttonViewMulti=new a.default.ButtonLink({id:"history-view-multi-button",title:"View all histories",cls:"panel-header-button",icon:"fa fa-columns",href:this.root+"history/view_multiple"}),this.model=new e.Model({cls:"history-right-panel",title:(0,u.default)("History"),buttons:[this.buttonRefresh,this.buttonOptions,this.buttonViewMulti]}),this.setElement(this._template()),this.historyView.setElement(this.$el),this.historyView.connectToQuotaMeter(Galaxy.quotaMeter),this.historyView.loadCurrentHistory(),Galaxy.listenTo(this.historyView,"history-size-change",function(){Galaxy.user.fetch({url:Galaxy.user.urlRoot()+"/"+(Galaxy.user.id||"current")})})},render:function(){this.optionsMenu=(0,l.default)(this.buttonOptions.$el,{anonymous:this.userIsAnonymous,purgeAllowed:this.allow_user_dataset_purge,root:this.root}),this.buttonViewMulti.$el[this.userIsAnonymous?"hide":"show"]()},_template:function(e){return[''].join("")},toString:function(){return"historyPanel"}});t.default=h}).call(t,i(2))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}function a(e,t,i){return n.clone(m).filter(function(n){return!(e&&!n.anon)&&(!(!t&&n.purge)&&(n.href&&(n.href=i+n.href,n.target=n.target||"galaxy_main"),n.confirm&&(n.func=function(){confirm(n.confirm)&&(galaxy_main.location=n.href)}),!0))})}Object.defineProperty(t,"__esModule",{value:!0});var o=i(27),l=s(o),r=i(78),d=s(r),c=i(5),u=(s(c),i(4)),h=s(u),f=i(17),p=s(f),m=[{html:(0,h.default)("History Lists"),header:!0},{html:(0,h.default)("Saved Histories"),href:"histories/list",target:"_top"},{html:(0,h.default)("Histories Shared with Me"),href:"histories/list_shared",target:"_top"},{html:(0,h.default)("Current History"),header:!0,anon:!0},{html:(0,h.default)("Create New"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.createNewHistory()}},{html:(0,h.default)("Copy History"),func:function(){(0,d.default)(Galaxy.currHistoryPanel.model).done(function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Share or Publish"),href:"history/sharing"},{html:(0,h.default)("Show Structure"),href:"history/display_structured",anon:!0},{html:(0,h.default)("Extract Workflow"),href:"workflow/build_from_current_history"},{html:(0,h.default)("Delete"),anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really delete the current history?"))&&Galaxy.currHistoryPanel.model._delete().done(function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Delete Permanently"),purge:!0,anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really delete the current history permanently? This cannot be undone."))&&Galaxy.currHistoryPanel.model.purge().done(function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Dataset Actions"),header:!0,anon:!0},{html:(0,h.default)("Copy Datasets"),href:"dataset/copy_datasets"},{html:(0,h.default)("Dataset Security"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.router&&Galaxy.router.push("/histories/permissions?id="+Galaxy.currHistoryPanel.model.id)}},{html:(0,h.default)("Resume Paused Jobs"),href:"history/resume_paused_jobs?current=True",anon:!0},{html:(0,h.default)("Collapse Expanded Datasets"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.collapseAll()}},{html:(0,h.default)("Unhide Hidden Datasets"),anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really unhide all hidden datasets?"))&&e.post(Galaxy.root+"history/adjust_hidden",{user_action:"unhide"},function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Delete Hidden Datasets"),anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really delete all hidden datasets?"))&&e.post(Galaxy.root+"history/adjust_hidden",{user_action:"delete"},function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Purge Deleted Datasets"),confirm:(0,h.default)("Really delete all deleted datasets permanently? This cannot be undone."),href:"history/purge_deleted_datasets",purge:!0,anon:!0},{html:(0,h.default)("Downloads"),header:!0},{html:(0,h.default)("Export Tool Citations"),href:"history/citations",anon:!0},{html:(0,h.default)("Export History to File"),href:"history/export_archive?preview=True",anon:!0},{html:(0,h.default)("Other Actions"),header:!0},{html:(0,h.default)("Import from File"),href:"history/import_archive"}];p.default.add({url:"api/webhooks/history-menu/all",async:!1,callback:function(t){var i=[];e.each(t.models,function(e,t){var n=t.toJSON();n.activate&&i.push({html:(0,h.default)(n.config.title),anon:!0})}),i.length>0&&(i.unshift({html:(0,h.default)("Webhooks"),header:!0}),e.merge(m,i))}});var g=function(e,t){t=t||{};var i=void 0===t.anonymous||t.anonymous,n=t.purgeAllowed||!1,s=a(i,n,Galaxy.root);return new l.default(e,s)};t.default=g}).call(t,i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(38),l=(a(o),i(153)),r=a(l),d=i(5),c=a(d),u=i(4),h=a(u),f=c.default.SessionStorageModel.extend({defaults:{tagsEditorShown:!1,annotationEditorShown:!1,scrollPosition:0},toString:function(){return"HistoryViewPrefs("+JSON.stringify(this.toJSON())+")"}});f.storageKey=function(){return"history-panel"};var p=r.default.HistoryViewEdit,m=p.extend({className:p.prototype.className+" current-history-panel",HDCAViewClass:p.prototype.HDCAViewClass.extend({foldoutStyle:"drilldown"}),emptyMsg:[(0,h.default)("This history is empty"),". ",(0,h.default)("You can "),'',(0,h.default)("load your own data"),"",(0,h.default)(" or "),'',(0,h.default)("get data from an external source"),""].join(""),initialize:function(t){t=t||{},this.preferences=new f(e.extend({id:f.storageKey()},e.pick(t,e.keys(f.prototype.defaults)))),p.prototype.initialize.call(this,t),this.panelStack=[],this.currentContentId=t.currentContentId||null},_setUpListeners:function(){p.prototype._setUpListeners.call(this);var e=this;this.on("new-model",function(){e.preferences.set("scrollPosition",0)})},loadCurrentHistory:function(){return this.loadHistory(null,{url:Galaxy.root+"history/current_history_json"})},switchToHistory:function(e,t){return Galaxy.user.isAnonymous()?(this.trigger("error",(0,h.default)("You must be logged in to switch histories"),(0,h.default)("Anonymous user")),n.when()):this.loadHistory(e,{url:Galaxy.root+"history/set_as_current?id="+e})},createNewHistory:function(e){return Galaxy.user.isAnonymous()?(this.trigger("error",(0,h.default)("You must be logged in to create histories"),(0,h.default)("Anonymous user")),n.when()):this.loadHistory(null,{url:Galaxy.root+"history/create_new_current"})},setModel:function(e,t,i){return p.prototype.setModel.call(this,e,t,i),this.model&&this.model.id&&(this.log("checking for updates"),this.model.checkForUpdates()),this},_setUpModelListeners:function(){return p.prototype._setUpModelListeners.call(this),this.listenTo(this.model,{"change:nice_size change:size":function(){this.trigger("history-size-change",this,this.model,arguments)},"change:id":function(){this.once("loading-done",function(){this.model.checkForUpdates()})}})},_setUpCollectionListeners:function(){p.prototype._setUpCollectionListeners.call(this),this.listenTo(this.collection,"state:ready",function(e,t,i){e.get("visible")||this.collection.storage.includeHidden()||this.removeItemView(e)})},_setUpBehaviors:function(t){t=t||this.$el;var i=this;return p.prototype._setUpBehaviors.call(i,t),this._debouncedScrollCaptureHandler||(this._debouncedScrollCaptureHandler=e.debounce(function(){i.$el.is(":visible")&&i.preferences.set("scrollPosition",n(this).scrollTop())},40)),i.$scrollContainer(t).off("scroll",this._debouncedScrollCaptureHandler).on("scroll",this._debouncedScrollCaptureHandler),i},_buildNewRender:function(){if(!this.model)return n();var e=p.prototype._buildNewRender.call(this);return e.find(".search").prependTo(e.find("> .controls")),this._renderQuotaMessage(e),e},_renderQuotaMessage:function(e){return e=e||this.$el,n(this.templates.quotaMsg({},this)).prependTo(e.find(".messages"))},_renderTags:function(e){var t=this;p.prototype._renderTags.call(t,e),t.preferences.get("tagsEditorShown")&&t.tagsEditor.toggle(!0),t.listenTo(t.tagsEditor,"hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(e){t.preferences.set("tagsEditorShown",e.hidden)})},_renderAnnotation:function(e){var t=this;p.prototype._renderAnnotation.call(t,e),t.preferences.get("annotationEditorShown")&&t.annotationEditor.toggle(!0),t.listenTo(t.annotationEditor,"hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(e){t.preferences.set("annotationEditorShown",e.hidden)})},_swapNewRender:function(t){p.prototype._swapNewRender.call(this,t);var i=this;return e.delay(function(){var e=i.preferences.get("scrollPosition");e&&i.scrollTo(e,0)},10),this},_attachItems:function(e){p.prototype._attachItems.call(this,e);var t=this;return t.currentContentId&&t._setCurrentContentById(t.currentContentId),this},addItemView:function(e,t,i){var n=p.prototype.addItemView.call(this,e,t,i);return n&&this.panelStack.length?this._collapseDrilldownPanel():n},_setUpItemViewListeners:function(e){var t=this;return p.prototype._setUpItemViewListeners.call(t,e),t.listenTo(e,{"expanded:drilldown":function(e,t){this._expandDrilldownPanel(t)},"collapsed:drilldown":function(e,t){this._collapseDrilldownPanel(t)}})},setCurrentContent:function(e){this.$(".history-content.current-content").removeClass("current-content"),e?(e.$el.addClass("current-content"),this.currentContentId=e.model.id):this.currentContentId=null},_setCurrentContentById:function(e){var t=this.viewFromModelId(e)||null;this.setCurrentContent(t)},_expandDrilldownPanel:function(e){this.panelStack.push(e),this.$controls().add(this.$list()).hide(),e.parentName=this.model.get("name"),e.delegateEvents().render().$el.appendTo(this.$el)},_collapseDrilldownPanel:function(e){this.panelStack.pop(),this.$controls().add(this.$list()).show()},events:e.extend(e.clone(p.prototype.events),{"click .uploader-link":function(e){Galaxy.upload.show(e)},"click .get-data-link":function(e){var t=n(".toolMenuContainer");t.parent().scrollTop(0),t.find('span:contains("Get Data")').click()}}),listenToGalaxy:function(t){this.listenTo(t,{"center-frame:load":function(t){var i=t.fullpath,n=null,s={display:/datasets\/([a-f0-9]+)\/display/,edit:/datasets\/([a-f0-9]+)\/edit/,report_error:/dataset\/errors\?id=([a-f0-9]+)/,rerun:/tool_runner\/rerun\?id=([a-f0-9]+)/,show_params:/datasets\/([a-f0-9]+)\/show_params/};e.find(s,function(t,s){return n=e.result(i.match(t),1)}),this._setCurrentContentById(n?"dataset-"+n:null)},"center-panel:load":function(e){this._setCurrentContentById()}})},connectToQuotaMeter:function(e){return e?(this.listenTo(e,"quota:over",this.showQuotaMessage),this.listenTo(e,"quota:under",this.hideQuotaMessage),this.on("rendered rendered:initial",function(){e&&e.isOverQuota()&&this.showQuotaMessage()}),this):this},clearMessages:function(t){var i=e.isUndefined(t)?this.$messages().children('[class$="message"]'):n(t.currentTarget);return i=i.not(".quota-message"),i.fadeOut(this.fxSpeed,function(){n(this).remove()}),this},showQuotaMessage:function(){var e=this.$(".quota-message");e.is(":hidden")&&e.slideDown(this.fxSpeed)},hideQuotaMessage:function(){var e=this.$(".quota-message");e.is(":hidden")||e.slideUp(this.fxSpeed)},unhideHidden:function(){var e=this;return confirm((0,h.default)("Really unhide all hidden datasets?"))?e.model.contents._filterAndUpdate({visible:!1,deleted:"",purged:""},{visible:!0}).done(function(){e.model.contents.includeHidden||e.renderItems()}):s.when()},deleteHidden:function(){var e=this;return confirm((0,h.default)("Really delete all hidden datasets?"))?e.model.contents._filterAndUpdate({visible:!1,deleted:"",purged:""},{deleted:!0,visible:!0}):s.when()},toString:function(){return"CurrentHistoryView("+(this.model?this.model.get("name"):"")+")"}});m.prototype.templates=function(){var t=c.default.wrapTemplate(['
',(0,h.default)("You are over your disk quota"),". ",(0,h.default)("Tool execution is on hold until your disk usage drops below your allocated quota"),".","
"],"history");return e.extend(e.clone(p.prototype.templates),{quotaMsg:t})}(),t.default={CurrentHistoryView:m}}).call(t,i(1),i(0),i(0))},function(e,t,i){"use strict";(function(e){function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function n(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var a=function e(t,i,n){null===t&&(t=Function.prototype);var s=Object.getOwnPropertyDescriptor(t,i);if(void 0===s){var a=Object.getPrototypeOf(t);return null===a?void 0:e(a,i,n)}if("value"in s)return s.value;var o=s.get;if(void 0!==o)return o.call(n)},o=function(){function e(e,t){for(var i=0;i .controls .deleted-count").html(""+(0,M.default)("loading...")+"")},"fetching-hidden":function(e){this.$("> .controls .hidden-count").html(""+(0,M.default)("loading...")+"")},"fetching-deleted-done fetching-hidden-done":this._renderCounts}),this},_buildNewRender:function(){var e=I.prototype._buildNewRender.call(this);return this.model?(Galaxy&&Galaxy.user&&Galaxy.user.id&&Galaxy.user.id===this.model.get("user_id")&&(this._renderTags(e),this._renderAnnotation(e)),e):e},updateHistoryDiskSize:function(){this.$(".history-size").text(this.model.get("nice_size"))},renderItems:function(e){var t=I.prototype.renderItems.call(this,e);return this.searchFor?this._renderSearchFindings(e):this._renderCounts(e),t},_renderCounts:function(t){t=t instanceof e?t:this.$el;var i=this.templates.counts(this.model.toJSON(),this);return t.find("> .controls .subtitle").html(i)},_renderTags:function(e){var t=this;this.tagsEditor=new _.default.TagsEditor({model:this.model,el:e.find(".controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.toggleHDATagEditors(!0,t.fxSpeed)},onhide:function(){t.toggleHDATagEditors(!1,t.fxSpeed)},$activator:(0,T.default)({title:(0,M.default)("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".controls .actions"))})},_renderAnnotation:function(e){var t=this;this.annotationEditor=new w.default.AnnotationEditor({model:this.model,el:e.find(".controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.toggleHDAAnnotationEditors(!0,t.fxSpeed)},onhide:function(){t.toggleHDAAnnotationEditors(!1,t.fxSpeed)},$activator:(0,T.default)({title:(0,M.default)("Edit history annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".controls .actions"))})},_setUpBehaviors:function(e){if(e=e||this.$el,I.prototype._setUpBehaviors.call(this,e),this.model&&Galaxy.user&&!Galaxy.user.isAnonymous()&&Galaxy.user.id===this.model.get("user_id")){var t=this;e.find("> .controls .name").attr("title",(0,M.default)("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(e){var i=t.model.get("name");e&&e!==i?(t.$el.find("> .controls .name").text(e),t.model.save({name:e}).fail(function(){t.$el.find("> .controls .name").text(t.model.previous("name"))})):t.$el.find("> .controls .name").text(i)}})}},multiselectActions:function(){var e=this,t=[{html:(0,M.default)("Hide datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.hide;e.getSelectedModels().ajaxQueue(t)}},{html:(0,M.default)("Unhide datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.unhide;e.getSelectedModels().ajaxQueue(t)}},{html:(0,M.default)("Delete datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.delete;e.getSelectedModels().ajaxQueue(t)}},{html:(0,M.default)("Undelete datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.undelete;e.getSelectedModels().ajaxQueue(t)}}];return e.purgeAllowed&&t.push({html:(0,M.default)("Permanently delete datasets"),func:function(){if(confirm((0,M.default)("This will permanently remove the data in your datasets. Are you sure?"))){var t=u.default.HistoryDatasetAssociation.prototype.purge;e.getSelectedModels().ajaxQueue(t)}}}),t=t.concat(e._collectionActions())},_collectionActions:function(){var e=this;return[{html:(0,M.default)("Build Dataset List"),func:function(){e.buildCollection("list")}},{html:(0,M.default)("Build Dataset Pair"),func:function(){e.buildCollection("paired")}},{html:(0,M.default)("Build List of Dataset Pairs"),func:function(){e.buildCollection("list:paired")}}]},buildCollection:function(e,t,i){var n,s=this,t=t||s.getSelectedModels(),i=i||!1;"list"==e?n=b.default.createListCollection:"paired"==e?n=C.default.createPairCollection:"list:paired"==e?n=k.default.createListOfPairsCollection:console.warn("Unknown collectionType encountered "+e),n(t,i).done(function(){s.model.refresh()})},_getItemViewOptions:function(e){var t=I.prototype._getItemViewOptions.call(this,e);return n.extend(t,{purgeAllowed:this.purgeAllowed,tagsEditorShown:this.tagsEditor&&!this.tagsEditor.hidden,annotationEditorShown:this.annotationEditor&&!this.annotationEditor.hidden}),t},_handleItemDeletedChange:function(e){e.get("deleted")?this._handleItemDeletion(e):this._handleItemUndeletion(e),this._renderCounts()},_handleItemDeletion:function(e){var t=this.model.get("contents_active");t.deleted+=1,t.active-=1,this.model.contents.includeDeleted||this.removeItemView(e),this.model.set("contents_active",t)},_handleItemUndeletion:function(e){var t=this.model.get("contents_active");t.deleted-=1,this.model.contents.includeDeleted||(t.active-=1),this.model.set("contents_active",t)},_handleItemVisibleChange:function(e){e.hidden()?this._handleItemHidden(e):this._handleItemUnhidden(e),this._renderCounts()},_handleItemHidden:function(e){var t=this.model.get("contents_active");t.hidden+=1,t.active-=1,this.model.contents.includeHidden||this.removeItemView(e),this.model.set("contents_active",t)},_handleItemUnhidden:function(e){var t=this.model.get("contents_active");t.hidden-=1,this.model.contents.includeHidden||(t.active-=1),this.model.set("contents_active",t)},toggleHDATagEditors:function(e,t){n.each(this.views,function(i){i.tagsEditor&&i.tagsEditor.toggle(e,t)})},toggleHDAAnnotationEditors:function(e,t){n.each(this.views,function(i){i.annotationEditor&&i.annotationEditor.toggle(e,t)})},events:n.extend(n.clone(I.prototype.events),{"click .show-selectors-btn":"toggleSelectors","click .toggle-deleted-link":function(e){this.toggleShowDeleted()},"click .toggle-hidden-link":function(e){this.toggleShowHidden()}}),_renderSearchProgress:function(e,t){var i=e+t;return this.$("> .controls .subtitle").html(["",(0,M.default)("Searching "),i,"/",this.model.contentsShown(),""].join(""))},_renderSearchFindings:function(t){t=t instanceof e?t:this.$el;var i=this.templates.found(this.model.toJSON(),this);return t.find("> .controls .subtitle").html(i),this},dropTargetOn:function(){if(this.dropTarget)return this;this.dropTarget=!0;var e={dragenter:n.bind(this.dragenter,this),dragover:n.bind(this.dragover,this),dragleave:n.bind(this.dragleave,this),drop:n.bind(this.drop,this)},t=this._renderDropTarget();this.$list().before([this._renderDropTargetHelp(),t]);for(var i in e)e.hasOwnProperty(i)&&t.on(i,e[i]);return this},_renderDropTarget:function(){return this.$(".history-drop-target").remove(),s("").addClass("history-drop-target")},_renderDropTargetHelp:function(){return this.$(".history-drop-target-help").remove(),s("").addClass("history-drop-target-help").text((0,M.default)("Drag datasets here to copy them to the current history"))},dropTargetOff:function(){if(!this.dropTarget)return this;this.dropTarget=!1;var e=this.$(".history-drop-target").get(0);for(var t in this._dropHandlers)this._dropHandlers.hasOwnProperty(t)&&e.off(t,this._dropHandlers[t]);return this.$(".history-drop-target").remove(),this.$(".history-drop-target-help").remove(),this},dropTargetToggle:function(){return this.dropTarget?this.dropTargetOff():this.dropTargetOn(),this},dragenter:function(e){e.preventDefault(),e.stopPropagation(),this.$(".history-drop-target").css("border","2px solid black")},dragover:function(e){e.preventDefault(),e.stopPropagation()},dragleave:function(e){e.preventDefault(),e.stopPropagation(),this.$(".history-drop-target").css("border","1px dashed black")},drop:function(e){e.preventDefault();var t=this,i=e.originalEvent.dataTransfer,n=i.getData("text");i.dropEffect="move";try{n=JSON.parse(n)}catch(e){t.warn("error parsing JSON from drop:",n)}return t.trigger("droptarget:drop",e,n,t),!1},dataDropped:function(t){var i=this;return n.isObject(t)&&"HistoryDatasetAssociation"===t.model_class&&t.id?0!==i.contents.currentPage?i.contents.fetchPage(0).then(function(){return i.model.contents.copy(t.id)}):i.model.contents.copy(t.id):e.when()},toString:function(){return"HistoryViewEdit("+(this.model?this.model.get("name"):"")+")"}});L.prototype.templates=function(){var e=P.default.wrapTemplate(["<% var shown = Math.max( view.views.length, history.contents_active.active ) %>","<% if( shown ){ %>",'',"<%- shown %> ",(0,M.default)("shown"),"","<% } %>","<% if( history.contents_active.deleted ){ %>",'',"<% if( view.model.contents.includeDeleted ){ %>",'',(0,M.default)("hide deleted"),"","<% } else { %>","<%- history.contents_active.deleted %> ",'',(0,M.default)("deleted"),"","<% } %>","","<% } %>","<% if( history.contents_active.hidden ){ %>",'',"<% if( view.model.contents.includeHidden ){ %>",'',(0,M.default)("hide hidden"),"","<% } else { %>","<%- history.contents_active.hidden %> ",'',(0,M.default)("hidden"),"","<% } %>","","<% } %>"],"history"),t=P.default.wrapTemplate([(0,M.default)("Found")," <%- view.views.length %>, ","<% if( history.contents_active.deleted ){ %>","<% if( view.model.contents.includeDeleted ){ %>",'',(0,M.default)("hide deleted"),", ","<% } else { %>",'',(0,M.default)("show deleted"),", ","<% } %>","<% } %>","<% if( history.contents_active.hidden ){ %>","<% if( view.model.contents.includeHidden ){ %>",'',(0,M.default)("hide hidden"),"","<% } else { %>",'',(0,M.default)("show hidden"),"","<% } %>","<% } %>"],"history");return n.extend(n.clone(I.prototype.templates),{counts:e,found:t})}(),t.default={HistoryViewEdit:L}}).call(t,i(0),i(1),i(0))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(82),o=s(a),l=i(38),r=s(l),d=i(39),c=s(d),u=i(40),h=(s(u),i(84)),f=s(h),p=i(85),m=s(p),g=i(59),_=(s(g),i(79)),v=s(_),w=i(14),y=s(w),b=i(5),x=s(b),C=i(4),$=s(C);i(83);var k=o.default.ModelListPanel,S=k.extend({_logNamespace:"history",HDAViewClass:f.default.HDAListItemView,HDCAViewClass:m.default.HDCAListItemView,collectionClass:c.default.HistoryContents,modelCollectionKey:"contents",tagName:"div",className:k.prototype.className+" history-panel",emptyMsg:(0,$.default)("This history is empty"),noneFoundMsg:(0,$.default)("No matching datasets found"),searchPlaceholder:(0,$.default)("search datasets"),FETCH_COLLECTION_COUNTS_DELAY:2e3,initialize:function(e){k.prototype.initialize.call(this,e),this.linkTarget=e.linkTarget||"_blank",this.detailedFetchTimeoutId=null},_createDefaultCollection:function(){return new this.collectionClass([],{history:this.model})},freeModel:function(){return k.prototype.freeModel.call(this),this.model&&this.model.clearUpdateTimeout(),this._clearDetailedFetchTimeout(),this},_clearDetailedFetchTimeout:function(){this.detailedFetchTimeoutId&&(clearTimeout(this.detailedFetchTimeoutId),this.detailedFetchTimeoutId=null)},_setUpListeners:function(){k.prototype._setUpListeners.call(this),this.on({error:function(e,t,i,n,s){this.errorHandler(e,t,i,n,s)},"loading-done":function(){var t=this;t.detailedFetchTimeoutId=e.delay(function(){t.detailedFetchTimeoutId=null,t.model.contents.fetchCollectionCounts()},t.FETCH_COLLECTION_COUNTS_DELAY)},"views:ready view:attached view:removed":function(e){this._renderSelectButton()},"view:attached":function(e){this.scrollTo(0)}})},loadHistory:function(t,i,n){n=e.extend(n||{silent:!0}),this.info("loadHistory:",t,i,n);var s=this;return s.setModel(new r.default.History({id:t})),n.silent=!0,s.trigger("loading"),s.model.fetchWithContents(i,n).always(function(){s.render(),s.trigger("loading-done")})},refreshContents:function(e){return this.model?this.model.refresh(e):n.when()},_setUpCollectionListeners:function(){return k.prototype._setUpCollectionListeners.call(this),this.listenTo(this.collection,{"fetching-more":function(){this._toggleContentsLoadingIndicator(!0),this.$emptyMessage().hide()},"fetching-more-done":function(){this._toggleContentsLoadingIndicator(!1)}})},_showLoadingIndicator:function(t,i,s){var a=n('');this.$el.html(a.text(t).slideDown(e.isUndefined(i)?this.fxSpeed:i))},_hideLoadingIndicator:function(t){this.$(".loading-indicator").slideUp(e.isUndefined(t)?this.fxSpeed+200:t,function(){n(this).remove()})},_buildNewRender:function(){var e=k.prototype._buildNewRender.call(this);return this._renderSelectButton(e),e},_renderSelectButton:function(e){if(e=e||this.$el,!this.multiselectActions().length)return null;if(!this.views.length)return this.hideSelectors(),e.find(".controls .actions .show-selectors-btn").remove(),null;var t=e.find(".controls .actions .show-selectors-btn");return t.length?t:(0,y.default)({title:(0,$.default)("Operations on multiple datasets"),classes:"show-selectors-btn",faIcon:"fa-check-square-o"}).prependTo(e.find(".controls .actions"))},_renderEmptyMessage:function(e){var t=this,i=t.$emptyMessage(e);return t.model.get("contents_active").active<=0?i.empty().append(t.emptyMsg).show():t.searchFor&&t.model.contents.haveSearchDetails()&&!t.views.length?i.empty().append(t.noneFoundMsg).show():(i.hide(),n())},$scrollContainer:function(e){return this.$list(e)},_toggleContentsLoadingIndicator:function(e){e?this.$list().html('
",(0,p.default)(["Pair collections are permanent collections containing two datasets: one forward and one reverse. ","Often these are forward and reverse reads. The pair collections can be passed to tools and ","workflows in order to have analyses done on both datasets. This interface allows ","you to create a pair, name it, and swap which is forward and which reverse."].join("")),"
","
","
",(0,p.default)(['Click the "Swap" link to make your forward dataset the reverse ',"and the reverse dataset forward."].join("")),"
","
",(0,p.default)(['Click the "Cancel" button to exit the interface.'].join("")),"
","
","
",(0,p.default)(['Once your collection is complete, enter a name and ','click "Create list".'].join("")),"
"].join("")),invalidInitial:n.template(['
','
','',"<% if( _.size( problems ) ){ %>",(0,p.default)("The following selections could not be included due to problems"),"
<% _.each( problems, function( problem ){ %>","
<%- problem.element.name %>: <%- problem.text %>
","<% }); %>
","<% } else if( _.size( elements ) === 0 ){ %>",(0,p.default)("No datasets were selected"),".","<% } else if( _.size( elements ) === 1 ){ %>",(0,p.default)("Only one dataset was selected"),": <%- elements[0].name %>","<% } else if( _.size( elements ) > 2 ){ %>",(0,p.default)("Too many datasets were selected"),': <%- _.pluck( elements, "name" ).join( ", ") %>',"<% } %>"," ",(0,p.default)("Two (and only two) elements are needed for the pair"),". ",(0,p.default)("You may need to "),'',(0,p.default)("cancel")," ",(0,p.default)("and reselect new elements"),".","","
","
",'"].join(""))}),toString:function(){return"PairCollectionCreator"}}),v=function(e,t){return t=t||{},t.title=(0,p.default)("Create a collection from a pair of datasets"),r.default.collectionCreatorModal(e,t,_)};t.default={PairCollectionCreator:_,pairCollectionCreatorModal:v,createPairCollection:o}}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s,a){function o(e){return e&&e.__esModule?e:{default:e}}function l(e){function t(){return i.length||(i=[new RegExp(this.filters[0]),new RegExp(this.filters[1])]),i}e=e||{},e.createPair=e.createPair||function(e){e=e||{};var t=e.listA.splice(e.indexA,1)[0],i=e.listB.splice(e.indexB,1)[0],n=e.listB.indexOf(t),s=e.listA.indexOf(i);return-1!==n&&e.listB.splice(n,1),-1!==s&&e.listA.splice(s,1),this._pair(t,i,{silent:!0})};var i=[];return e.preprocessMatch=e.preprocessMatch||function(e){var i=t.call(this);return n.extend(e,{matchTo:e.matchTo.name.replace(i[0],""),possible:e.possible.name.replace(i[1],"")})},function(t){this.debug("autopair _strategy ---------------------------"),t=t||{};var i,n=t.listA,s=t.listB,a=0,o={score:0,index:null},l=[];for(this.debug("starting list lens:",n.length,s.length),this.debug("bestMatch (starting):",JSON.stringify(o,null," "));a=c?l.push(e.createPair.call(this,{listA:n,indexA:a,listB:s,indexB:o.index})):a+=1,!n.length||!s.length)return l}return this.debug("paired:",JSON.stringify(l,null," ")),this.debug("autopair _strategy ---------------------------"),l}}function r(e,t){var i=e.toJSON();return b(i,{historyId:e.historyId,defaultHideSourceItems:t})}Object.defineProperty(t,"__esModule",{value:!0});var d=i(162),c=o(d),u=i(75),h=o(u),f=i(74),p=o(f),m=i(5),g=o(m),_=i(4),v=o(_);i(76);var w=e.View.extend(g.default.LoggableMixin).extend({_logNamespace:"collections",tagName:"li",className:"dataset paired",initialize:function(e){this.pair=e.pair||{}},template:n.template(['<%- pair.forward.name %>','','<%- pair.name %>',"",'<%- pair.reverse.name %>'].join("")),render:function(){this.dragStartHandler=n.bind(this._dragstart,this),this.dragEndHandler=n.bind(this._dragend,this);var e=this.$el.attr("draggable",!0).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container").get(0);return e.addEventListener("dragstart",this.dragStartHandler,!1),e.addEventListener("dragend",this.dragEndHandler,!1),this},events:{dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(e){e.currentTarget.style.opacity="0.4",e.originalEvent&&(e=e.originalEvent),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",JSON.stringify(this.pair)),this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(e){e.currentTarget.style.opacity="1.0",this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(e){this.$el.parent().trigger(e)},toString:function(){return"PairView("+this.pair.name+")"}}),y=e.View.extend(g.default.LoggableMixin).extend(p.default.CollectionCreatorMixin).extend({_logNamespace:"collections",className:"list-of-pairs-collection-creator collection-creator flex-row-container",initialize:function(e){this.metric("PairedCollectionCreator.initialize",e),e=n.defaults(e,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:!0,strategy:"lcs",matchPercentage:.9,twoPassAutopairing:!0}),this.initialList=e.datasets,this.historyId=e.historyId,this.filters=this.commonFilters[e.filters]||this.commonFilters[this.DEFAULT_FILTERS],n.isArray(e.filters)&&(this.filters=e.filters),this.automaticallyPair=e.automaticallyPair,this.strategy=this.strategies[e.strategy]||this.strategies[this.DEFAULT_STRATEGY],n.isFunction(e.strategy)&&(this.strategy=e.strategy),this.matchPercentage=e.matchPercentage,this.twoPassAutopairing=e.twoPassAutopairing,this.removeExtensions=!0,this.oncancel=e.oncancel,this.oncreate=e.oncreate,this.autoscrollDist=e.autoscrollDist||24,this.unpairedPanelHidden=!1,this.pairedPanelHidden=!1,this.$dragging=null,this.blocking=!1,this._setUpCommonSettings(e),this._setUpBehaviors(),this._dataSetUp()},commonFilters:{illumina:["_1","_2"],Rs:["_R1","_R2"]},DEFAULT_FILTERS:"illumina",strategies:{simple:"autopairSimple",lcs:"autopairLCS",levenshtein:"autopairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[],this.unpaired=[],this.selectedIds=[],this._sortInitialList(),this._ensureIds(),this.unpaired=this.initialList.slice(0),this.automaticallyPair&&(this.autoPair(),this.once("rendered:initial",function(){this.trigger("autopair")}))},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(e){return e.sort(function(e,t){return(0,h.default)(e.name,t.name)}),e},_ensureIds:function(){return this.initialList.forEach(function(e){e.hasOwnProperty("id")||(e.id=n.uniqueId())}),this.initialList},_splitByFilters:function(){function e(e,t){return t.test(e.name)}var t=this.filters.map(function(e){return new RegExp(e)}),i=[[],[]];return this.unpaired.forEach(function(n){t.forEach(function(t,s){e(n,t)&&i[s].push(n)})}),i},_addToUnpaired:function(e){var t=this;this.unpaired.splice(function i(n,s){if(n===s)return n;var a=Math.floor((s-n)/2)+n,o=(0,h.default)(e.name,t.unpaired[a].name);if(o<0)return i(n,a);if(o>0)return i(a+1,s);for(;t.unpaired[a]&&t.unpaired[a].name===e.name;)a++;return a}(0,this.unpaired.length),0,e)},autoPair:function(e){var t=this._splitByFilters(),i=[];return this.twoPassAutopairing&&(i=this.autopairSimple({listA:t[0],listB:t[1]}),t=this._splitByFilters()),e=e||this.strategy,t=this._splitByFilters(),i=i.concat(this[e].call(this,{listA:t[0],listB:t[1]}))},autopairSimple:l({scoreThreshold:function(){return.6},match:function(e){return e=e||{},e.matchTo===e.possible?{index:e.index,score:1}:e.bestMatch}}),autopairLevenshtein:l({scoreThreshold:function(){return this.matchPercentage},match:function(e){e=e||{};var t=(0,c.default)(e.matchTo,e.possible),i=1-t/Math.max(e.matchTo.length,e.possible.length);return i>e.bestMatch.score?{index:e.index,score:i}:e.bestMatch}}),autopairLCS:l({scoreThreshold:function(){return this.matchPercentage},match:function(e){e=e||{};var t=this._naiveStartingAndEndingLCS(e.matchTo,e.possible).length,i=t/Math.max(e.matchTo.length,e.possible.length);return i>e.bestMatch.score?{index:e.index,score:i}:e.bestMatch}}),_naiveStartingAndEndingLCS:function(e,t){for(var i="",n="",s=0,a=0;s=0&&a>=0&&e[s]===t[a];)n=[e[s],n].join(""),s-=1,a-=1;return i+n},_pair:function(e,t,i){i=i||{},this.debug("_pair:",e,t);var s=this._createPair(e,t,i.name);return this.paired.push(s),this.unpaired=n.without(this.unpaired,e,t),i.silent||this.trigger("pair:new",s),s},_createPair:function(e,t,i){if(!e||!t||e===t)throw new Error("Bad pairing: "+[JSON.stringify(e),JSON.stringify(t)]);return i=i||this._guessNameForPair(e,t),{forward:e,name:i,reverse:t}},_guessNameForPair:function(e,t,i){i=void 0!==i?i:this.removeExtensions;var n=e.name,s=t.name,a=this._naiveStartingAndEndingLCS(n.replace(new RegExp(this.filters[0]),""),s.replace(new RegExp(this.filters[1]),""));if(i){var o=a.lastIndexOf(".");if(o>0){var l=a.slice(o,a.length);a=a.replace(l,""),n=n.replace(l,""),s=s.replace(l,"")}}return a||n+" & "+s},_unpair:function(e,t){if(t=t||{},!e)throw new Error("Bad pair: "+JSON.stringify(e));return this.paired=n.without(this.paired,e),this._addToUnpaired(e.forward),this._addToUnpaired(e.reverse),t.silent||this.trigger("pair:unpair",[e]),e},unpairAll:function(){for(var e=[];this.paired.length;)e.push(this._unpair(this.paired[0],{silent:!0}));this.trigger("pair:unpair",e)},_pairToJSON:function(e,t){return t=t||"hda",{collection_type:"paired",src:"new_collection",name:e.name,element_identifiers:[{name:"forward",id:e.forward.id,src:t},{name:"reverse",id:e.reverse.id,src:t}]}},createList:function(e){var t=this,i=Galaxy.root+"api/histories/"+this.historyId+"/contents/dataset_collections",a={type:"dataset_collection",collection_type:"list:paired",hide_source_items:t.hideOriginals||!1,name:n.escape(e||t.$(".collection-name").val()),element_identifiers:t.paired.map(function(e){return t._pairToJSON(e)})};return t.blocking=!0,s.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(a)}).always(function(){t.blocking=!1}).fail(function(e,i,n){t._ajaxErrHandler(e,i,n)}).done(function(e,i,n){t.trigger("collection:created",e,i,n),t.metric("collection:created",e),"function"==typeof t.oncreate&&t.oncreate.call(this,e,i,n)})},_ajaxErrHandler:function(e,t,i){this.error(e,t,i);var n=this,s=(0,v.default)("An error occurred while creating this collection");e&&(0===e.readyState&&0===e.status?s+=": "+(0,v.default)("Galaxy could not be reached and may be updating.")+(0,v.default)(" Try again in a few minutes."):e.responseJSON?s+="
",(0,v.default)(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"
","
",(0,v.default)(['Unpaired datasets are shown in the unpaired section ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the paired section.',"
To pair datasets, you can:","
Click a dataset in the ",'forward column ',"to select it then click a dataset in the ",'reverse column.',"
",'
Click one of the "Pair these datasets" buttons in the ','middle column ',"to pair the datasets in a particular row.","
",'
Click "Auto-pair" ',"to have your datasets automatically paired based on name.","
","
"].join("")),"","
",(0,v.default)(["
You can filter what is shown in the unpaired sections by:","
Entering partial dataset names in either the ",'forward filter or ','reverse filter.',"
","
Choosing from a list of preset filters by clicking the ",'"Choose filters" link.',"
Clearing the filters by clicking the ",'"Clear filters" link.',"
","
"].join("")),"","
",(0,v.default)(["To unpair individual dataset pairs, click the ",'unpair buttons ( ). ','Click the "Unpair all" link to unpair all pairs.'].join("")),"
","
",(0,v.default)(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','"Remove file extensions from pair names?" control.'].join("")),"
","
",(0,v.default)(['Once your collection is complete, enter a name and ','click "Create list". ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"
"].join(""))})}),b=function(e,t){var i,a=s.Deferred();if(t=n.defaults(t||{},{datasets:e,oncancel:function(){Galaxy.modal.hide(),a.reject("cancelled")},oncreate:function(e,t){Galaxy.modal.hide(),a.resolve(t)}}),!window.Galaxy||!Galaxy.modal)throw new Error("Galaxy or Galaxy.modal not found");return i=new y(t),Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:!0}),i.render(),window.creator=i,a};t.default={PairedCollectionCreator:y,pairedCollectionCreatorModal:b,createListOfPairsCollection:r}}).call(t,i(2),i(1),i(0),i(0))},function(e,t,i){"use strict";function n(e,t){if(0===e.length)return t.length;if(0===t.length)return e.length;var i,n=[];for(i=0;i<=t.length;i++)n[i]=[i];var s;for(s=0;s<=e.length;s++)n[0][s]=s;for(i=1;i<=t.length;i++)for(s=1;s<=e.length;s++)t.charAt(i-1)===e.charAt(s-1)?n[i][s]=n[i-1][s-1]:n[i][s]=Math.min(n[i-1][s-1]+1,Math.min(n[i][s-1]+1,n[i-1][s]+1));return n[t.length][e.length]}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(9),l=(a(o),i(6)),r=a(l),d=i(8),c=a(d),u=e.Model.extend({initialize:function(e){e=e||{},e.user_id=e.user_id||Galaxy.user.id,this.set({user_id:e.user_id,information:{title:"Manage information",description:"Edit your email, addresses and custom parameters or change your username.",url:"api/users/"+e.user_id+"/information/inputs",icon:"fa-user",redirect:"user"},password:{title:"Change password",description:"Allows you to change your login credentials.",icon:"fa-unlock-alt",url:"api/users/"+e.user_id+"/password/inputs",submit_title:"Save password",redirect:"user"},communication:{title:"Change communication settings",description:"Enable or disable the communication feature to chat with other users.",url:"api/users/"+e.user_id+"/communication/inputs",icon:"fa-comments-o",redirect:"user"},permissions:{title:"Set dataset permissions for new histories",description:"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.",url:"api/users/"+e.user_id+"/permissions/inputs",icon:"fa-users",submit_title:"Save permissions",redirect:"user"},api_key:{title:"Manage API key",description:"Access your current API key or create a new one.",url:"api/users/"+e.user_id+"/api_key/inputs",icon:"fa-key",submit_title:"Create a new key",submit_icon:"fa-check"},toolbox_filters:{title:"Manage Toolbox filters",description:"Customize your Toolbox by displaying or omitting sets of Tools.",url:"api/users/"+e.user_id+"/toolbox_filters/inputs",icon:"fa-filter",submit_title:"Save filters",redirect:"user"},openids:{title:"Manage OpenIDs",description:"Associate OpenIDs with your account.",icon:"fa-openid",onclick:function(){window.location.href=Galaxy.root+"user/openid_manage?cntrller=user&use_panels=True"}},custom_builds:{title:"Manage custom builds",description:"Add or remove custom builds using history datasets.",icon:"fa-cubes",onclick:function(){window.location.href=Galaxy.root+"custom_builds"}},logout:{title:"Sign out",description:"Click here to sign out of all sessions.",icon:"fa-sign-out",onclick:function(){Galaxy.modal.show({title:"Sign out",body:"Do you want to continue and sign out of all active sessions?",buttons:{Cancel:function(){Galaxy.modal.hide()},"Sign out":function(){window.location.href=Galaxy.root+"user/logout?session_csrf_token="+Galaxy.session_csrf_token}}})}}})}}),h=e.View.extend({title:"User Preferences",initialize:function(){this.model=new u,this.setElement(""),this.render()},render:function(){var e=this,t=Galaxy.config;n.getJSON(Galaxy.root+"api/users/"+Galaxy.user.id,function(i){e.$preferences=n("").addClass("ui-panel").append(n("").append("User preferences")).append(n("").append("You are logged in as "+s.escape(i.email)+".")).append(e.$table=n("
You are using '+e.nice_total_disk_usage+" of disk space in this Galaxy instance. "+(Galaxy.config.enable_quotas?"Your disk quota is: "+e.quota+". ":"")+'Is your usage more than expected? See the documentation for tips on how to find all of the data in your account.
'}});t.default={View:h,Model:u}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=(s(a),i(6)),l=s(o),r=i(9),d=s(r),c=i(68),u=s(c),h=e.Collection.extend({comparator:function(e,t){return e=e.get("name"),t=t.get("name"),e>t?1:e").append(n("").text("Current Custom Builds")).append(this.table.$el).append(this.$installed=n("").append(n("").text("System Installed Builds").addClass("ui-margin-top")).append(this.installed_builds.$el)).append(n("").text("Add a Custom Build").addClass("ui-margin-top")).append(n("").addClass("ui-column").append(n("").addClass("ui-column-left").append(this.message.$el).append(this.$form=n("").addClass("ui-margin-top"))).append(this.$help=n("").addClass("ui-column-right")))),this.listenTo(this.collection,"add remove reset",function(){i._renderTable()}),this.listenTo(this.model,"change",function(){i._renderForm()}),this.collection.fetch(),this.model.fetch()},render:function(){this._renderTable(),this._renderForm()},_renderTable:function(){var e=this;this.table.delAll(),this.collection.sort(),this.collection.each(function(t){e.table.add(t.get("name")),e.table.add(t.id),e.table.add(void 0!==t.get("count")?t.get("count"):"Processing..."),e.table.add(new l.default.ButtonIcon({icon:"fa-trash-o",cls:"ui-button-icon-plain",tooltip:"Delete custom build.",onclick:function(){t.destroy()}}).$el),e.table.append(t.id)})},_renderForm:function(){var e=this,t=new d.default({inputs:[{type:"text",name:"name",label:"Name",help:"Specify a build name e.g. Hamster."},{type:"text",name:"id",label:"Key",help:"Specify a build key e.g. hamster_v1."},{name:"len",type:"conditional",test_param:{name:"type",label:"Definition",help:"Provide the data source.",type:"select",value:"fasta",data:[{value:"fasta",label:"FASTA-file from history"},{value:"file",label:"Len-file from disk"},{value:"text",label:"Len-file by copy/paste"}]},cases:[{value:"fasta",inputs:[{type:"select",name:"value",label:"FASTA-file",data:this.model.get("fasta_hdas")}]},{value:"file",inputs:[{type:"upload",name:"value",label:"Len-file",data:this.model.get("len_hdas")}]},{value:"text",inputs:[{type:"text",area:!0,name:"value",label:"Edit/Paste"}]}]}],buttons:{save:new l.default.Button({icon:"fa-save",tooltip:"Create new Build",title:"Save",cls:"btn btn-primary ui-clear-float",onclick:function(){var i=t.data.create();i.id&&i.name?e.collection.create(i,{wait:!0,success:function(t){t.get("message")?e.message.update({message:t.get("message"),status:"warning"}):e.message.update({message:"Successfully added a new custom build.",status:"success"})},error:function(t,i){var n=i&&i.responseJSON&&i.responseJSON.err_msg;e.message.update({message:n||"Failed to create custom build.",status:"danger"})}}):e.message.update({message:"All inputs are required.",status:"danger"})}})},onchange:function(){var i=t.data.match("len|type");if(i){var n=t.field_list[i];e._renderHelp(n.value())}}});this.$form.empty().append(t.$el);var i=this.model.get("installed_builds");i&&i.length?(this.$installed.show(),this.installed_builds.update(this.model.get("installed_builds"))):this.$installed.hide(),this._renderHelp("fasta")},_renderHelp:function(e){this.$help.empty().addClass("alert alert-info").html("fasta"==e?this._templateFasta():this._templateLen())},_templateLen:function(){return"
Length Format
The length format is two-column, separated by whitespace, of the form:
chrom/contig length of chrom/contig
For example, the first few entries of mm9.len are as follows:
Trackster uses this information to populate the select box for chrom/contig, andto set the maximum basepair of the track browser. You may either upload a .len fileof this format (Len File option), or directly enter the information into the box (Len Entry option).
"},_templateFasta:function(){return"
FASTA format
This is a multi-fasta file from your current history that provides the genomesequences for each chromosome/contig in your build.
Here is a snippet from an example multi-fasta file:
")}),t.append(a)}else t.append("No "+this.model.get("plural").toLowerCase()+" have been shared with you.");return t}});t.default={View:l}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(54),l=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t.default=e,t}(o),r=i(22),d=a(r),c=i(167),u=a(c),h=i(8),f=a(h),p=e.View.extend({tagName:"tr",initialize:function(){n.bindAll(this,"render","_rowTemplate","renderTagEditor","_templateActions","removeWorkflow","copyWorkflow"),l.options.timeOut=1500},events:{"click #show-in-tool-panel":"showInToolPanel","click #delete-workflow":"removeWorkflow","click #rename-workflow":"renameWorkflow","click #copy-workflow":"copyWorkflow"},render:function(){return s(this.el).html(this._rowTemplate()),this},showInToolPanel:function(){this.model.set("show_in_tool_panel",!this.model.get("show_in_tool_panel")),this.model.save(),window.location=Galaxy.root+"workflow"},removeWorkflow:function(){var e=this.model.get("name");window.confirm("Are you sure you want to delete workflow '"+e+"'?")&&(this.model.destroy({success:function(){l.success("Successfully deleted workflow '"+e+"'")}}),this.remove())},renameWorkflow:function(){var e=this.model.get("name"),t=window.prompt("Enter a new Name for workflow '"+e+"'",e);t&&(this.model.save({name:t},{success:function(){l.success("Successfully renamed workflow '"+e+"' to '"+t+"'")}}),this.render())},copyWorkflow:function(){var e=this,t=this.model.get("name");s.getJSON(this.model.urlRoot+"/"+this.model.id+"/download",function(i){var n="Copy of "+t,s=e.model.get("owner");s!=Galaxy.user.attributes.username&&(n+=" shared by user "+s),i.name=n,e.collection.create(i,{at:0,wait:!0,success:function(){l.success("Successfully copied workflow '"+t+"' to '"+n+"'")},error:function(e,t,i){l.error(i.errorThrown)}})}).error(function(e,t,i){l.error(e.responseJSON.err_msg)})},_rowTemplate:function(){var e=this.model.get("show_in_tool_panel"),t=this.model.id,i='';return'
'}}),m=e.View.extend({title:"Workflows",initialize:function(){this.setElement(""),n.bindAll(this,"adjustActiondropdown"),this.collection=new u.default.WorkflowCollection,this.collection.fetch().done(this.render()),this.collection.bind("add",this.appendItem),this.collection.on("sync",this.render,this)},events:{dragleave:"unhighlightDropZone",drop:"drop",dragover:function(e){s(".hidden_description_layer").addClass("dragover"),s(".menubutton").addClass("background-none"),e.preventDefault()}},unhighlightDropZone:function(){s(".hidden_description_layer").removeClass("dragover"),s(".menubutton").removeClass("background-none")},drop:function(e){this.unhighlightDropZone(),e.preventDefault();for(var t,i=e.dataTransfer.files,n=this,s=0;t=i[s];s++)n.readWorkflowFiles(t)},readWorkflowFiles:function(e){var t=this,i=new FileReader;i.onload=function(n){var s;try{s=JSON.parse(i.result)}catch(t){l.error("Could not read file '"+e.name+"'. Verify it is a valid Galaxy workflow"),s=null}s&&t.collection.create(s,{at:0,wait:!0,success:function(){l.success("Successfully imported workflow '"+s.name+"'")},error:function(e,t,i){l.error(i.errorThrown)}})},i.readAsText(e,"utf-8")},_showArgErrors:n.once(function(){var e=f.default.get("message");"error"===f.default.get("status")?l.error(n.escape(e||"Unknown Error, please report this to an administrator.")):e&&l.info(n.escape(e))}),render:function(){var e=this._templateHeader(),t=this._templateActionButtons(),i=this._templateWorkflowTable();this.$el.html(e+t+i);var s=this;n(this.collection.models).each(function(e){s.appendItem(e),s.confirmDelete(e)},this);return this.searchWorkflow(this.$(".search-wf"),this.$(".workflow-search tr"),3),this.adjustActiondropdown(),this._showArgErrors(),this},appendItem:function(e){var t=new p({model:e,collection:this.collection});s(".workflow-search").append(t.render().el),t.renderTagEditor()},confirmDelete:function(e){this.$(".link-confirm-shared-"+e.id).click(function(){return window.confirm("Are you sure you want to remove the shared workflow '"+e.attributes.name+"'?")})},searchWorkflow:function(e,t,i){e.on("keyup",function(){var e=s(this).val();if(e.length>=i){var n=new RegExp(e,"i");t.hide(),t.filter(function(){return n.test(s(this).text())}).show()}else t.show()})},adjustActiondropdown:function(){s(this.el).on("show.bs.dropdown",function(){s(this.el).css("overflow","inherit")}),s(this.el).on("hide.bs.dropdown",function(){s(this.el).css("overflow","auto")})},_templateNoWorkflow:function(){return'
Click the link above to visit myExperiment and browse for Galaxy workflows.
"}});t.default={View:m,ImportWorkflowView:g}}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e){Object.defineProperty(t,"__esModule",{value:!0});var n=i(5),s=function(e){return e&&e.__esModule?e:{default:e}}(n),a=e.Model.extend(s.default.LoggableMixin).extend({_logNamespace:"workflow",urlRoot:Galaxy.root+"api/workflows",toJSON:function(){return{workflow:this.attributes}}}),o=e.Collection.extend({model:a,url:Galaxy.root+"api/workflows"});t.default={WorkflowItem:a,WorkflowCollection:o}}).call(t,i(2))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(12),d=a(r),c=i(38),u=a(c),h=i(78),f=a(h),p=e.View.extend({title:"Histories",initialize:function(t){var i=this;this.setElement(n("")),this.model=new e.Model,l.default.get({url:Galaxy.root+"history/"+t.action_id+"?"+n.param(Galaxy.params),success:function(e){e.dict_format=!0,s.each(e.operations,function(e){"Copy"==e.label&&(e.onclick=function(e){i._showCopyDialog(e)})}),i.model.set(e),i.render()}})},render:function(){var e=new d.default(this.model.attributes);this.$el.empty().append(e.$el)},_showCopyDialog:function(e){var t=new u.default.History({id:e});t.fetch().fail(function(){alert("History could not be fetched. Please contact an administrator")}).done(function(){(0,f.default)(t,{}).done(function(){window.parent&&window.parent.Galaxy&&window.parent.Galaxy.currHistoryPanel&&window.parent.Galaxy.currHistoryPanel.loadCurrentHistory(),window.location.reload(!0)})})}});t.default={View:p}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=s(a),l=i(6),r=s(l),d=i(9),c=s(d),u=e.View.extend({initialize:function(){this.setElement(""),this.model=new e.Model({dataset_id:Galaxy.params.dataset_id}),this.render()},render:function(){var e=Galaxy.root+"api/datasets/"+this.model.get("dataset_id"),t=this;o.default.get({url:e,success:function(e){var i=Galaxy.root+"api/jobs/"+e.creating_job+"?full=True";o.default.get({url:i,success:function(i){Galaxy.root,e.creating_job;t.render_error_page(t,e,i)},error:function(e){var i={status:"error",message:"Error occured while loading the job.",persistent:!0,cls:"errormessage"};t.display_message(i,t.$(".response-message"))}})},error:function(e){var i={status:"error",message:"Error occured while loading the dataset.",persistent:!0,cls:"errormessage"};t.display_message(i,t.$(".response-message"))}})},render_error_page:function(e,t,i){e.$el.empty().append(e._templateHeader()),e.$el.append("
Dataset Error
"),e.$el.append("
An error occured while running the tool "+i.tool_id+".
"),e.$el.append("
Tool execution generated the following messages:
"),e.$el.append('
'+i.stderr+"
"),e.$el.append("
Report This Error"),e.$el.append("
Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.
'},_getBugFormTemplate:function(e,t){var i=this,n=[{help:"Your email address",options:[],type:"text",name:"email",label:"Your email",value:Galaxy.user.get("email")},{help:"Any additional comments you can provide regarding what you were doing at the time of the bug.",options:[],type:"text",area:!0,name:"message",label:"Message"}],s=new c.default({title:"Error Report",inputs:n,buttons:{save:new r.default.Button({icon:"fa-bug",title:"Report",cls:"ui-button btn btn-primary",floating:"clear",onclick:function(){var n=s.data.create(),a=Galaxy.root+"api/jobs/"+t.id+"/error";n.dataset_id=e.id,i.submit(n,a)}})}});return s.$el},submit:function(e,t){var i=this;n.ajax({type:"POST",url:t,data:e,success:function(e){i.$el.empty().append(i._templateHeader()),e.messages.forEach(function(e){i.display_message({status:e[1],message:e[0],persistent:!0},i.$(".response-message"),!0,!0)})},error:function(e){var t={status:"error",message:"Error occured while saving. Please fill all the required fields and try again.",persistent:!0,cls:"errormessage"};i.display_message(t,i.$(".response-message"))}})}});t.default={View:u}}).call(t,i(2),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(28)),r=a(l),d=i(6),c=a(d),u=i(9),h=a(u),f=e.View.extend({initialize:function(){this.setElement(""),this.model=new e.Model({dataset_id:Galaxy.params.dataset_id}),this.message=new c.default.Message({persistent:!0}),this.tabs=this._createTabs(),this.$el.append(n("").append("Edit dataset attributes")).append(this.message.$el).append("").append(this.tabs.$el).hide(),this.render()},render:function(){var e=this;n.ajax({url:Galaxy.root+"dataset/get_edit?dataset_id="+e.model.get("dataset_id"),success:function(t){!e.initial_message&&e.message.update(t),e.initial_message=!0,s.each(e.forms,function(e,i){e.model.set("inputs",t[i+"_inputs"]),e.model.set("hide_operations",t[i+"_disable"]),e.render()}),e.$el.show()},error:function(t){var i=t.responseJSON&&t.responseJSON.err_msg;e.message.update({status:"danger",message:i||"Error occured while loading the dataset."})}})},_submit:function(e,t){var i=this,s=t.data.create();s.dataset_id=this.model.get("dataset_id"),s.operation=e,n.ajax({type:"PUT",url:Galaxy.root+"dataset/set_edit",data:s,success:function(e){i.message.update(e),i.render(),i._reloadHistory()},error:function(e){var t=e.responseJSON&&e.responseJSON.err_msg;i.message.update({status:"danger",message:t||"Error occured while editing the dataset attributes."})}})},_createTabs:function(){this.forms={attribute:this._getAttribute(),conversion:this._getConversion(),datatype:this._getDatatype(),permission:this._getPermission()};var e=new r.default.View;return e.add({id:"attribute",title:"Attributes",icon:"fa fa-bars",tooltip:"Edit dataset attributes",$el:this.forms.attribute.$el}),e.add({id:"convert",title:"Convert",icon:"fa-gear",tooltip:"Convert to new format",$el:this.forms.conversion.$el}),e.add({id:"datatype",title:"Datatypes",icon:"fa-database",tooltip:"Change data type",$el:this.forms.datatype.$el}),e.add({id:"permissions",title:"Permissions",icon:"fa-user",tooltip:"Permissions",$el:this.forms.permission.$el}),e},_getAttribute:function(){var e=this,t=new h.default({title:"Edit attributes",operations:{submit_attributes:new c.default.ButtonIcon({tooltip:"Save attributes of the dataset.",icon:"fa-floppy-o",title:"Save",onclick:function(){e._submit("attributes",t)}}),submit_autodetect:new c.default.ButtonIcon({tooltip:"This will inspect the dataset and attempt to correct the values of fields if they are not accurate.",icon:"fa-undo",title:"Auto-detect",onclick:function(){e._submit("autodetect",t)}})}});return t},_getConversion:function(){var e=this,t=new h.default({title:"Convert to new format",operations:{submit_conversion:new c.default.ButtonIcon({tooltip:"Convert the datatype to a new format.",title:"Convert datatype",icon:"fa-exchange",onclick:function(){e._submit("conversion",t)}})}});return t},_getDatatype:function(){var e=this,t=new h.default({title:"Change datatype",operations:{submit_datatype:new c.default.ButtonIcon({tooltip:"Change the datatype to a new type.",title:"Change datatype",icon:"fa-exchange",onclick:function(){e._submit("datatype",t)}})}});return t},_getPermission:function(){var e=this,t=new h.default({title:"Manage dataset permissions",operations:{submit_permission:new c.default.ButtonIcon({tooltip:"Save permissions.",title:"Save permissions",icon:"fa-floppy-o ",onclick:function(){e._submit("permission",t)}})}});return t},_reloadHistory:function(){window.Galaxy&&window.Galaxy.currHistoryPanel.loadCurrentHistory()}});t.default={View:f}}).call(t,i(2),i(0),i(1))}],[137]);
+this.get("accessible")||this.set("state",l.default.NOT_VIEWABLE),this.urls=this._generateUrls(),this._setUpListeners()},_generateUrls:function(){var e=this.get("id");if(!e)return{};var t={purge:"datasets/"+e+"/purge_async",display:"datasets/"+e+"/display/?preview=True",edit:"datasets/edit?dataset_id="+e,download:"datasets/"+e+"/display"+this._downloadQueryParameters(),report_error:"dataset/errors?id="+e,rerun:"tool_runner/rerun?id="+e,show_params:"datasets/"+e+"/show_params",visualization:"visualization",meta_download:"dataset/get_metadata_file?hda_id="+e+"&metadata_name="};return n.each(t,function(e,i){t[i]=Galaxy.root+e}),this.urls=t,t},_downloadQueryParameters:function(){return"?to_ext="+this.get("file_ext")},_setUpListeners:function(){this.on("change:state",function(e,t){this.log(this+" has changed state:",e,t),this.inReadyState()&&this.trigger("state:ready",e,t,this.previous("state"))}),this.on("change:id change:file_ext",function(e){this._generateUrls()})},toJSON:function(){var t=e.Model.prototype.toJSON.call(this);return n.extend(t,{urls:this.urls})},isDeletedOrPurged:function(){return this.get("deleted")||this.get("purged")},inReadyState:function(){var e=n.contains(l.default.READY_STATES,this.get("state"));return this.isDeletedOrPurged()||e},hasDetails:function(){return!this.get("accessible")||this.has("annotation")},hasData:function(){return this.get("file_size")>0},fetch:function(t){var i=this;return e.Model.prototype.fetch.call(this,t).always(function(){i._generateUrls()})},parse:function(t,i){var n=e.Model.prototype.parse.call(this,t,i);return n.create_time&&(n.create_time=new Date(n.create_time)),n.update_time&&(n.update_time=new Date(n.update_time)),n},save:function(t,i){return i=i||{},i.wait=!!n.isUndefined(i.wait)||i.wait,e.Model.prototype.save.call(this,t,i)},delete:function(e){return this.get("deleted")?s.when():this.save({deleted:!0},e)},undelete:function(e){return!this.get("deleted")||this.get("purged")?s.when():this.save({deleted:!1},e)},purge:function(e){if(this.get("purged"))return s.when();e=e||{},e.url=this.urls.purge;var t=this,i=s.ajax(e);return i.done(function(e,i,n){t.set({deleted:!0,purged:!0})}),i.fail(function(i,n,s){var a=(0,u.default)("Unable to purge dataset");i.responseJSON&&i.responseJSON.error?a=i.responseJSON.error:-1!==i.responseText.indexOf("Removal of datasets by users is not allowed in this Galaxy instance")&&(a="Removal of datasets by users is not allowed in this Galaxy instance"),i.responseText=a,t.trigger("error",t,i,e,(0,u.default)(a),{error:a})}),i},searchAttributes:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],searchAliases:{title:"name",format:"file_ext",database:"genome_build",blurb:"misc_blurb",description:"misc_blurb",info:"misc_info",tag:"tags"},toString:function(){var e=this.get("id")||"";return this.get("name")&&(e='"'+this.get("name")+'",'+e),"Dataset("+e+")"}})),p=e.Collection.extend(d.default.LoggableMixin).extend({_logNamespace:"dataset",model:f,urlRoot:Galaxy.root+"api/datasets",url:function(){return this.urlRoot},ids:function(){return this.map(function(e){return e.get("id")})},notReady:function(){return this.filter(function(e){return!e.inReadyState()})},haveDetails:function(){return this.all(function(e){return e.hasDetails()})},ajaxQueue:function(e,t){var i=s.Deferred(),n=this.length,a=[];if(!n)return i.resolve([]),i;var o=this.chain().reverse().map(function(s,l){return function(){var r=e.call(s,t);r.done(function(e){i.notify({curr:l,total:n,response:e,model:s})}),r.always(function(e){a.push(e),o.length?o.shift()():i.resolve(a)})}}).value();return o.shift()(),i},matches:function(e){return this.filter(function(t){return t.matches(e)})},toString:function(){return["DatasetAssociationCollection(",this.length,")"].join("")}});t.default={DatasetAssociation:f,DatasetAssociationCollection:p}}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var s=i(11),a=(n(s),i(5)),o=(n(a),i(4)),l=(n(o),{defaults:{history_id:null,history_content_type:null,hid:null,visible:!0},idAttribute:"type_id",hidden:function(){return!this.get("visible")},isVisible:function(e,t){var i=!0;return e||!this.get("deleted")&&!this.get("purged")||(i=!1),t||this.get("visible")||(i=!1),i},urlRoot:Galaxy.root+"api/histories/",url:function(){var e=this.get("history_content_type"),t=(this.get("history_id"),this.get("id"));return this.urlRoot+'{this.get("historyId")}/contents/'+e+"s/"+t},hide:function(t){return this.get("visible")?this.save({visible:!1},t):e.when()},unhide:function(t){return this.get("visible")?e.when():this.save({visible:!0},t)},toString:function(){return[this.get("type_id"),this.get("hid"),this.get("name")].join(":")}});t.default={HistoryContentMixin:l}}).call(t,i(0))},function(e,t,i){"use strict";(function(e){Object.defineProperty(t,"__esModule",{value:!0});var i={_validationWarning:function(e,t){"name"===e&&(e=this.$(".collection-name").add(this.$(".collection-name-prompt")),this.$(".collection-name").focus().select()),t?(e=e||this.$(".validation-warning"),e.removeClass("validation-warning")):e.addClass("validation-warning")},_changeHideOriginals:function(e){this.hideOriginals=this.$(".hide-originals").prop("checked")},_changeName:function(e){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(e){13!==e.keyCode||this.blocking||this._clickCreate()},_getName:function(){return e.escape(this.$(".collection-name").val())},_clickMoreHelp:function(e){e.stopPropagation(),this.$(".main-help").addClass("expanded"),this.$(".more-help").hide()},_clickLessHelp:function(e){e.stopPropagation(),this.$(".main-help").removeClass("expanded"),this.$(".more-help").show()},_toggleHelp:function(e){e.stopPropagation(),this.$(".main-help").toggleClass("expanded"),this.$(".more-help").toggle()},_showAlert:function(e,t){t=t||"alert-danger",this.$(".main-help").hide(),this.$(".header .alert").attr("class","alert alert-dismissable").addClass(t).show().find(".alert-message").html(e)},_hideAlert:function(e){this.$(".main-help").show(),this.$(".header .alert").hide()},_cancelCreate:function(e){"function"==typeof this.oncancel&&this.oncancel.call(this)},_clickCreate:function(e){var t=this._getName();t?this.blocking||this.createList(t):this._validationWarning("name")},_setUpCommonSettings:function(e){this.hideOriginals=e.defaultHideSourceItems||!1},_renderFooter:function(t,i){var n=this,s=this.$(".footer").empty().html(this.templates.footer());return e.each(this.footerSettings,function(e,t){n.$(t).prop("checked",n[e])}),"function"==typeof this.oncancel&&this.$(".cancel-create.btn").show(),s},_creatorTemplates:{main:e.template(['','',''].join(""))}};t.default={CollectionCreatorMixin:i}}).call(t,i(1))},function(e,t,i){"use strict";function n(e,t){var i=/(-?[0-9\.]+)/g,n=e.toString().toLowerCase()||"",s=t.toString().toLowerCase()||"",a=String.fromCharCode(0),o=n.replace(i,a+"$1"+a).split(a),l=s.replace(i,a+"$1"+a).split(a),r=new Date(n).getTime(),d=r?new Date(s).getTime():null;if(d){if(rd)return 1}for(var c,u,h=0,f=Math.max(o.length,l.length);hu)return 1}return 0}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,i){"use strict";var n=i(0),s=function(e){return e&&e.__esModule?e:{default:e}}(n),a=s.default;s.default.fn.extend({hoverhighlight:function(e,t){return e=e||"body",this.length?(a(this).each(function(){var i=a(this),n=i.data("target");n&&i.mouseover(function(i){a(n,e).css({background:t})}).mouseout(function(e){a(n).css({background:""})})}),this):this}})},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(67),d=a(r),c=i(6),u=a(c),h=i(9),f=a(h),p=i(70),m=a(p),g=i(66),_=a(g),v=i(7),w=a(v),y=i(17),b=a(y),x=i(149),C=a(x),$=e.View.extend({initialize:function(t){var i=this;this.modal=parent.Galaxy.modal||new w.default.View,this.model=t&&t.model||new e.Model(t),this.deferred=new d.default,this.setElement(n("").addClass("ui-form-composite").append(this.$message=n("")).append(this.$header=n("")).append(this.$steps=n(""))),n("body").append(this.$el),this._configure(),this.render(),n(window).resize(function(){i._refresh()})},_refresh:function(e){var t=s.reduce(this.$el.children(),function(e,t){return e+n(t).outerHeight()},0)-this.$steps.height()+90;this.$steps.css("height",n(window).height()-t)},_configure:function(){function e(e,n){for(var s,a=/\$\{(.+?)\}/g;s=a.exec(String(e));){var o=s[1];n(t.wp_inputs[o]=t.wp_inputs[o]||{label:o,name:o,type:"text",color:"hsl( "+100*++i+", 70%, 30% )",style:"ui-form-wp-source",links:[]})}}var t=this;this.forms=[],this.steps=[],this.links=[],this.parms=[],s.each(this.model.get("steps"),function(e,i){Galaxy.emit.debug("tool-form-composite::initialize()",i+" : Preparing workflow step.");var n=C.default[e.step_type],a=parseInt(i+1)+": "+(e.step_label||e.step_name);e.annotation&&(a+=" - "+e.annotation),e.step_version&&(a+=" (Galaxy Version "+e.step_version+")"),e=l.default.merge({index:i,fixed_title:s.escape(a),icon:n||"",help:null,citations:null,collapsible:!0,collapsed:i>0&&!t._isDataStep(e),sustain_version:!0,sustain_repeats:!0,sustain_conditionals:!0,narrow:!0,text_enable:"Edit",text_disable:"Undo",cls_enable:"fa fa-edit",cls_disable:"fa fa-undo",errors:e.messages,initial_errors:!0,cls:"ui-portlet-narrow",hide_operations:!0,needs_refresh:!1,always_refresh:"tool"!=e.step_type},e),t.steps[i]=e,t.links[i]=[],t.parms[i]={}}),s.each(this.steps,function(e,i){m.default.visitInputs(e.inputs,function(e,n){t.parms[i][n]=e})}),s.each(this.steps,function(e,i){s.each(e.output_connections,function(e){s.each(t.steps,function(n,s){n.step_index===e.input_step_index&&t.links[i].push(n)})})}),s.each(this.steps,function(e,i){s.each(t.steps,function(n,a){var o={};s.each(e.output_connections,function(e){n.step_index===e.input_step_index&&(o[e.input_name]=e)}),s.each(t.parms[a],function(t,n){var s=o[n];s&&(t.type="hidden",t.help=t.step_linked?t.help+", ":"",t.help+="Output dataset '"+s.output_name+"' from step "+(parseInt(i)+1),t.step_linked=t.step_linked||[],t.step_linked.push(e))})})});var i=0;this.wp_inputs={},s.each(this.steps,function(i,n){s.each(t.parms[n],function(t,n){e(t.value,function(e){e.links.push(i),t.wp_linked=!0,t.type="text",t.backdrop=!0,t.style="ui-form-wp-target"})}),s.each(i.post_job_actions,function(t){s.each(t.action_arguments,function(t){e(t,function(){})})})}),s.each(this.steps,function(e,i){if("tool"==e.step_type){var n=!0;m.default.visitInputs(e.inputs,function(i,s,a){var o=i.value&&"RuntimeValue"==i.value.__class__,r=-1!=["data","data_collection"].indexOf(i.type),d=a[i.data_ref];i.step_linked&&!t._isDataStep(i.step_linked)&&(n=!1),i.options&&(0==i.options.length&&!n||i.wp_linked)&&(i.is_workflow=!0),d&&(i.is_workflow=d.step_linked&&!t._isDataStep(d.step_linked)||i.wp_linked),(r||i.value&&"RuntimeValue"==i.value.__class__&&!i.step_linked)&&(e.collapsed=!1),o&&(i.value=i.default_value),i.flavor="workflow",o||r||"hidden"===i.type||i.wp_linked||(i.optional||!l.default.isEmpty(i.value)&&""!==i.value)&&(i.collapsible_value=i.value,i.collapsible_preview=!0)})}})},render:function(){var e=this;this.deferred.reset(),this._renderHeader(),this._renderMessage(),this._renderParameters(),this._renderHistory(),s.each(this.steps,function(t){e._renderStep(t)})},_renderHeader:function(){var e=this;this.execute_btn=new u.default.Button({icon:"fa-check",title:"Run workflow",cls:"btn btn-primary",onclick:function(){e._execute()}}),this.$header.addClass("ui-form-header").empty().append(new u.default.Label({title:"Workflow: "+this.model.get("name")}).$el).append(this.execute_btn.$el)},_renderMessage:function(){this.$message.empty(),this.model.get("has_upgrade_messages")&&this.$message.append(new u.default.Message({message:"Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.",status:"warning",persistent:!0,fade:!1}).$el);var e=this.model.get("step_version_changes");e&&e.length>0&&this.$message.append(new u.default.Message({message:"Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.",status:"warning",persistent:!0,fade:!1}).$el)},_renderParameters:function(){var e=this;this.wp_form=null,s.isEmpty(this.wp_inputs)||(this.wp_form=new f.default({title:"Workflow Parameters",inputs:this.wp_inputs,cls:"ui-portlet-narrow",onchange:function(){s.each(e.wp_form.input_list,function(t,i){s.each(t.links,function(t){e._refreshStep(t)})})}}),this._append(this.$steps.empty(),this.wp_form.$el))},_renderHistory:function(){this.history_form=new f.default({cls:"ui-portlet-narrow",title:"History Options",inputs:[{type:"conditional",name:"new_history",test_param:{name:"check",label:"Send results to a new history",type:"boolean",value:"false",help:""},cases:[{value:"true",inputs:[{name:"name",label:"History name",type:"text",value:this.model.get("name")}]}]}]}),this._append(this.$steps,this.history_form.$el)},_renderStep:function(e){var t=this,i=null;this.deferred.execute(function(a){if(t.$steps.addClass("ui-steps"),"tool"==e.step_type)e.postchange=function(t,i){var s={tool_id:e.id,tool_version:e.version,inputs:n.extend(!0,{},i.data.create())};i.wait(!0),Galaxy.emit.debug("tool-form-composite::postchange()","Sending current state.",s),l.default.request({type:"POST",url:Galaxy.root+"api/tools/"+e.id+"/build",data:s,success:function(e){i.update(e),i.wait(!1),Galaxy.emit.debug("tool-form-composite::postchange()","Received new model.",e),t.resolve()},error:function(e){Galaxy.emit.debug("tool-form-composite::postchange()","Refresh request failed.",e),t.reject()}})},i=new _.default(e),e.post_job_actions&&e.post_job_actions.length&&i.portlet.append(n("").addClass("ui-form-element-disabled").append(n("").addClass("ui-form-title").html("Job Post Actions")).append(n("").addClass("ui-form-preview").html(s.reduce(e.post_job_actions,function(e,t){return e+" "+t.short_str},""))));else{var o=-1!=["data_input","data_collection_input"].indexOf(e.step_type);s.each(e.inputs,function(e){e.flavor="module",e.hide_label=o}),i=new f.default(l.default.merge({title:e.fixed_title,onchange:function(){s.each(t.links[e.index],function(e){t._refreshStep(e)})},inputs:e.inputs&&e.inputs.length>0?e.inputs:[{type:"hidden",name:"No options available.",ignore:null}]},e))}t.forms[e.index]=i,t._append(t.$steps,i.$el),t._refresh(),e.needs_refresh&&t._refreshStep(e),i.portlet[t.show_progress?"disable":"enable"](),t.show_progress&&t.execute_btn.model.set({wait:!0,wait_text:"Preparing...",percentage:100*(e.index+1)/t.steps.length}),Galaxy.emit.debug("tool-form-composite::initialize()",e.index+" : Workflow step state ready.",e),setTimeout(function(){a.resolve()},0)})},_refreshStep:function(e){var t=this,i=this.forms[e.index];i?(s.each(t.parms[e.index],function(e,n){if(e.step_linked||e.wp_linked){var a=i.field_list[i.data.match(n)];if(a){var o=void 0;if(e.step_linked)o={values:[]},s.each(e.step_linked,function(e){if(t._isDataStep(e)){var i=t.forms[e.index].data.create().input;i&&s.each(i.values,function(e){o.values.push(e)})}}),!e.multiple&&o.values.length>0&&(o={values:[o.values[0]]});else if(e.wp_linked){o=e.value;for(var l,r=/\$\{(.+?)\}/g;l=r.exec(e.value);){var d=t.wp_form.field_list[t.wp_form.data.match(l[1])],c=d&&d.value();c&&(o=o.split(l[0]).join(c))}}void 0!==o&&a.value(o)}}}),i.trigger("change")):e.needs_refresh=!0},_refreshHistory:function(){var e=this,t=parent.Galaxy&&parent.Galaxy.currHistoryPanel&&parent.Galaxy.currHistoryPanel.model;this._refresh_history&&clearTimeout(this._refresh_history),t&&t.refresh().success(function(){0===t.numOfUnfinishedShownContents()&&(e._refresh_history=setTimeout(function(){e._refreshHistory()},t.UPDATE_DELAY))})},_execute:function(){var e=this;this.show_progress=!0,this._enabled(!1),this.deferred.execute(function(t){setTimeout(function(){t.resolve(),e._submit()},0)})},_submit:function(){var e=this,t=this.history_form.data.create(),i={new_history_name:t["new_history|name"]?t["new_history|name"]:null,history_id:t["new_history|name"]?null:this.model.get("history_id"),replacement_params:this.wp_form?this.wp_form.data.create():{},parameters:{},parameters_normalized:!0,batch:!0},s=!0;for(var a in this.forms){var o=this.forms[a],r=o.data.create(),d=e.steps[a],c=d.step_index;o.trigger("reset");for(var u in r){var h=r[u],f=o.data.match(u),p=(o.field_list[f],o.input_list[f]);if(!p.step_linked){if(!(s=this._isDataStep(d)?h&&h.values&&h.values.length>0:p.optional||p.is_workflow&&""!==h||!p.is_workflow&&null!==h)){o.highlight(f);break}i.parameters[c]=i.parameters[c]||{},i.parameters[c][u]=r[u]}}if(!s)break}s?(Galaxy.emit.debug("tool-form-composite::submit()","Validation complete.",i),l.default.request({type:"POST",url:Galaxy.root+"api/workflows/"+this.model.id+"/invocations",data:i,success:function(t){if(Galaxy.emit.debug("tool-form-composite::submit","Submission successful.",t),e.$el.children().hide(),e.$el.append(e._templateSuccess(t)),n.isArray(t)&&t.length>0){e.$el.append(n("",{id:"webhook-view"}));new b.default.WebhookView({urlRoot:Galaxy.root+"api/webhooks/workflow",toolId:i.tool_id,toolVersion:i.tool_version})}e._refreshHistory()},error:function(t){Galaxy.emit.debug("tool-form-composite::submit","Submission failed.",t);var n=!1;if(t&&t.err_data)for(var s in e.forms){var a=e.forms[s],o=t.err_data[a.model.get("step_index")];if(o){var l=a.data.matchResponse(o);for(var r in l){a.highlight(r,l[r]),n=!0;break}}}n||e.modal.show({title:"Workflow submission failed",body:e._templateError(i,t&&t.err_msg),buttons:{Close:function(){e.modal.hide()}}})},complete:function(){e._enabled(!0)}})):(e._enabled(!0),Galaxy.emit.debug("tool-form-composite::submit()","Validation failed.",i))},_append:function(e,t){e.append("").append(t)},_enabled:function(e){this.execute_btn.model.set({wait:!e,wait_text:"Sending...",percentage:-1}),this.wp_form&&this.wp_form.portlet[e?"enable":"disable"](),this.history_form&&this.history_form.portlet[e?"enable":"disable"](),s.each(this.forms,function(t){t&&t.portlet[e?"enable":"disable"]()})},_isDataStep:function(e){for(var t=n.isArray(e)?e:[e],i=0;i0?n("").addClass("donemessagelarge").append(n("").html("Successfully invoked workflow "+l.default.sanitize(this.model.get("name"))+""+(e.length>1?" "+e.length+" times":"")+".")).append(n("").append("").text("You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.")):this._templateError(e,"Invalid success response. No invocations found.")},_templateError:function(e,t){return n("").addClass("errormessagelarge").append(n("").text("The server could not complete the request. Please contact the Galaxy Team if this error persists. "+(JSON.stringify(t)||""))).append(n("").text(JSON.stringify(e,null,4)))}});t.default={View:$}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(7),l=a(o),r=i(79),d=a(r),c=i(4),u=a(c),h={defaultName:e.template("Copy of '<%- name %>'"),title:e.template((0,u.default)("Copying history")+' "<%- name %>"'),submitLabel:(0,u.default)("Copy"),errorMessage:(0,u.default)("History could not be copied."),progressive:(0,u.default)("Copying history"),activeLabel:(0,u.default)("Copy only the active, non-deleted datasets"),allLabel:(0,u.default)("Copy all datasets including deleted ones"),anonWarning:(0,u.default)("As an anonymous user, unless you login or register, you will lose your current history ")+(0,u.default)("after copying this history. "),_template:e.template(["<% if( isAnon ){ %>",'
";this.modal.$(".modal-body").empty().append(e).css({"margin-top":"8px"})},dialog:function(t,i,a){function o(){var e=t.$("#copy-modal-title").val();if(!e)return void t.$(".invalid-title").show();var n="copy-all"===t.$('input[name="copy-what"]:checked').val();t.$("button").prop("disabled",!0),l._showAjaxIndicator(),i.copy(!0,e,n).done(function(e){r.resolve(e)}).fail(function(t,s,a){var o={name:e,copyAllDatasets:n};d.default.ajaxErrorModal(i,t,o,l.errorMessage),r.rejectWith(r,arguments)}).done(function(){m&&t.hide()})}a=a||{};var l=this,r=n.Deferred(),c=a.nameFn||this.defaultName,h=c({name:i.get("name")}),f=a.allDatasets?"copy-all":"copy-non-deleted",p=!!e.isUndefined(a.allowAll)||a.allowAll,m=!!e.isUndefined(a.autoClose)||a.autoClose;this.modal=t;var g=a.closing_callback;return t.show(e.extend(a,{title:this.title({name:i.get("name")}),body:s(l._template({name:h,isAnon:Galaxy.user.isAnonymous(),allowAll:p,copyWhat:f,activeLabel:this.activeLabel,allLabel:this.allLabel,anonWarning:this.anonWarning})),buttons:e.object([[(0,u.default)("Cancel"),function(){t.hide()}],[this.submitLabel,o]]),height:"auto",closing_events:!0,closing_callback:function(e){e&&r.reject({cancelled:!0}),g&&g(e)}})),t.$("#copy-modal-title").focus().select(),t.$("#copy-modal-title").on("keydown",function(e){13===e.keyCode&&(e.preventDefault(),o())}),r}},f=e.extend({},h,{defaultName:e.template("imported: <%- name %>"),title:e.template((0,u.default)("Importing history")+' "<%- name %>"'),submitLabel:(0,u.default)("Import"),errorMessage:(0,u.default)("History could not be imported."),progressive:(0,u.default)("Importing history"),activeLabel:(0,u.default)("Import only the active, non-deleted datasets"),allLabel:(0,u.default)("Import all datasets including deleted ones"),anonWarning:(0,u.default)("As an anonymous user, unless you login or register, you will lose your current history ")+(0,u.default)("after importing this history. ")}),p=function(e,t){t=t||{};var i=window.parent.Galaxy.modal||new l.default.View({});return t.useImport?f.dialog(i,e,t):h.dialog(i,e,t)};t.default=p}).call(t,i(1),i(0),i(0))},function(e,t,i){"use strict";(function(e,n){function s(t,i,n){return Galaxy.modal.show({title:i,body:t,closing_events:!0,buttons:{Ok:function(){Galaxy.modal.hide()}}}),Galaxy.modal.$el.addClass("error-modal"),n&&(Galaxy.modal.$(".error-details").add(Galaxy.modal.$('button:contains("Details")')).remove(),e("").addClass("error-details").hide().appendTo(Galaxy.modal.$(".modal-content")).append([e("").text(p),e("").text(JSON.stringify(n,null," "))]),e('").appendTo(Galaxy.modal.$(".buttons")).click(function(){Galaxy.modal.$(".error-details").toggle()})),Galaxy.modal}function a(e,t,i){if(e){if(e=(0,u.default)(e),t=(0,u.default)(t)||(0,u.default)("Error:"),window.Galaxy&&Galaxy.modal)return s(e,t,i);alert(t+"\n\n"+e),console.log("error details:",JSON.stringify(i))}}function o(){return a((0,u.default)("You appear to be offline. Please check your connection and try again."),(0,u.default)("Offline?"))}function l(){return a((0,u.default)("Galaxy is currently unreachable. Please try again in a few minutes.")+" "+h,(0,u.default)("Cannot connect to Galaxy"))}function r(e,t,i,n,s){return n=n||f,n+=" "+h,s=s||(0,u.default)("An error occurred"),a(n,s,d(e,t,i))}function d(e,t,i){return{raven:n.result(window.Raven,"lastEventId"),userAgent:navigator.userAgent,onLine:navigator.onLine,version:n.result(Galaxy.config,"version_major"),xhr:n.omit(t,n.functions(t)),options:n.omit(i,"xhr"),url:n.result(Galaxy.lastAjax,"url"),data:n.result(Galaxy.lastAjax,"data"),model:n.result(e,"toJSON",""+e),user:n.omit(n.result(Galaxy.user,"toJSON"),"email")}}Object.defineProperty(t,"__esModule",{value:!0});var c=i(4),u=function(e){return e&&e.__esModule?e:{default:e}}(c),h=(0,u.default)("Please contact a Galaxy administrator if the problem persists."),f=(0,u.default)("An error occurred while updating information with the server."),p=(0,u.default)("The following information can assist the developers in finding the source of the error:");t.default={errorModal:a,offlineErrorModal:o,badGatewayErrorModal:l,ajaxErrorModal:r}}).call(t,i(0),i(1))},function(e,t,i){"use strict";(function(e){function n(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t.default=e,t}Object.defineProperty(t,"__esModule",{value:!0});var s=i(1),a=n(s),o=i(2),l=n(o),r=i(5),d=function(e){return e&&e.__esModule?e:{default:e}}(r),c=l.Collection.extend({initialize:function(e,t){l.Collection.prototype.initialize.call(this,e,t),this.setOrder(t.order||this.order,{silent:!0})},_setUpListeners:function(){return this.on({"changed-order":this.sort})},fetch:function(e){return e=this._buildFetchOptions(e),Galaxy.debug("fetch options:",e),l.Collection.prototype.fetch.call(this,e)},_buildFetchOptions:function(e){e=a.clone(e)||{};var t=this;e.traditional=!0,e.data=e.data||t._buildFetchData(e),Galaxy.debug("data:",e.data);var i=this._buildFetchFilters(e);return Galaxy.debug("filters:",i),a.isEmpty(i)||a.extend(e.data,this._fetchFiltersToAjaxData(i)),Galaxy.debug("data:",e.data),e},_buildFetchData:function(e){var t={};return this.order&&(t.order=this.order),a.defaults(a.pick(e,this._fetchParams),t)},_fetchParams:["order","limit","offset","view","keys"],_buildFetchFilters:function(e){return a.clone(e.filters||{})},_fetchFiltersToAjaxData:function(e){var t={q:[],qv:[]};return a.each(e,function(e,i){void 0!==e&&""!==e&&(!0===e&&(e="True"),!1===e&&(e="False"),null===e&&(e="None"),t.q.push(i),t.qv.push(e))}),t},reset:function(e,t){return this.allFetched=!1,l.Collection.prototype.reset.call(this,e,t)},order:null,comparators:{update_time:d.default.buildComparator("update_time",{ascending:!1}),"update_time-asc":d.default.buildComparator("update_time",{ascending:!0}),create_time:d.default.buildComparator("create_time",{ascending:!1}),"create_time-asc":d.default.buildComparator("create_time",{ascending:!0})},setOrder:function(e,t){t=t||{};var i=this,n=i.comparators[e];if(a.isUndefined(n))throw new Error("unknown order: "+e);if(n!==i.comparator)return i.order=e,i.comparator=n,t.silent||i.trigger("changed-order",t),i}}),u=c.extend({limitPerPage:500,initialize:function(e,t){c.prototype.initialize.call(this,e,t),this.currentPage=t.currentPage||0},getTotalItemCount:function(){return this.length},shouldPaginate:function(){return this.getTotalItemCount()>=this.limitPerPage},getLastPage:function(){return Math.floor(this.getTotalItemCount()/this.limitPerPage)},getPageCount:function(){return this.getLastPage()+1},getPageLimitOffset:function(e){return e=this.constrainPageNum(e),{limit:this.limitPerPage,offset:e*this.limitPerPage}},constrainPageNum:function(e){return Math.max(0,Math.min(e,this.getLastPage()))},fetchPage:function(e,t){var i=this;return e=i.constrainPageNum(e),i.currentPage=e,t=a.defaults(t||{},i.getPageLimitOffset(e)),i.trigger("fetching-more"),i.fetch(t).always(function(){i.trigger("fetching-more-done")})},fetchCurrentPage:function(e){return this.fetchPage(this.currentPage,e)},fetchPrevPage:function(e){return this.fetchPage(this.currentPage-1,e)},fetchNextPage:function(e){return this.fetchPage(this.currentPage+1,e)}}),h=c.extend({limitOnFirstFetch:null,limitPerFetch:100,initialize:function(e,t){c.prototype.initialize.call(this,e,t),this.limitOnFirstFetch=t.limitOnFirstFetch||this.limitOnFirstFetch,this.limitPerFetch=t.limitPerFetch||this.limitPerFetch,this.allFetched=!1,this.lastFetched=t.lastFetched||0},_buildFetchOptions:function(e){return e.remove=e.remove||!1,c.prototype._buildFetchOptions.call(this,e)},fetchFirst:function(e){return Galaxy.debug("ControlledFetchCollection.fetchFirst:",e),e=e?a.clone(e):{},this.allFetched=!1,this.lastFetched=0,this.fetchMore(a.defaults(e,{reset:!0,limit:this.limitOnFirstFetch}))},fetchMore:function(t){Galaxy.debug("ControlledFetchCollection.fetchMore:",t),t=a.clone(t||{});var i=this;if(Galaxy.debug("fetchMore, options.reset:",t.reset),!t.reset&&i.allFetched)return e.when();t.reset?t.offset=0:void 0===t.offset&&(t.offset=i.lastFetched);var n=t.limit=t.limit||i.limitPerFetch||null;return Galaxy.debug("fetchMore, limit:",n,"offset:",t.offset),i.trigger("fetching-more"),i.fetch(t).always(function(){i.trigger("fetching-more-done")}).done(function(e){var t=a.isArray(e)?e.length:0;i.lastFetched+=t,Galaxy.debug("fetchMore, lastFetched:",i.lastFetched),(!n||t1?this.renderItems():1===i.added.length?this.addItemView(n.first(i.added),e,t):1===i.removed.length?this.removeItemView(n.first(i.removed),e,t):void 0}}),this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners"),this.on({"view:selected":function(e,t){if(t&&t.shiftKey&&this.lastSelected){var i=this.viewFromModelId(this.lastSelected);i&&this.selectRange(e,i)}else t&&t.altKey&&!this.selecting&&this.showSelectors();this.selected.push(e.model.id),this.lastSelected=e.model.id},"view:de-selected":function(e,t){this.selected=n.without(this.selected,e.model.id)}})},render:function(e){this.log(this+".render",e);var t=this._buildNewRender();return this._setUpBehaviors(t),this._queueNewRender(t,e),this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var e=s(this.templates.el({},this));return this._renderControls(e),this._renderTitle(e),this._renderSubtitle(e),this._renderSearch(e),this.renderItems(e),e},_renderControls:function(e){this.debug(this+"(ListPanel)._renderControls");var t=s(this.templates.controls({},this));return e.find(".controls").replaceWith(t),t},_renderTitle:function(e){},_renderSubtitle:function(e){},_queueNewRender:function(e,t){t=void 0===t?this.fxSpeed:t;var i=this;i.log("_queueNewRender:",e,t),s(i).queue("fx",[function(e){i.$el.fadeOut(t,e)},function(t){i._swapNewRender(e),t()},function(e){i.$el.fadeIn(t,e)},function(e){i.trigger("rendered",i),e()}])},_swapNewRender:function(e){return this.$el.empty().attr("class",this.className).append(e.children()),this.selecting&&this.showSelectors(0),this},_setUpBehaviors:function(e){return e=e||this.$el,this.$controls(e).find("[title]").tooltip(),this._renderMultiselectActionMenu(e),this},_renderMultiselectActionMenu:function(e){e=e||this.$el;var t=e.find(".list-action-menu"),i=this.multiselectActions();if(!i.length)return t.empty();var n=s(['
"],"collection");return e.extend(e.clone(f.prototype.templates),{controls:t})}();var m=p.extend({DatasetDCEViewClass:r.default.DatasetDCEListItemView,toString:function(){return"ListCollectionView("+(this.model?this.model.get("name"):"")+")"}}),g=m.extend({toString:function(){return"PairCollectionView("+(this.model?this.model.get("name"):"")+")"}}),_=p.extend({NestedDCDCEViewClass:r.default.NestedDCDCEListItemView.extend({foldoutPanelClass:g}),toString:function(){return"ListOfPairsCollectionView("+(this.model?this.model.get("name"):"")+")"}}),v=p.extend({NestedDCDCEViewClass:r.default.NestedDCDCEListItemView.extend({foldoutPanelClass:g}),toString:function(){return"ListOfListsCollectionView("+(this.model?this.model.get("name"):"")+")"}});t.default={CollectionView:p,ListCollectionView:m,PairCollectionView:g,ListOfPairsCollectionView:_,ListOfListsCollectionView:v}}).call(t,i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(11),o=s(a),l=i(42),r=s(l),d=i(22),c=s(d),u=i(89),h=s(u),f=i(14),p=s(f),m=i(5),g=s(m),_=i(4),v=s(_),w=r.default.DatasetListItemView,y=w.extend({initialize:function(e){w.prototype.initialize.call(this,e),this.hasUser=e.hasUser,this.purgeAllowed=e.purgeAllowed||!1,this.tagsEditorShown=e.tagsEditorShown||!1,this.annotationEditorShown=e.annotationEditorShown||!1},_renderPrimaryActions:function(){var e=w.prototype._renderPrimaryActions.call(this);return this.model.get("state")===o.default.NOT_VIEWABLE?e:w.prototype._renderPrimaryActions.call(this).concat([this._renderEditButton(),this._renderDeleteButton()])},_renderEditButton:function(){var t=this;if(this.model.get("state")===o.default.DISCARDED||!this.model.get("accessible"))return null;var i=this.model.get("purged"),n=this.model.get("deleted"),s={title:(0,v.default)("Edit attributes"),href:Galaxy.root+"datasets/edit?dataset_id="+this.model.attributes.id,faIcon:"fa-pencil",classes:"edit-btn",onclick:function(e){Galaxy.router&&(e.preventDefault(),Galaxy.router.push("datasets/edit",{dataset_id:t.model.attributes.id}))}};return n||i?(s.disabled=!0,i?s.title=(0,v.default)("Cannot edit attributes of datasets removed from disk"):n&&(s.title=(0,v.default)("Undelete dataset to edit attributes"))):e.contains([o.default.UPLOAD,o.default.NEW],this.model.get("state"))&&(s.disabled=!0,s.title=(0,v.default)("This dataset is not yet editable")),(0,p.default)(s)},_renderDeleteButton:function(){if(!this.model.get("accessible"))return null;var e=this,t=this.model.isDeletedOrPurged();return(0,p.default)({title:t?(0,v.default)("Dataset is already deleted"):(0,v.default)("Delete"),disabled:t,faIcon:"fa-times",classes:"delete-btn",onclick:function(){e.$el.find(".icon-btn.delete-btn").trigger("mouseout"),e.model.delete()}})},_renderDetails:function(){var t=w.prototype._renderDetails.call(this),i=this.model.get("state");return!this.model.isDeletedOrPurged()&&e.contains([o.default.OK,o.default.FAILED_METADATA],i)&&(this._renderTags(t),this._renderAnnotation(t),this._makeDbkeyEditLink(t)),this._setUpBehaviors(t),t},_renderToolHelpButton:function(){var e=this.model.attributes.dataset_id,t=this.model.attributes.creating_job,i=this,s=function(t){var s='
';t.name&&t.help?(s+="Tool help for "+t.name+"",s+=t.help):s+="Tool help is unavailable for this dataset.",s+="
",i.$el.find(".details").append(n.parseHTML(s))},a=function(e){n.ajax({url:Galaxy.root+"api/tools/"+e.tool_id+"/build"}).done(function(e){s(e)}).fail(function(){s({})})};return null===Galaxy.user.id?null:(0,p.default)({title:(0,v.default)("Tool Help"),classes:"icon-btn",href:"#",faIcon:"fa-question",onclick:function(){i.$el.find(".toolhelp").length>0?i.$el.find(".toolhelp").toggle():n.ajax({url:Galaxy.root+"api/jobs/"+t}).done(function(e){a(e)}).fail(function(){console.log('Failed at recovering job information from the Galaxy API for job id "'+t+'".')})}})},_renderSecondaryActions:function(){var e=w.prototype._renderSecondaryActions.call(this);switch(this.model.get("state")){case o.default.UPLOAD:case o.default.NOT_VIEWABLE:return e;case o.default.ERROR:return e.unshift(this._renderErrButton()),e.concat([this._renderRerunButton(),this._renderToolHelpButton()]);case o.default.OK:case o.default.FAILED_METADATA:return e.concat([this._renderRerunButton(),this._renderVisualizationsButton(),this._renderToolHelpButton()])}return e.concat([this._renderRerunButton(),this._renderToolHelpButton()])},_renderErrButton:function(){var e=this;return(0,p.default)({title:(0,v.default)("View or report this error"),href:Galaxy.root+"datasets/error?dataset_id="+this.model.attributes.id,classes:"report-error-btn",faIcon:"fa-bug",onclick:function(t){Galaxy.router&&(t.preventDefault(),Galaxy.router.push("datasets/error",{dataset_id:e.model.attributes.id}))}})},_renderRerunButton:function(){var e=this.model.get("creating_job");if(this.model.get("rerunnable"))return(0,p.default)({title:(0,v.default)("Run this job again"),href:this.model.urls.rerun,classes:"rerun-btn",target:this.linkTarget,faIcon:"fa-refresh",onclick:function(t){Galaxy.router&&(t.preventDefault(),Galaxy.router.push("/",{job_id:e}))}})},_renderVisualizationsButton:function(){var t=this.model.get("visualizations");if(this.model.isDeletedOrPurged()||!this.hasUser||!this.model.hasData()||e.isEmpty(t))return null;if(!e.isObject(t[0]))return this.warn("Visualizations have been switched off"),null;var i=n(this.templates.visualizations(t,this));return i.find('[target="galaxy_main"]').attr("target",this.linkTarget),this._addScratchBookFn(i.find(".visualization-link").addBack(".visualization-link")),i},_addScratchBookFn:function(e){e.click(function(e){Galaxy.frame&&Galaxy.frame.active&&(Galaxy.frame.add({title:"Visualization",url:n(this).attr("href")}),e.preventDefault(),e.stopPropagation())})},_renderTags:function(e){if(this.hasUser){var t=this;this.tagsEditor=new c.default.TagsEditor({model:this.model,el:e.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.tagsEditorShown=!0},onhide:function(){t.tagsEditorShown=!1},$activator:(0,p.default)({title:(0,v.default)("Edit dataset tags"),classes:"tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".actions .right"))}),this.tagsEditorShown&&this.tagsEditor.toggle(!0)}},_renderAnnotation:function(e){if(this.hasUser){var t=this;this.annotationEditor=new h.default.AnnotationEditor({model:this.model,el:e.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.annotationEditorShown=!0},onhide:function(){t.annotationEditorShown=!1},$activator:(0,p.default)({title:(0,v.default)("Edit dataset annotation"),classes:"annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".actions .right"))}),this.annotationEditorShown&&this.annotationEditor.toggle(!0)}},_makeDbkeyEditLink:function(e){if("?"===this.model.get("metadata_dbkey")&&!this.model.isDeletedOrPurged()){var t=n('?').attr("href",this.model.urls.edit).attr("target","_top");e.find(".dbkey .value").replaceWith(t)}},events:e.extend(e.clone(w.prototype.events),{"click .undelete-link":"_clickUndeleteLink","click .purge-link":"_clickPurgeLink","click .edit-btn":function(e){this.trigger("edit",this,e)},"click .delete-btn":function(e){this.trigger("delete",this,e)},"click .rerun-btn":function(e){this.trigger("rerun",this,e)},"click .report-err-btn":function(e){this.trigger("report-err",this,e)},"click .visualization-btn":function(e){this.trigger("visualize",this,e)},"click .dbkey a":function(e){this.trigger("edit",this,e)}}),_clickUndeleteLink:function(e){return this.model.undelete(),!1},_clickPurgeLink:function(e){return confirm((0,v.default)("This will permanently remove the data in your dataset. Are you sure?"))&&this.model.purge(),!1},toString:function(){return"HDAEditView("+(this.model?""+this.model:"(no model)")+")"}});y.prototype.templates=function(){var t=e.extend({},w.prototype.templates.warnings,{failed_metadata:g.default.wrapTemplate(['<% if( dataset.state === "failed_metadata" ){ %>','
',"",(0,c.default)("Search did not match any tools."),"","
","
",'','','
',"",(0,c.default)("Workflows"),"","
",'
','',"
","
"].join("")},toString:function(){return"toolPanel"}}));t.default=h}).call(t,i(2),i(1))},function(e,t,i){"use strict";(function(e){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var s=i(3),a=n(s),o=i(7),l=n(o),r=i(28),d=n(r),c=i(141),u=n(c),h=i(142),f=n(h),p=i(145),m=n(p),g=i(147),_=n(g);t.default=e.View.extend({options:{nginx_upload_path:"",ftp_upload_site:"n/a",default_genome:"?",default_extension:"auto",height:500,width:900,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."}},list_extensions:[],list_genomes:[],initialize:function(e){var t=this;this.options=a.default.merge(e,this.options),this.ui_button=new u.default.View({onclick:function(e){e.preventDefault(),t.show()},onunload:function(){var e=t.ui_button.model.get("percentage",0);if(e>0&&e<100)return"Several uploads are queued."}}),this.setElement(this.ui_button.$el);var t=this;a.default.get({url:Galaxy.root+"api/datatypes?extension_only=False",success:function(e){for(var i in e)t.list_extensions.push({id:e[i].extension,text:e[i].extension,description:e[i].description,description_url:e[i].description_url,composite_files:e[i].composite_files});t.list_extensions.sort(function(e,t){var i=e.text&&e.text.toLowerCase(),n=t.text&&t.text.toLowerCase();return i>n?1:ii.text?1:e.text0){var n={file_count:e.length,dbkey:e[0].get("genome","?"),file_type:e[0].get("extension","auto")};for(var s in e){var a=e[s];if(a.set("status","running"),!(a.get("file_size")>0)){i.error_message="Upload content incomplete.",a.set("status","error"),a.set("info",i.error_message);break}var o="files_"+s+"|";switch(n[o+"type"]="upload_dataset",n[o+"space_to_tab"]=a.get("space_to_tab")&&"Yes"||null,n[o+"to_posix_lines"]=a.get("to_posix_lines")&&"Yes"||null,n[o+"dbkey"]=a.get("genome",null),n[o+"file_type"]=a.get("extension",null),a.get("file_mode")){case"new":n[o+"url_paste"]=a.get("url_paste");break;case"ftp":n[o+"ftp_files"]=a.get("file_path");break;case"local":i.files.push({name:o+"file_data",file:a.get("file_data")})}}i.payload.inputs=JSON.stringify(n)}return i}})}).call(t,i(2))},function(e,t,i){"use strict";(function(e,i){Object.defineProperty(t,"__esModule",{value:!0});var n=e.View.extend({initialize:function(t){var n=this;this.model=t&&t.model||new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",percentage:0,status:"",onunload:function(){},onclick:function(){}}).set(t),this.setElement(this._template()),this.$progress=this.$(".progress-bar"),this.listenTo(this.model,"change",this.render,this),this.render(),i(window).on("beforeunload",function(){return n.model.get("onunload")()})},render:function(){var e=this.model.attributes;this.$el.off("click").on("click",function(t){e.onclick(t)}).tooltip({title:this.model.get("tooltip"),placement:"bottom"}),this.$progress.removeClass().addClass("progress-bar").addClass("progress-bar-notransition").addClass(""!=e.status&&"progress-bar-"+e.status).css({width:e.percentage+"%"})},_template:function(){return'
'}});t.default={View:n}}).call(t,i(2),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(16)),r=a(l),d=i(143),c=a(d),u=i(32),h=a(u),f=i(33),p=a(f),m=i(10),g=a(m),_=i(13),v=a(_),w=i(6),y=a(w),b=i(144),x=a(b);i(34),t.default=e.View.extend({upload_size:0,collection:new r.default.Collection,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(e){var t=this;this.app=e,this.options=e.options,this.list_extensions=e.list_extensions,this.list_genomes=e.list_genomes,this.ui_button=e.ui_button,this.ftp_upload_site=e.currentFtp(),this.setElement(this._template()),this.$uploadbox=this.$(".upload-box"),this.$uploadtable=this.$(".upload-table"),this.btnLocal=new y.default.Button({id:"btn-local",title:"Choose local file",onclick:function(){t.uploadbox.select()},icon:"fa fa-laptop"}),this.btnFtp=new y.default.Button({id:"btn-ftp",title:"Choose FTP file",onclick:function(){t._eventFtp()},icon:"fa fa-folder-open-o"}),this.btnCreate=new y.default.Button({id:"btn-new",title:"Paste/Fetch data",onclick:function(){t._eventCreate()},icon:"fa fa-edit"}),this.btnStart=new y.default.Button({id:"btn-start",title:"Start",onclick:function(){t._eventStart()}}),this.btnStop=new y.default.Button({id:"btn-stop",title:"Pause",onclick:function(){t._eventStop()}}),this.btnReset=new y.default.Button({id:"btn-reset",title:"Reset",onclick:function(){t._eventReset()}}),this.btnClose=new y.default.Button({id:"btn-close",title:"Close",onclick:function(){t.app.modal.hide()}}),n.each([this.btnLocal,this.btnFtp,this.btnCreate,this.btnStop,this.btnReset,this.btnStart,this.btnClose],function(e){t.$(".upload-buttons").prepend(e.$el)}),this.uploadbox=this.$uploadbox.uploadbox({url:this.app.options.nginx_upload_path,announce:function(e,i){t._eventAnnounce(e,i)},initialize:function(e){return t.app.toData([t.collection.get(e)],t.history_id)},progress:function(e,i){t._eventProgress(e,i)},success:function(e,i){t._eventSuccess(e,i)},error:function(e,i){t._eventError(e,i)},complete:function(){t._eventComplete()},ondragover:function(){t.$uploadbox.addClass("highlight")},ondragleave:function(){t.$uploadbox.removeClass("highlight")}}),this.ftp=new g.default.View({title:"FTP files",container:this.btnFtp.$el}),this.select_extension=new v.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-extension"),data:n.filter(this.list_extensions,function(e){return!e.composite_files}),value:this.options.default_extension,onchange:function(e){t._changeExtension(e)}}),this.$(".upload-footer-extension-info").on("click",function(e){new p.default({$el:s(e.target),title:t.select_extension.text(),extension:t.select_extension.value(),list:t.list_extensions,placement:"top"})}).on("mousedown",function(e){e.preventDefault()}),this.select_genome=new v.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-genome"),data:this.list_genomes,value:this.options.default_genome,onchange:function(e){t._changeGenome(e)}}),this.loader=new x.default({$container:this.$uploadbox,collection:this.collection,new_content:function(e){var i=new c.default(t,{model:e});return t.$uploadtable.find("> tbody:first").append(i.$el),i.render(),i}}),this.collection.on("remove",function(e){t._eventRemove(e)}),this.render()},render:function(){var e="";e=0==this.counter.announce?this.uploadbox.compatible()?" ":"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.":0==this.counter.running?"You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed.":"Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining.",this.$(".upload-top-info").html(e);var t=0==this.counter.running&&this.counter.announce+this.counter.success+this.counter.error>0,i=0==this.counter.running&&this.counter.announce>0,n=0==this.counter.running,s=this.counter.announce+this.counter.success+this.counter.error>0;this.btnReset[t?"enable":"disable"](),this.btnStart[i?"enable":"disable"](),this.btnStart.$el[i?"addClass":"removeClass"]("btn-primary"),this.btnStop[this.counter.running>0?"enable":"disable"](),this.btnLocal[n?"enable":"disable"](),this.btnFtp[n?"enable":"disable"](),this.btnCreate[n?"enable":"disable"](),this.btnFtp.$el[this.ftp_upload_site?"show":"hide"](),this.$(".upload-table")[s?"show":"hide"](),this.$(".upload-helper")[s?"hide":"show"]()},_eventAnnounce:function(e,t){this.counter.announce++;var i=new r.default.Model({id:e,file_name:t.name,file_size:t.size,file_mode:t.mode||"local",file_path:t.path,file_data:t});this.render(),this.collection.add(i)},_eventProgress:function(e,t){var i=this.collection.get(e);i.set("percentage",t),this.ui_button.model.set("percentage",this._uploadPercentage(t,i.get("file_size")))},_eventSuccess:function(e,t){var i=this.collection.get(e);i.set({percentage:100,status:"success"}),this.ui_button.model.set("percentage",this._uploadPercentage(100,i.get("file_size"))),this.upload_completed+=100*i.get("file_size"),this.counter.announce--,this.counter.success++,this.render(),Galaxy.currHistoryPanel.refreshContents()},_eventError:function(e,t){var i=this.collection.get(e);i.set({percentage:100,status:"error",info:t}),this.ui_button.model.set({percentage:this._uploadPercentage(100,i.get("file_size")),status:"danger"}),this.upload_completed+=100*i.get("file_size"),this.counter.announce--,this.counter.error++,this.render()},_eventComplete:function(){this.collection.each(function(e){"queued"==e.get("status")&&e.set("status","init")}),this.counter.running=0,this.render()},_eventRemove:function(e){var t=e.get("status");"success"==t?this.counter.success--:"error"==t?this.counter.error--:this.counter.announce--,this.uploadbox.remove(e.id),this.render()},_eventFtp:function(){if(this.ftp.visible)this.ftp.hide();else{this.ftp.empty();var e=this;this.ftp.append(new h.default({collection:this.collection,ftp_upload_site:this.ftp_upload_site,onadd:function(t){return e.uploadbox.add([{mode:"ftp",name:t.path,size:t.size,path:t.path}])},onremove:function(t){e.collection.remove(t)}}).$el),this.ftp.show()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(0!=this.counter.announce&&0==this.counter.running){var e=this;this.upload_size=0,this.upload_completed=0,this.collection.each(function(t){"init"==t.get("status")&&(t.set("status","queued"),e.upload_size+=t.get("file_size"))}),this.ui_button.model.set({percentage:0,status:"success"}),this.counter.running=this.counter.announce,this.history_id=this.app.currentHistory(),this._uploadFtp(),this.uploadbox.start(),this.render()}},_eventStop:function(){this.counter.running>0&&(this.ui_button.model.set("status","info"),s(".upload-top-info").html("Queue will pause after completing the current file..."),this.uploadbox.stop())},_eventReset:function(){if(0==this.counter.running){this.collection.reset(),this.counter.reset(),this.uploadbox.reset(),this.select_extension.value(this.options.default_extension),this.select_genome.value(this.options.default_genome),this.ui_button.model.set("percentage",0),this.render()}},_changeExtension:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("extension")!=i.options.default_extension&&t||n.set("extension",e)})},_changeGenome:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("genome")!=i.options.default_genome&&t||n.set("genome",e)})},_uploadFtp:function(){var e=this,t=[];this.collection.each(function(i){"queued"==i.get("status")&&"ftp"==i.get("file_mode")&&(e.uploadbox.remove(i.id),t.push(i))}),t.length>0&&s.uploadpost({data:this.app.toData(t),url:this.app.options.nginx_upload_path,success:function(i){n.each(t,function(t){e._eventSuccess(t.id)})},error:function(i){n.each(t,function(t){e._eventError(t.id,i)})}})},_uploadPercentage:function(e,t){return(this.upload_completed+e*t)/this.upload_size},_template:function(){return'
Drop files here
Name
Size
Type
Genome
Settings
Status
'}})}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(16),d=(a(r),i(31)),c=a(d),u=i(10),h=a(u),f=i(13),p=a(f);t.default=e.View.extend({status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},initialize:function(e,t){var i=this;this.app=e,this.model=t.model,this.setElement(this._template(t.model)),this.$mode=this.$(".upload-mode"),this.$title=this.$(".upload-title"),this.$text=this.$(".upload-text"),this.$size=this.$(".upload-size"),this.$info_text=this.$(".upload-info-text"),this.$info_progress=this.$(".upload-info-progress"),this.$text_content=this.$(".upload-text-content"),this.$settings=this.$(".upload-settings"),this.$symbol=this.$(".upload-symbol"),this.$progress_bar=this.$(".upload-progress-bar"),this.$percentage=this.$(".upload-percentage"),this.settings=new h.default.View({title:"Upload configuration",container:this.$(".upload-settings"),placement:"bottom"});var s=this.app.select_genome.value(),a=this.app.select_extension.value();this.select_genome=new p.default.View({css:"upload-genome",data:i.app.list_genomes,container:this.$(".upload-genome"),value:s,onchange:function(e){i.model.set("genome",e)}}),this.select_extension=new p.default.View({css:"upload-extension",data:i.app.list_extensions,container:this.$(".upload-extension"),value:a,onchange:function(e){i.model.set("extension",e)}}),this.model.set({genome:s,extension:a}),this.$symbol.on("click",function(){i._removeRow()}),this.$(".upload-extension-info").on("click",function(e){i.app.showExtensionInfo({$el:n(e.target),title:i.select_extension.text(),extension:i.select_extension.value()})}).on("mousedown",function(e){e.preventDefault()}),this.$settings.on("click",function(e){i._showSettings()}).on("mousedown",function(e){e.preventDefault()}),this.$text_content.on("change input",function(e){i.model.set({url_paste:n(e.target).val(),file_size:n(e.target).val().length})}),this.listenTo(this.model,"change:percentage",function(){i._refreshPercentage()}),this.listenTo(this.model,"change:status",function(){i._refreshStatus()}),this.listenTo(this.model,"change:info",function(){i._refreshInfo()}),this.listenTo(this.model,"change:genome",function(){i._refreshGenome()}),this.listenTo(this.model,"change:extension",function(){i._refreshExtension()}),this.listenTo(this.model,"change:file_size",function(){i._refreshFileSize()})},render:function(){this._refreshType(),this._refreshPercentage(),this._refreshStatus(),this._refreshInfo(),this._refreshGenome(),this._refreshExtension(),this._refreshFileSize()},remove:function(){this.select_genome.remove(),this.select_extension.remove(),e.View.prototype.remove.apply(this)},_refreshType:function(){var e=this.model.attributes;this.$title.html(s.escape(e.file_name)),this.$size.html(l.default.bytesToString(e.file_size)),this.$mode.removeClass().addClass("upload-mode").addClass("text-primary"),"new"==e.file_mode?(this.$text.css({width:this.$el.width()-16+"px",top:this.$el.height()-8+"px"}).show(),this.$el.height(this.$el.height()-8+this.$text.height()+16),this.$mode.addClass("fa fa-edit")):"local"==e.file_mode?this.$mode.addClass("fa fa-laptop"):"ftp"==e.file_mode&&this.$mode.addClass("fa fa-folder-open-o")},_refreshExtension:function(){this.select_extension.value(this.model.get("extension"))},_refreshGenome:function(){this.select_genome.value(this.model.get("genome"))},_refreshInfo:function(){var e=this.model.get("info");e?this.$info_text.html("Failed: "+e).show():this.$info_text.hide()},_refreshPercentage:function(){var e=parseInt(this.model.get("percentage"));this.$progress_bar.css({width:e+"%"}),this.$percentage.html(100!=e?e+"%":"Adding to history...")},_refreshStatus:function(){var e=this.model.get("status");this.$symbol.removeClass().addClass("upload-symbol").addClass(this.status_classes[e]),this.model.set("enabled","init"==e);var t=this.model.get("enabled");this.$text_content.attr("disabled",!t),t?(this.select_genome.enable(),this.select_extension.enable()):(this.select_genome.disable(),this.select_extension.disable()),"success"==e&&(this.$el.addClass("success"),this.$percentage.html("100%")),"error"==e&&(this.$el.addClass("danger"),this.$info_progress.hide())},_refreshFileSize:function(){this.$size.html(l.default.bytesToString(this.model.get("file_size")))},_removeRow:function(){-1!==["init","success","error"].indexOf(this.model.get("status"))&&this.app.collection.remove(this.model)},_showSettings:function(){this.settings.visible?this.settings.hide():(this.settings.empty(),this.settings.append(new c.default(this).$el),this.settings.show())},_template:function(e){return'
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
 
0%
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,i,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=e.View.extend({initialize:function(e){this.$container=e.$container,this.collection=e.collection,this.new_content=e.new_content,this.max=e.max||50,this.content_list={},this.$message=i("").addClass("ui-limitloader").append("...only the first "+this.max+" entries are visible."),this.$container.append(this.$message),this.listenTo(this.collection,"reset",this._reset,this),this.listenTo(this.collection,"add",this._refresh,this),this.listenTo(this.collection,"remove",this._remove,this)},_done:function(){var e=n.size(this.content_list)>this.max;return this.$message[e?"show":"hide"](),e},_reset:function(){n.each(this.content_list,function(e){e.remove()}),this.content_list={},this.$message.hide()},_remove:function(e){var t=e.id,i=this.content_list[t];i&&(i.remove(),delete this.content_list[t]),this._refresh()},_refresh:function(){if(!this._done())for(var e in this.collection.models){var t=this.collection.models[e];this.content_list[t.id];if(!this.content_list[t.id]){var i=this.new_content(t);if(this.content_list[t.id]=i,this._done())break}}}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(16)),r=a(l),d=i(146),c=a(d),u=i(33),h=a(u),f=i(10),p=(a(f),i(13)),m=a(p),g=i(6),_=a(g);t.default=e.View.extend({collection:new r.default.Collection,initialize:function(e){var t=this;this.app=e,this.options=e.options,this.list_extensions=e.list_extensions,this.list_genomes=e.list_genomes,this.ftp_upload_site=e.currentFtp(),this.setElement(this._template()),this.btnStart=new _.default.Button({title:"Start",onclick:function(){t._eventStart()}}),this.btnClose=new _.default.Button({title:"Close",onclick:function(){t.app.modal.hide()}}),n.each([this.btnStart,this.btnClose],function(e){t.$(".upload-buttons").prepend(e.$el)}),this.select_extension=new m.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-extension"),data:n.filter(this.list_extensions,function(e){return e.composite_files}),onchange:function(e){t.collection.reset();var i=n.findWhere(t.list_extensions,{id:e});i&&i.composite_files&&n.each(i.composite_files,function(e){t.collection.add({id:t.collection.size(),file_desc:e.description||e.name})})}}),this.$(".upload-footer-extension-info").on("click",function(e){new h.default({$el:s(e.target),title:t.select_extension.text(),extension:t.select_extension.value(),list:t.list_extensions,placement:"top"})}).on("mousedown",function(e){e.preventDefault()}),this.select_genome=new m.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-genome"),data:this.list_genomes,value:this.options.default_genome}),this.listenTo(this.collection,"add",function(e){t._eventAnnounce(e)}),this.listenTo(this.collection,"change add",function(){t.render()}),this.select_extension.options.onchange(this.select_extension.value()),this.render()},render:function(){var e=this.collection.first();e&&"running"==e.get("status")?(this.select_genome.disable(),this.select_extension.disable()):(this.select_genome.enable(),this.select_extension.enable()),this.collection.where({status:"ready"}).length==this.collection.length&&this.collection.length>0?(this.btnStart.enable(),this.btnStart.$el.addClass("btn-primary")):(this.btnStart.disable(),this.btnStart.$el.removeClass("btn-primary")),this.$(".upload-table")[this.collection.length>0?"show":"hide"]()},_eventAnnounce:function(e){var t=new c.default(this,{model:e});this.$(".upload-table > tbody:first").append(t.$el),this.$(".upload-table")[this.collection.length>0?"show":"hide"](),t.render()},_eventStart:function(){var e=this;this.collection.each(function(t){t.set({genome:e.select_genome.value(),extension:e.select_extension.value()})}),s.uploadpost({url:this.app.options.nginx_upload_path,data:this.app.toData(this.collection.filter()),success:function(t){e._eventSuccess(t)},error:function(t){e._eventError(t)},progress:function(t){e._eventProgress(t)}})},_eventProgress:function(e){this.collection.each(function(t){t.set("percentage",e)})},_eventSuccess:function(e){this.collection.each(function(e){e.set("status","success")}),Galaxy.currHistoryPanel.refreshContents()},_eventError:function(e){this.collection.each(function(t){t.set({status:"error",info:e})})},_template:function(){return'
Description
Name
Size
Settings
Status
'}})}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(31),d=a(r),c=i(32),u=a(c),h=i(10),f=a(h),p=i(6),m=a(p),g=i(13);a(g);i(34),t.default=e.View.extend({status_classes:{init:"upload-mode fa fa-exclamation text-primary",ready:"upload-mode fa fa-check text-success",running:"upload-mode fa fa-spinner fa-spin",success:"upload-mode fa fa-check",error:"upload-mode fa fa-exclamation-triangle"},initialize:function(e,t){var i=this;this.app=e,this.model=t.model,this.setElement(this._template()),this.$source=this.$(".upload-source"),this.$settings=this.$(".upload-settings"),this.$status=this.$(".upload-status"),this.$text=this.$(".upload-text"),this.$text_content=this.$(".upload-text-content"),this.$info_text=this.$(".upload-info-text"),this.$info_progress=this.$(".upload-info-progress"),this.$file_name=this.$(".upload-file-name"),this.$file_desc=this.$(".upload-file-desc"),this.$file_size=this.$(".upload-file-size"),this.$progress_bar=this.$(".upload-progress-bar"),this.$percentage=this.$(".upload-percentage"),this.uploadinput=this.$el.uploadinput({ondragover:function(){i.model.get("enabled")&&i.$el.addClass("warning")},ondragleave:function(){i.$el.removeClass("warning")},onchange:function(e){"running"!=i.model.get("status")&&e&&e.length>0&&(i.model.reset({file_data:e[0],file_name:e[0].name,file_size:e[0].size,file_mode:e[0].mode||"local"}),i._refreshReady())}}),this.button_menu=new m.default.ButtonMenu({icon:"fa-caret-down",title:"Select",pull:"left"}),this.$source.append(this.button_menu.$el),this.button_menu.addMenu({icon:"fa-laptop",title:"Choose local file",onclick:function(){i.uploadinput.dialog()}}),this.app.ftp_upload_site&&this.button_menu.addMenu({icon:"fa-folder-open-o",title:"Choose FTP file",onclick:function(){i._showFtp()}}),this.button_menu.addMenu({icon:"fa-edit",title:"Paste/Fetch data",onclick:function(){i.model.reset({file_mode:"new",file_name:"New File"})}}),this.ftp=new f.default.View({title:"Choose FTP file:",container:this.$source.find(".ui-button-menu"),placement:"right"}),this.settings=new f.default.View({title:"Upload configuration",container:this.$settings,placement:"bottom"}),this.$text_content.on("change input",function(e){i.model.set({url_paste:n(e.target).val(),file_size:n(e.target).val().length}),i._refreshReady()}),this.$settings.on("click",function(e){i._showSettings()}).on("mousedown",function(e){e.preventDefault()}),this.listenTo(this.model,"change:percentage",function(){i._refreshPercentage()}),this.listenTo(this.model,"change:status",function(){i._refreshStatus()}),this.listenTo(this.model,"change:info",function(){i._refreshInfo()}),this.listenTo(this.model,"change:file_name",function(){i._refreshFileName()}),this.listenTo(this.model,"change:file_mode",function(){i._refreshMode()}),this.listenTo(this.model,"change:file_size",function(){i._refreshFileSize()}),this.listenTo(this.model,"remove",function(){i.remove()}),this.app.collection.on("reset",function(){i.remove()})},render:function(){this.$el.attr("id","upload-row-"+this.model.id),this.$file_name.html(s.escape(this.model.get("file_name")||"-")),this.$file_desc.html(this.model.get("file_desc")||"Unavailable"),this.$file_size.html(l.default.bytesToString(this.model.get("file_size"))),this.$status.removeClass().addClass(this.status_classes.init)},remove:function(){e.View.prototype.remove.apply(this)},_refreshReady:function(){this.app.collection.each(function(e){e.set("status",e.get("file_size")>0&&"ready"||"init")})},_refreshMode:function(){"new"==this.model.get("file_mode")?(this.height=this.$el.height(),this.$text.css({width:this.$el.width()-16+"px",top:this.$el.height()-8+"px"}).show(),this.$el.height(this.$el.height()-8+this.$text.height()+16),this.$text_content.val("").trigger("keyup")):(this.$el.height(this.height),this.$text.hide())},_refreshInfo:function(){var e=this.model.get("info");e?this.$info_text.html("Failed: "+e).show():this.$info_text.hide()},_refreshPercentage:function(){var e=parseInt(this.model.get("percentage"));0!=e?this.$progress_bar.css({width:e+"%"}):(this.$progress_bar.addClass("no-transition"),this.$progress_bar.css({width:"0%"}),this.$progress_bar[0].offsetHeight,this.$progress_bar.removeClass("no-transition")),this.$percentage.html(100!=e?e+"%":"Adding to history...")},_refreshStatus:function(){var e=this.model.get("status");this.$status.removeClass().addClass(this.status_classes[e]),this.model.set("enabled","running"!=e),this.$text_content.attr("disabled",!this.model.get("enabled")),this.$el.removeClass("success danger warning"),"running"!=e&&"ready"!=e||this.model.set("percentage",0),this.$source.find(".button")["running"==e?"addClass":"removeClass"]("disabled"),"success"==e&&(this.$el.addClass("success"),this.model.set("percentage",100),this.$percentage.html("100%")),"error"==e?(this.$el.addClass("danger"),this.model.set("percentage",0),this.$info_progress.hide(),this.$info_text.show()):(this.$info_progress.show(),this.$info_text.hide())},_refreshFileName:function(){this.$file_name.html(this.model.get("file_name")||"-")},_refreshFileSize:function(){this.$file_size.html(l.default.bytesToString(this.model.get("file_size")))},_showFtp:function(){if(this.ftp.visible)this.ftp.hide();else{var e=this;this.ftp.empty(),this.ftp.append(new u.default({ftp_upload_site:this.app.ftp_upload_site,onchange:function(t){e.ftp.hide(),"running"!=e.model.get("status")&&t&&(e.model.reset({file_mode:"ftp",file_name:t.path,file_size:t.size,file_path:t.path}),e._refreshReady())}}).$el),this.ftp.show()}},_showSettings:function(){this.settings.visible?this.settings.hide():(this.settings.empty(),this.settings.append(new d.default(this).$el),this.settings.show())},_template:function(){return'
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(16)),r=a(l),d=i(148),c=a(d),u=i(32),h=a(u),f=i(33),p=a(f),m=i(10),g=a(m),_=i(13),v=a(_),w=i(6),y=a(w),b=i(35);a(b);i(34),t.default=e.View.extend({upload_size:0,collection:new r.default.Collection,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(e){var t=this;this.app=e,this.options=e.options,this.list_extensions=e.list_extensions,this.list_genomes=e.list_genomes,this.ui_button=e.ui_button,this.ftp_upload_site=e.currentFtp(),this.setElement(this._template()),this.btnLocal=new y.default.Button({id:"btn-local",title:"Choose local files",onclick:function(){t.uploadbox.select()},icon:"fa fa-laptop"}),this.btnFtp=new y.default.Button({id:"btn-ftp",title:"Choose FTP files",onclick:function(){t._eventFtp()},icon:"fa fa-folder-open-o"}),this.btnCreate=new y.default.Button({id:"btn-new",title:"Paste/Fetch data",onclick:function(){t._eventCreate()},icon:"fa fa-edit"}),this.btnStart=new y.default.Button({id:"btn-start",title:"Start",onclick:function(){t._eventStart()}}),this.btnBuild=new y.default.Button({id:"btn-build",title:"Build",onclick:function(){t._eventBuild()}}),this.btnStop=new y.default.Button({id:"btn-stop",title:"Pause",onclick:function(){t._eventStop()}}),this.btnReset=new y.default.Button({id:"btn-reset",title:"Reset",onclick:function(){t._eventReset()}}),this.btnClose=new y.default.Button({id:"btn-close",title:"Close",onclick:function(){t.app.modal.hide()}}),n.each([this.btnLocal,this.btnFtp,this.btnCreate,this.btnStop,this.btnReset,this.btnStart,this.btnBuild,this.btnClose],function(e){t.$(".upload-buttons").prepend(e.$el)}),this.uploadbox=this.$(".upload-box").uploadbox({url:this.app.options.nginx_upload_path,announce:function(e,i){t._eventAnnounce(e,i)},initialize:function(e){return t.app.toData([t.collection.get(e)],t.history_id)},progress:function(e,i){t._eventProgress(e,i)},success:function(e,i){t._eventSuccess(e,i)},error:function(e,i){t._eventError(e,i)},complete:function(){t._eventComplete()},ondragover:function(){t.$(".upload-box").addClass("highlight")},ondragleave:function(){t.$(".upload-box").removeClass("highlight")}}),this.ftp=new g.default.View({title:"FTP files",container:this.btnFtp.$el}),this.select_extension=new v.default.View({css:"upload-footer-selection-compressed",container:this.$(".upload-footer-extension"),data:n.filter(this.list_extensions,function(e){return!e.composite_files}),value:this.options.default_extension,onchange:function(e){t.updateExtension(e)}}),this.collectionType="list",this.select_collection=new v.default.View({css:"upload-footer-selection-compressed",container:this.$(".upload-footer-collection-type"),data:[{id:"list",text:"List"},{id:"paired",text:"Paired"},{id:"list:paired",text:"List of Pairs"}],value:"list",onchange:function(e){t.updateCollectionType(e)}}),this.$(".upload-footer-extension-info").on("click",function(e){new p.default({$el:s(e.target),title:t.select_extension.text(),extension:t.select_extension.value(),list:t.list_extensions,placement:"top"})}).on("mousedown",function(e){e.preventDefault()}),this.select_genome=new v.default.View({css:"upload-footer-selection",container:this.$(".upload-footer-genome"),data:this.list_genomes,value:this.options.default_genome,onchange:function(e){t.updateGenome(e)}}),this.collection.on("remove",function(e){t._eventRemove(e)}),this._updateScreen()},_eventAnnounce:function(e,t){this.counter.announce++;var i=new r.default.Model({id:e,file_name:t.name,file_size:t.size,file_mode:t.mode||"local",file_path:t.path,file_data:t,extension:this.select_extension.value(),genome:this.select_genome.value()});this.collection.add(i);var n=new c.default(this,{model:i});this.$(".upload-table > tbody:first").append(n.$el),this._updateScreen(),n.render()},_eventProgress:function(e,t){var i=this.collection.get(e);i.set("percentage",t),this.ui_button.model.set("percentage",this._uploadPercentage(t,i.get("file_size")))},_eventSuccess:function(e,t){var i=n.pluck(t.outputs,"hid"),s=this.collection.get(e);s.set({percentage:100,status:"success",hids:i}),this.ui_button.model.set("percentage",this._uploadPercentage(100,s.get("file_size"))),this.upload_completed+=100*s.get("file_size"),this.counter.announce--,this.counter.success++,this._updateScreen(),Galaxy.currHistoryPanel.refreshContents()},_eventError:function(e,t){var i=this.collection.get(e);i.set({percentage:100,status:"error",info:t}),this.ui_button.model.set({percentage:this._uploadPercentage(100,i.get("file_size")),status:"danger"}),this.upload_completed+=100*i.get("file_size"),this.counter.announce--,this.counter.error++,this._updateScreen()},_eventComplete:function(){this.collection.each(function(e){"queued"==e.get("status")&&e.set("status","init")}),this.counter.running=0,this._updateScreen()},_eventBuild:function(){var e=[];n.forEach(this.collection.models,function(t){e.push.apply(e,t.get("hids"))});var t=n.map(e,function(e){return Galaxy.currHistoryPanel.collection.getByHid(e)}),i=new Galaxy.currHistoryPanel.collection.constructor(t);i.historyId=Galaxy.currHistoryPanel.collection.historyId,Galaxy.currHistoryPanel.buildCollection(this.collectionType,i,!0),this.counter.running=0,this._updateScreen(),this._eventReset(),this.app.modal.hide()},_eventRemove:function(e){var t=e.get("status");"success"==t?this.counter.success--:"error"==t?this.counter.error--:this.counter.announce--,this.uploadbox.remove(e.id),this._updateScreen()},_eventFtp:function(){if(this.ftp.visible)this.ftp.hide();else{this.ftp.empty();var e=this;this.ftp.append(new h.default({collection:this.collection,ftp_upload_site:this.ftp_upload_site,onadd:function(t){return e.uploadbox.add([{mode:"ftp",name:t.path,size:t.size,path:t.path}])},onremove:function(t){e.collection.remove(t)}}).$el),this.ftp.show()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(!(0==this.counter.announce||this.counter.running>0)){var e=this;this.upload_size=0,this.upload_completed=0,this.collection.each(function(t){"init"==t.get("status")&&(t.set("status","queued"),e.upload_size+=t.get("file_size"))}),this.ui_button.model.set({percentage:0,status:"success"}),this.counter.running=this.counter.announce,this.history_id=this.app.currentHistory(),this.uploadbox.start(),this._updateScreen()}},_eventStop:function(){this.counter.running>0&&(this.ui_button.model.set("status","info"),s(".upload-top-info").html("Queue will pause after completing the current file..."),this.uploadbox.stop())},_eventReset:function(){0==this.counter.running&&(this.collection.reset(),this.counter.reset(),this.uploadbox.reset(),this.select_extension.value(this.options.default_extension),this.select_genome.value(this.options.default_genome),this.ui_button.model.set("percentage",0),this._updateScreen())},updateExtension:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("extension")!=i.options.default_extension&&t||n.set("extension",e)})},updateCollectionType:function(e){this.collectionType=e},updateGenome:function(e,t){var i=this;this.collection.each(function(n){"init"!=n.get("status")||n.get("genome")!=i.options.default_genome&&t||n.set("genome",e)})},_updateScreen:function(){var e="";e=0==this.counter.announce?this.uploadbox.compatible()?" ":"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.":0==this.counter.running?"You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed.":"Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining.",this.$(".upload-top-info").html(e);var t=0==this.counter.running&&this.counter.announce+this.counter.success+this.counter.error>0,i=0==this.counter.running&&this.counter.announce>0,n=0==this.counter.running&&0==this.counter.announce&&this.counter.success>0&&0==this.counter.error,s=0==this.counter.running,a=this.counter.announce+this.counter.success+this.counter.error>0;this.btnReset[t?"enable":"disable"](),this.btnStart[i?"enable":"disable"](),this.btnStart.$el[i?"addClass":"removeClass"]("btn-primary"),this.btnBuild[n?"enable":"disable"](),this.btnBuild.$el[n?"addClass":"removeClass"]("btn-primary"),this.btnStop[this.counter.running>0?"enable":"disable"](),this.btnLocal[s?"enable":"disable"](),this.btnFtp[s?"enable":"disable"](),this.btnCreate[s?"enable":"disable"](),this.btnFtp.$el[this.ftp_upload_site?"show":"hide"](),this.$(".upload-table")[a?"show":"hide"](),this.$(".upload-helper")[a?"hide":"show"]()},_uploadPercentage:function(e,t){return(this.upload_completed+e*t)/this.upload_size},_template:function(){return'
Drop files here
Name
Size
Status
'}})}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(16),d=(a(r),i(31)),c=a(d),u=i(10),h=a(u),f=i(13);a(f);t.default=e.View.extend({status_classes:{init:"upload-icon-button fa fa-trash-o",queued:"upload-icon fa fa-spinner fa-spin",running:"upload-icon fa fa-spinner fa-spin",success:"upload-icon-button fa fa-check",error:"upload-icon-button fa fa-exclamation-triangle"},initialize:function(e,t){var i=this;this.app=e,this.model=t.model,this.setElement(this._template(t.model)),this.$mode=this.$(".upload-mode"),this.$title=this.$(".upload-title-extended"),this.$text=this.$(".upload-text"),this.$size=this.$(".upload-size"),this.$info_text=this.$(".upload-info-text"),this.$info_progress=this.$(".upload-info-progress"),this.$text_content=this.$(".upload-text-content"),this.$symbol=this.$(".upload-symbol"),this.$progress_bar=this.$(".upload-progress-bar"),this.$percentage=this.$(".upload-percentage"),this.settings=new h.default.View({title:"Upload configuration",container:this.$(".upload-settings"),placement:"bottom"});this.app.select_genome.value(),this.app.select_extension.value();this.$symbol.on("click",function(){i._removeRow()}),this.$text_content.on("change input",function(e){i.model.set({url_paste:n(e.target).val(),file_size:n(e.target).val().length})}),this.listenTo(this.model,"change:percentage",function(){i._refreshPercentage()}),this.listenTo(this.model,"change:status",function(){i._refreshStatus()}),this.listenTo(this.model,"change:info",function(){i._refreshInfo()}),this.listenTo(this.model,"change:file_size",function(){i._refreshFileSize()}),this.listenTo(this.model,"remove",function(){i.remove()}),this.app.collection.on("reset",function(){i.remove()})},render:function(){var e=this.model.attributes;this.$title.html(s.escape(e.file_name)),this.$size.html(l.default.bytesToString(e.file_size)),this.$mode.removeClass().addClass("upload-mode").addClass("text-primary"),"new"==e.file_mode?(this.$text.css({width:this.$el.width()-16+"px",top:this.$el.height()-8+"px"}).show(),this.$el.height(this.$el.height()-8+this.$text.height()+16),this.$mode.addClass("fa fa-edit")):"local"==e.file_mode?this.$mode.addClass("fa fa-laptop"):"ftp"==e.file_mode&&this.$mode.addClass("fa fa-folder-open-o")},_refreshInfo:function(){var e=this.model.get("info");e?this.$info_text.html("Failed: "+e).show():this.$info_text.hide()},_refreshPercentage:function(){var e=parseInt(this.model.get("percentage"));this.$progress_bar.css({width:e+"%"}),this.$percentage.html(100!=e?e+"%":"Adding to history...")},_refreshStatus:function(){var e=this.model.get("status");this.$symbol.removeClass().addClass("upload-symbol").addClass(this.status_classes[e]),this.model.set("enabled","init"==e);var t=this.model.get("enabled");this.$text_content.attr("disabled",!t),"success"==e&&(this.$el.addClass("success"),this.$percentage.html("100%")),"error"==e&&(this.$el.addClass("danger"),this.$info_progress.hide())},_refreshFileSize:function(){this.$size.html(l.default.bytesToString(this.model.get("file_size")))},_removeRow:function(){-1!==["init","success","error"].indexOf(this.model.get("status"))&&this.app.collection.remove(this.model)},_showSettings:function(){this.settings.visible?this.settings.hide():(this.settings.empty(),this.settings.append(new c.default(this).$el),this.settings.show())},_template:function(e){return'
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
'}})}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={tool:"fa-wrench",data_input:"fa-file-o",data_collection_input:"fa-folder-o",subworkflow:"fa-sitemap fa-rotate-270",pause:"fa-pause"}},function(e,t,i){"use strict";(function(e){function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var s=i(6),a=n(s),o=i(151),l=n(o),r=i(152),d=n(r),c=i(4),u=n(c),h=e.View.extend({initialize:function(t,i){var n=this;this.userIsAnonymous=Galaxy.user.isAnonymous(),this.allow_user_dataset_purge=i.config.allow_user_dataset_purge,this.root=i.root,this.historyView=new d.default.CurrentHistoryView({className:d.default.CurrentHistoryView.prototype.className+" middle",purgeAllowed:this.allow_user_dataset_purge,linkTarget:"galaxy_main"}),Galaxy.currHistoryPanel=this.historyView,Galaxy.currHistoryPanel.listenToGalaxy(Galaxy),this.buttonRefresh=new a.default.ButtonLink({id:"history-refresh-button",title:"Refresh history",cls:"panel-header-button",icon:"fa fa-refresh",onclick:function(){n.historyView.loadCurrentHistory()}}),this.buttonOptions=new a.default.ButtonLink({id:"history-options-button",title:"History options",cls:"panel-header-button",target:"galaxy_main",icon:"fa fa-cog",href:this.root+"root/history_options"}),this.buttonViewMulti=new a.default.ButtonLink({id:"history-view-multi-button",title:"View all histories",cls:"panel-header-button",icon:"fa fa-columns",href:this.root+"history/view_multiple"}),this.model=new e.Model({cls:"history-right-panel",title:(0,u.default)("History"),buttons:[this.buttonRefresh,this.buttonOptions,this.buttonViewMulti]}),this.setElement(this._template()),this.historyView.setElement(this.$el),this.historyView.connectToQuotaMeter(Galaxy.quotaMeter),this.historyView.loadCurrentHistory(),Galaxy.listenTo(this.historyView,"history-size-change",function(){Galaxy.user.fetch({url:Galaxy.user.urlRoot()+"/"+(Galaxy.user.id||"current")})})},render:function(){this.optionsMenu=(0,l.default)(this.buttonOptions.$el,{anonymous:this.userIsAnonymous,purgeAllowed:this.allow_user_dataset_purge,root:this.root}),this.buttonViewMulti.$el[this.userIsAnonymous?"hide":"show"]()},_template:function(e){return[''].join("")},toString:function(){return"historyPanel"}});t.default=h}).call(t,i(2))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}function a(e,t,i){return n.clone(m).filter(function(n){return!(e&&!n.anon)&&(!(!t&&n.purge)&&(n.href&&(n.href=i+n.href,n.target=n.target||"galaxy_main"),n.confirm&&(n.func=function(){confirm(n.confirm)&&(galaxy_main.location=n.href)}),!0))})}Object.defineProperty(t,"__esModule",{value:!0});var o=i(27),l=s(o),r=i(78),d=s(r),c=i(5),u=(s(c),i(4)),h=s(u),f=i(17),p=s(f),m=[{html:(0,h.default)("History Lists"),header:!0},{html:(0,h.default)("Saved Histories"),href:"histories/list",target:"_top"},{html:(0,h.default)("Histories Shared with Me"),href:"histories/list_shared",target:"_top"},{html:(0,h.default)("Current History"),header:!0,anon:!0},{html:(0,h.default)("Create New"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.createNewHistory()}},{html:(0,h.default)("Copy History"),func:function(){(0,d.default)(Galaxy.currHistoryPanel.model).done(function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Share or Publish"),href:"history/sharing"},{html:(0,h.default)("Show Structure"),href:"history/display_structured",anon:!0},{html:(0,h.default)("Extract Workflow"),href:"workflow/build_from_current_history"},{html:(0,h.default)("Delete"),anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really delete the current history?"))&&Galaxy.currHistoryPanel.model._delete().done(function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Delete Permanently"),purge:!0,anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really delete the current history permanently? This cannot be undone."))&&Galaxy.currHistoryPanel.model.purge().done(function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Dataset Actions"),header:!0,anon:!0},{html:(0,h.default)("Copy Datasets"),href:"dataset/copy_datasets"},{html:(0,h.default)("Dataset Security"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.router&&Galaxy.router.push("/histories/permissions?id="+Galaxy.currHistoryPanel.model.id)}},{html:(0,h.default)("Resume Paused Jobs"),href:"history/resume_paused_jobs?current=True",anon:!0},{html:(0,h.default)("Collapse Expanded Datasets"),func:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.collapseAll()}},{html:(0,h.default)("Unhide Hidden Datasets"),anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really unhide all hidden datasets?"))&&e.post(Galaxy.root+"history/adjust_hidden",{user_action:"unhide"},function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Delete Hidden Datasets"),anon:!0,func:function(){Galaxy&&Galaxy.currHistoryPanel&&confirm((0,h.default)("Really delete all hidden datasets?"))&&e.post(Galaxy.root+"history/adjust_hidden",{user_action:"delete"},function(){Galaxy.currHistoryPanel.loadCurrentHistory()})}},{html:(0,h.default)("Purge Deleted Datasets"),confirm:(0,h.default)("Really delete all deleted datasets permanently? This cannot be undone."),href:"history/purge_deleted_datasets",purge:!0,anon:!0},{html:(0,h.default)("Downloads"),header:!0},{html:(0,h.default)("Export Tool Citations"),href:"history/citations",anon:!0},{html:(0,h.default)("Export History to File"),href:"history/export_archive?preview=True",anon:!0},{html:(0,h.default)("Other Actions"),header:!0},{html:(0,h.default)("Import from File"),href:"history/import_archive"}];p.default.add({url:"api/webhooks/history-menu/all",async:!1,callback:function(t){var i=[];e.each(t.models,function(e,t){var n=t.toJSON();n.activate&&i.push({html:(0,h.default)(n.config.title),anon:!0})}),i.length>0&&(i.unshift({html:(0,h.default)("Webhooks"),header:!0}),e.merge(m,i))}});var g=function(e,t){t=t||{};var i=void 0===t.anonymous||t.anonymous,n=t.purgeAllowed||!1,s=a(i,n,Galaxy.root);return new l.default(e,s)};t.default=g}).call(t,i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(38),l=(a(o),i(154)),r=a(l),d=i(5),c=a(d),u=i(4),h=a(u),f=c.default.SessionStorageModel.extend({defaults:{tagsEditorShown:!1,annotationEditorShown:!1,scrollPosition:0},toString:function(){return"HistoryViewPrefs("+JSON.stringify(this.toJSON())+")"}});f.storageKey=function(){return"history-panel"};var p=r.default.HistoryViewEdit,m=p.extend({className:p.prototype.className+" current-history-panel",HDCAViewClass:p.prototype.HDCAViewClass.extend({foldoutStyle:"drilldown"}),emptyMsg:[(0,h.default)("This history is empty"),". ",(0,h.default)("You can "),'',(0,h.default)("load your own data"),"",(0,h.default)(" or "),'',(0,h.default)("get data from an external source"),""].join(""),initialize:function(t){t=t||{},this.preferences=new f(e.extend({id:f.storageKey()},e.pick(t,e.keys(f.prototype.defaults)))),p.prototype.initialize.call(this,t),this.panelStack=[],this.currentContentId=t.currentContentId||null},_setUpListeners:function(){p.prototype._setUpListeners.call(this);var e=this;this.on("new-model",function(){e.preferences.set("scrollPosition",0)})},loadCurrentHistory:function(){return this.loadHistory(null,{url:Galaxy.root+"history/current_history_json"})},switchToHistory:function(e,t){return Galaxy.user.isAnonymous()?(this.trigger("error",(0,h.default)("You must be logged in to switch histories"),(0,h.default)("Anonymous user")),n.when()):this.loadHistory(e,{url:Galaxy.root+"history/set_as_current?id="+e})},createNewHistory:function(e){return Galaxy.user.isAnonymous()?(this.trigger("error",(0,h.default)("You must be logged in to create histories"),(0,h.default)("Anonymous user")),n.when()):this.loadHistory(null,{url:Galaxy.root+"history/create_new_current"})},setModel:function(e,t,i){return p.prototype.setModel.call(this,e,t,i),this.model&&this.model.id&&(this.log("checking for updates"),this.model.checkForUpdates()),this},_setUpModelListeners:function(){return p.prototype._setUpModelListeners.call(this),this.listenTo(this.model,{"change:nice_size change:size":function(){this.trigger("history-size-change",this,this.model,arguments)},"change:id":function(){this.once("loading-done",function(){this.model.checkForUpdates()})}})},_setUpCollectionListeners:function(){p.prototype._setUpCollectionListeners.call(this),this.listenTo(this.collection,"state:ready",function(e,t,i){e.get("visible")||this.collection.storage.includeHidden()||this.removeItemView(e)})},_setUpBehaviors:function(t){t=t||this.$el;var i=this;return p.prototype._setUpBehaviors.call(i,t),this._debouncedScrollCaptureHandler||(this._debouncedScrollCaptureHandler=e.debounce(function(){i.$el.is(":visible")&&i.preferences.set("scrollPosition",n(this).scrollTop())},40)),i.$scrollContainer(t).off("scroll",this._debouncedScrollCaptureHandler).on("scroll",this._debouncedScrollCaptureHandler),i},_buildNewRender:function(){if(!this.model)return n();var e=p.prototype._buildNewRender.call(this);return e.find(".search").prependTo(e.find("> .controls")),this._renderQuotaMessage(e),e},_renderQuotaMessage:function(e){return e=e||this.$el,n(this.templates.quotaMsg({},this)).prependTo(e.find(".messages"))},_renderTags:function(e){var t=this;p.prototype._renderTags.call(t,e),t.preferences.get("tagsEditorShown")&&t.tagsEditor.toggle(!0),t.listenTo(t.tagsEditor,"hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(e){t.preferences.set("tagsEditorShown",e.hidden)})},_renderAnnotation:function(e){var t=this;p.prototype._renderAnnotation.call(t,e),t.preferences.get("annotationEditorShown")&&t.annotationEditor.toggle(!0),t.listenTo(t.annotationEditor,"hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(e){t.preferences.set("annotationEditorShown",e.hidden)})},_swapNewRender:function(t){p.prototype._swapNewRender.call(this,t);var i=this;return e.delay(function(){var e=i.preferences.get("scrollPosition");e&&i.scrollTo(e,0)},10),this},_attachItems:function(e){p.prototype._attachItems.call(this,e);var t=this;return t.currentContentId&&t._setCurrentContentById(t.currentContentId),this},addItemView:function(e,t,i){var n=p.prototype.addItemView.call(this,e,t,i);return n&&this.panelStack.length?this._collapseDrilldownPanel():n},_setUpItemViewListeners:function(e){var t=this;return p.prototype._setUpItemViewListeners.call(t,e),t.listenTo(e,{"expanded:drilldown":function(e,t){this._expandDrilldownPanel(t)},"collapsed:drilldown":function(e,t){this._collapseDrilldownPanel(t)}})},setCurrentContent:function(e){this.$(".history-content.current-content").removeClass("current-content"),e?(e.$el.addClass("current-content"),this.currentContentId=e.model.id):this.currentContentId=null},_setCurrentContentById:function(e){var t=this.viewFromModelId(e)||null;this.setCurrentContent(t)},_expandDrilldownPanel:function(e){this.panelStack.push(e),this.$controls().add(this.$list()).hide(),e.parentName=this.model.get("name"),e.delegateEvents().render().$el.appendTo(this.$el)},_collapseDrilldownPanel:function(e){this.panelStack.pop(),this.$controls().add(this.$list()).show()},events:e.extend(e.clone(p.prototype.events),{"click .uploader-link":function(e){Galaxy.upload.show(e)},"click .get-data-link":function(e){var t=n(".toolMenuContainer");t.parent().scrollTop(0),t.find('span:contains("Get Data")').click()}}),listenToGalaxy:function(t){this.listenTo(t,{"center-frame:load":function(t){var i=t.fullpath,n=null,s={display:/datasets\/([a-f0-9]+)\/display/,edit:/datasets\/([a-f0-9]+)\/edit/,report_error:/dataset\/errors\?id=([a-f0-9]+)/,rerun:/tool_runner\/rerun\?id=([a-f0-9]+)/,show_params:/datasets\/([a-f0-9]+)\/show_params/};e.find(s,function(t,s){return n=e.result(i.match(t),1)}),this._setCurrentContentById(n?"dataset-"+n:null)},"center-panel:load":function(e){this._setCurrentContentById()}})},connectToQuotaMeter:function(e){return e?(this.listenTo(e,"quota:over",this.showQuotaMessage),this.listenTo(e,"quota:under",this.hideQuotaMessage),this.on("rendered rendered:initial",function(){e&&e.isOverQuota()&&this.showQuotaMessage()}),this):this},clearMessages:function(t){var i=e.isUndefined(t)?this.$messages().children('[class$="message"]'):n(t.currentTarget);return i=i.not(".quota-message"),i.fadeOut(this.fxSpeed,function(){n(this).remove()}),this},showQuotaMessage:function(){var e=this.$(".quota-message");e.is(":hidden")&&e.slideDown(this.fxSpeed)},hideQuotaMessage:function(){var e=this.$(".quota-message");e.is(":hidden")||e.slideUp(this.fxSpeed)},unhideHidden:function(){var e=this;return confirm((0,h.default)("Really unhide all hidden datasets?"))?e.model.contents._filterAndUpdate({visible:!1,deleted:"",purged:""},{visible:!0}).done(function(){e.model.contents.includeHidden||e.renderItems()}):s.when()},deleteHidden:function(){var e=this;return confirm((0,h.default)("Really delete all hidden datasets?"))?e.model.contents._filterAndUpdate({visible:!1,deleted:"",purged:""},{deleted:!0,visible:!0}):s.when()},toString:function(){return"CurrentHistoryView("+(this.model?this.model.get("name"):"")+")"}});m.prototype.templates=function(){var t=c.default.wrapTemplate(['
',(0,h.default)("You are over your disk quota"),". ",(0,h.default)("Tool execution is on hold until your disk usage drops below your allocated quota"),".","
"],"history");return e.extend(e.clone(p.prototype.templates),{quotaMsg:t})}(),t.default={CurrentHistoryView:m}}).call(t,i(1),i(0),i(0))},function(e,t,i){"use strict";(function(e){function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function n(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function s(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var a=function e(t,i,n){null===t&&(t=Function.prototype);var s=Object.getOwnPropertyDescriptor(t,i);if(void 0===s){var a=Object.getPrototypeOf(t);return null===a?void 0:e(a,i,n)}if("value"in s)return s.value;var o=s.get;if(void 0!==o)return o.call(n)},o=function(){function e(e,t){for(var i=0;i .controls .deleted-count").html(""+(0,M.default)("loading...")+"")},"fetching-hidden":function(e){this.$("> .controls .hidden-count").html(""+(0,M.default)("loading...")+"")},"fetching-deleted-done fetching-hidden-done":this._renderCounts}),this},_buildNewRender:function(){var e=I.prototype._buildNewRender.call(this);return this.model?(Galaxy&&Galaxy.user&&Galaxy.user.id&&Galaxy.user.id===this.model.get("user_id")&&(this._renderTags(e),this._renderAnnotation(e)),e):e},updateHistoryDiskSize:function(){this.$(".history-size").text(this.model.get("nice_size"))},renderItems:function(e){var t=I.prototype.renderItems.call(this,e);return this.searchFor?this._renderSearchFindings(e):this._renderCounts(e),t},_renderCounts:function(t){t=t instanceof e?t:this.$el;var i=this.templates.counts(this.model.toJSON(),this);return t.find("> .controls .subtitle").html(i)},_renderTags:function(e){var t=this;this.tagsEditor=new _.default.TagsEditor({model:this.model,el:e.find(".controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.toggleHDATagEditors(!0,t.fxSpeed)},onhide:function(){t.toggleHDATagEditors(!1,t.fxSpeed)},$activator:(0,T.default)({title:(0,M.default)("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".controls .actions"))})},_renderAnnotation:function(e){var t=this;this.annotationEditor=new w.default.AnnotationEditor({model:this.model,el:e.find(".controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){t.toggleHDAAnnotationEditors(!0,t.fxSpeed)},onhide:function(){t.toggleHDAAnnotationEditors(!1,t.fxSpeed)},$activator:(0,T.default)({title:(0,M.default)("Edit history annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".controls .actions"))})},_setUpBehaviors:function(e){if(e=e||this.$el,I.prototype._setUpBehaviors.call(this,e),this.model&&Galaxy.user&&!Galaxy.user.isAnonymous()&&Galaxy.user.id===this.model.get("user_id")){var t=this;e.find("> .controls .name").attr("title",(0,M.default)("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(e){var i=t.model.get("name");e&&e!==i?(t.$el.find("> .controls .name").text(e),t.model.save({name:e}).fail(function(){t.$el.find("> .controls .name").text(t.model.previous("name"))})):t.$el.find("> .controls .name").text(i)}})}},multiselectActions:function(){var e=this,t=[{html:(0,M.default)("Hide datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.hide;e.getSelectedModels().ajaxQueue(t)}},{html:(0,M.default)("Unhide datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.unhide;e.getSelectedModels().ajaxQueue(t)}},{html:(0,M.default)("Delete datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.delete;e.getSelectedModels().ajaxQueue(t)}},{html:(0,M.default)("Undelete datasets"),func:function(){var t=u.default.HistoryDatasetAssociation.prototype.undelete;e.getSelectedModels().ajaxQueue(t)}}];return e.purgeAllowed&&t.push({html:(0,M.default)("Permanently delete datasets"),func:function(){if(confirm((0,M.default)("This will permanently remove the data in your datasets. Are you sure?"))){var t=u.default.HistoryDatasetAssociation.prototype.purge;e.getSelectedModels().ajaxQueue(t)}}}),t=t.concat(e._collectionActions())},_collectionActions:function(){var e=this;return[{html:(0,M.default)("Build Dataset List"),func:function(){e.buildCollection("list")}},{html:(0,M.default)("Build Dataset Pair"),func:function(){e.buildCollection("paired")}},{html:(0,M.default)("Build List of Dataset Pairs"),func:function(){e.buildCollection("list:paired")}}]},buildCollection:function(e,t,i){var n,s=this,t=t||s.getSelectedModels(),i=i||!1;"list"==e?n=b.default.createListCollection:"paired"==e?n=C.default.createPairCollection:"list:paired"==e?n=k.default.createListOfPairsCollection:console.warn("Unknown collectionType encountered "+e),n(t,i).done(function(){s.model.refresh()})},_getItemViewOptions:function(e){var t=I.prototype._getItemViewOptions.call(this,e);return n.extend(t,{purgeAllowed:this.purgeAllowed,tagsEditorShown:this.tagsEditor&&!this.tagsEditor.hidden,annotationEditorShown:this.annotationEditor&&!this.annotationEditor.hidden}),t},_handleItemDeletedChange:function(e){e.get("deleted")?this._handleItemDeletion(e):this._handleItemUndeletion(e),this._renderCounts()},_handleItemDeletion:function(e){var t=this.model.get("contents_active");t.deleted+=1,t.active-=1,this.model.contents.includeDeleted||this.removeItemView(e),this.model.set("contents_active",t)},_handleItemUndeletion:function(e){var t=this.model.get("contents_active");t.deleted-=1,this.model.contents.includeDeleted||(t.active-=1),this.model.set("contents_active",t)},_handleItemVisibleChange:function(e){e.hidden()?this._handleItemHidden(e):this._handleItemUnhidden(e),this._renderCounts()},_handleItemHidden:function(e){var t=this.model.get("contents_active");t.hidden+=1,t.active-=1,this.model.contents.includeHidden||this.removeItemView(e),this.model.set("contents_active",t)},_handleItemUnhidden:function(e){var t=this.model.get("contents_active");t.hidden-=1,this.model.contents.includeHidden||(t.active-=1),this.model.set("contents_active",t)},toggleHDATagEditors:function(e,t){n.each(this.views,function(i){i.tagsEditor&&i.tagsEditor.toggle(e,t)})},toggleHDAAnnotationEditors:function(e,t){n.each(this.views,function(i){i.annotationEditor&&i.annotationEditor.toggle(e,t)})},events:n.extend(n.clone(I.prototype.events),{"click .show-selectors-btn":"toggleSelectors","click .toggle-deleted-link":function(e){this.toggleShowDeleted()},"click .toggle-hidden-link":function(e){this.toggleShowHidden()}}),_renderSearchProgress:function(e,t){var i=e+t;return this.$("> .controls .subtitle").html(["",(0,M.default)("Searching "),i,"/",this.model.contentsShown(),""].join(""))},_renderSearchFindings:function(t){t=t instanceof e?t:this.$el;var i=this.templates.found(this.model.toJSON(),this);return t.find("> .controls .subtitle").html(i),this},dropTargetOn:function(){if(this.dropTarget)return this;this.dropTarget=!0;var e={dragenter:n.bind(this.dragenter,this),dragover:n.bind(this.dragover,this),dragleave:n.bind(this.dragleave,this),drop:n.bind(this.drop,this)},t=this._renderDropTarget();this.$list().before([this._renderDropTargetHelp(),t]);for(var i in e)e.hasOwnProperty(i)&&t.on(i,e[i]);return this},_renderDropTarget:function(){return this.$(".history-drop-target").remove(),s("").addClass("history-drop-target")},_renderDropTargetHelp:function(){return this.$(".history-drop-target-help").remove(),s("").addClass("history-drop-target-help").text((0,M.default)("Drag datasets here to copy them to the current history"))},dropTargetOff:function(){if(!this.dropTarget)return this;this.dropTarget=!1;var e=this.$(".history-drop-target").get(0);for(var t in this._dropHandlers)this._dropHandlers.hasOwnProperty(t)&&e.off(t,this._dropHandlers[t]);return this.$(".history-drop-target").remove(),this.$(".history-drop-target-help").remove(),this},dropTargetToggle:function(){return this.dropTarget?this.dropTargetOff():this.dropTargetOn(),this},dragenter:function(e){e.preventDefault(),e.stopPropagation(),this.$(".history-drop-target").css("border","2px solid black")},dragover:function(e){e.preventDefault(),e.stopPropagation()},dragleave:function(e){e.preventDefault(),e.stopPropagation(),this.$(".history-drop-target").css("border","1px dashed black")},drop:function(e){e.preventDefault();var t=this,i=e.originalEvent.dataTransfer,n=i.getData("text");i.dropEffect="move";try{n=JSON.parse(n)}catch(e){t.warn("error parsing JSON from drop:",n)}return t.trigger("droptarget:drop",e,n,t),!1},dataDropped:function(t){var i=this;return n.isObject(t)&&"HistoryDatasetAssociation"===t.model_class&&t.id?0!==i.contents.currentPage?i.contents.fetchPage(0).then(function(){return i.model.contents.copy(t.id)}):i.model.contents.copy(t.id):e.when()},toString:function(){return"HistoryViewEdit("+(this.model?this.model.get("name"):"")+")"}});L.prototype.templates=function(){var e=P.default.wrapTemplate(["<% var shown = Math.max( view.views.length, history.contents_active.active ) %>","<% if( shown ){ %>",'',"<%- shown %> ",(0,M.default)("shown"),"","<% } %>","<% if( history.contents_active.deleted ){ %>",'',"<% if( view.model.contents.includeDeleted ){ %>",'',(0,M.default)("hide deleted"),"","<% } else { %>","<%- history.contents_active.deleted %> ",'',(0,M.default)("deleted"),"","<% } %>","","<% } %>","<% if( history.contents_active.hidden ){ %>",'',"<% if( view.model.contents.includeHidden ){ %>",'',(0,M.default)("hide hidden"),"","<% } else { %>","<%- history.contents_active.hidden %> ",'',(0,M.default)("hidden"),"","<% } %>","","<% } %>"],"history"),t=P.default.wrapTemplate([(0,M.default)("Found")," <%- view.views.length %>, ","<% if( history.contents_active.deleted ){ %>","<% if( view.model.contents.includeDeleted ){ %>",'',(0,M.default)("hide deleted"),", ","<% } else { %>",'',(0,M.default)("show deleted"),", ","<% } %>","<% } %>","<% if( history.contents_active.hidden ){ %>","<% if( view.model.contents.includeHidden ){ %>",'',(0,M.default)("hide hidden"),"","<% } else { %>",'',(0,M.default)("show hidden"),"","<% } %>","<% } %>"],"history");return n.extend(n.clone(I.prototype.templates),{counts:e,found:t})}(),t.default={HistoryViewEdit:L}}).call(t,i(0),i(1),i(0))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(82),o=s(a),l=i(38),r=s(l),d=i(39),c=s(d),u=i(40),h=(s(u),i(84)),f=s(h),p=i(86),m=s(p),g=i(59),_=(s(g),i(79)),v=s(_),w=i(14),y=s(w),b=i(5),x=s(b),C=i(4),$=s(C);i(83);var k=o.default.ModelListPanel,S=k.extend({_logNamespace:"history",HDAViewClass:f.default.HDAListItemView,HDCAViewClass:m.default.HDCAListItemView,collectionClass:c.default.HistoryContents,modelCollectionKey:"contents",tagName:"div",className:k.prototype.className+" history-panel",emptyMsg:(0,$.default)("This history is empty"),noneFoundMsg:(0,$.default)("No matching datasets found"),searchPlaceholder:(0,$.default)("search datasets"),FETCH_COLLECTION_COUNTS_DELAY:2e3,initialize:function(e){k.prototype.initialize.call(this,e),this.linkTarget=e.linkTarget||"_blank",this.detailedFetchTimeoutId=null},_createDefaultCollection:function(){return new this.collectionClass([],{history:this.model})},freeModel:function(){return k.prototype.freeModel.call(this),this.model&&this.model.clearUpdateTimeout(),this._clearDetailedFetchTimeout(),this},_clearDetailedFetchTimeout:function(){this.detailedFetchTimeoutId&&(clearTimeout(this.detailedFetchTimeoutId),this.detailedFetchTimeoutId=null)},_setUpListeners:function(){var t=this;k.prototype._setUpListeners.call(this),this.on({error:function(e,t,i,n,s){this.errorHandler(e,t,i,n,s)},"loading-done":function(){t.detailedFetchTimeoutId=e.delay(function(){t.detailedFetchTimeoutId=null,t.model.contents.fetchCollectionCounts()},t.FETCH_COLLECTION_COUNTS_DELAY)},"views:ready view:attached view:removed":function(e){this._renderSelectButton()},"view:attached":function(e){this.scrollTo(0)}})},loadHistory:function(t,i,n){var s=this;return n=e.extend(n||{silent:!0}),this.info("loadHistory:",t,i,n),this.setModel(new r.default.History({id:t})),n.silent=!0,this.trigger("loading"),this.model.fetchWithContents(i,n).always(function(){s.render(),s.trigger("loading-done")})},refreshContents:function(e){return this.model?this.model.refresh(e):n.when()},_setUpCollectionListeners:function(){return k.prototype._setUpCollectionListeners.call(this),this.listenTo(this.collection,{"fetching-more":function(){this._toggleContentsLoadingIndicator(!0),this.$emptyMessage().hide()},"fetching-more-done":function(){this._toggleContentsLoadingIndicator(!1)}})},_showLoadingIndicator:function(t,i,s){var a=n('');this.$el.html(a.text(t).slideDown(e.isUndefined(i)?this.fxSpeed:i))},_hideLoadingIndicator:function(t){this.$(".loading-indicator").slideUp(e.isUndefined(t)?this.fxSpeed+200:t,function(){n(this).remove()})},_buildNewRender:function(){var e=k.prototype._buildNewRender.call(this);return this._renderSelectButton(e),e},_renderSelectButton:function(e){if(e=e||this.$el,!this.multiselectActions().length)return null;if(!this.views.length)return this.hideSelectors(),e.find(".controls .actions .show-selectors-btn").remove(),null;var t=e.find(".controls .actions .show-selectors-btn");return t.length?t:(0,y.default)({title:(0,$.default)("Operations on multiple datasets"),classes:"show-selectors-btn",faIcon:"fa-check-square-o"}).prependTo(e.find(".controls .actions"))},_renderEmptyMessage:function(e){var t=this.$emptyMessage(e);return this.model.get("contents_active").active<=0?t.empty().append(this.emptyMsg).show():this.searchFor&&this.model.contents.haveSearchDetails()&&!this.views.length?t.empty().append(this.noneFoundMsg).show():(t.hide(),n())},$scrollContainer:function(e){return this.$list(e)},_toggleContentsLoadingIndicator:function(e){e?this.$list().html('
",(0,p.default)(["Pair collections are permanent collections containing two datasets: one forward and one reverse. ","Often these are forward and reverse reads. The pair collections can be passed to tools and ","workflows in order to have analyses done on both datasets. This interface allows ","you to create a pair, name it, and swap which is forward and which reverse."].join("")),"
","
","
",(0,p.default)(['Click the "Swap" link to make your forward dataset the reverse ',"and the reverse dataset forward."].join("")),"
","
",(0,p.default)(['Click the "Cancel" button to exit the interface.'].join("")),"
","
","
",(0,p.default)(['Once your collection is complete, enter a name and ','click "Create list".'].join("")),"
"].join("")),invalidInitial:n.template(['
','
','',"<% if( _.size( problems ) ){ %>",(0,p.default)("The following selections could not be included due to problems"),"
<% _.each( problems, function( problem ){ %>","
<%- problem.element.name %>: <%- problem.text %>
","<% }); %>
","<% } else if( _.size( elements ) === 0 ){ %>",(0,p.default)("No datasets were selected"),".","<% } else if( _.size( elements ) === 1 ){ %>",(0,p.default)("Only one dataset was selected"),": <%- elements[0].name %>","<% } else if( _.size( elements ) > 2 ){ %>",(0,p.default)("Too many datasets were selected"),': <%- _.pluck( elements, "name" ).join( ", ") %>',"<% } %>"," ",(0,p.default)("Two (and only two) elements are needed for the pair"),". ",(0,p.default)("You may need to "),'',(0,p.default)("cancel")," ",(0,p.default)("and reselect new elements"),".","","
","
",'"].join(""))}),toString:function(){return"PairCollectionCreator"}}),v=function(e,t){return t=t||{},t.title=(0,p.default)("Create a collection from a pair of datasets"),r.default.collectionCreatorModal(e,t,_)};t.default={PairCollectionCreator:_,pairCollectionCreatorModal:v,createPairCollection:o}}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e,n,s,a){function o(e){return e&&e.__esModule?e:{default:e}}function l(e){function t(){return i.length||(i=[new RegExp(this.filters[0]),new RegExp(this.filters[1])]),i}e=e||{},e.createPair=e.createPair||function(e){e=e||{};var t=e.listA.splice(e.indexA,1)[0],i=e.listB.splice(e.indexB,1)[0],n=e.listB.indexOf(t),s=e.listA.indexOf(i);return-1!==n&&e.listB.splice(n,1),-1!==s&&e.listA.splice(s,1),this._pair(t,i,{silent:!0})};var i=[];return e.preprocessMatch=e.preprocessMatch||function(e){var i=t.call(this);return n.extend(e,{matchTo:e.matchTo.name.replace(i[0],""),possible:e.possible.name.replace(i[1],"")})},function(t){this.debug("autopair _strategy ---------------------------"),t=t||{};var i,n=t.listA,s=t.listB,a=0,o={score:0,index:null},l=[];for(this.debug("starting list lens:",n.length,s.length),this.debug("bestMatch (starting):",JSON.stringify(o,null," "));a=c?l.push(e.createPair.call(this,{listA:n,indexA:a,listB:s,indexB:o.index})):a+=1,!n.length||!s.length)return l}return this.debug("paired:",JSON.stringify(l,null," ")),this.debug("autopair _strategy ---------------------------"),l}}function r(e,t){var i=e.toJSON();return b(i,{historyId:e.historyId,defaultHideSourceItems:t})}Object.defineProperty(t,"__esModule",{value:!0});var d=i(163),c=o(d),u=i(75),h=o(u),f=i(74),p=o(f),m=i(5),g=o(m),_=i(4),v=o(_);i(76);var w=e.View.extend(g.default.LoggableMixin).extend({_logNamespace:"collections",tagName:"li",className:"dataset paired",initialize:function(e){this.pair=e.pair||{}},template:n.template(['<%- pair.forward.name %>','','<%- pair.name %>',"",'<%- pair.reverse.name %>'].join("")),render:function(){this.dragStartHandler=n.bind(this._dragstart,this),this.dragEndHandler=n.bind(this._dragend,this);var e=this.$el.attr("draggable",!0).data("pair",this.pair).html(this.template({pair:this.pair})).addClass("flex-column-container").get(0);return e.addEventListener("dragstart",this.dragStartHandler,!1),e.addEventListener("dragend",this.dragEndHandler,!1),this},events:{dragover:"_sendToParent",drop:"_sendToParent"},_dragstart:function(e){e.currentTarget.style.opacity="0.4",e.originalEvent&&(e=e.originalEvent),e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",JSON.stringify(this.pair)),this.$el.parent().trigger("pair.dragstart",[this])},_dragend:function(e){e.currentTarget.style.opacity="1.0",this.$el.parent().trigger("pair.dragend",[this])},_sendToParent:function(e){this.$el.parent().trigger(e)},toString:function(){return"PairView("+this.pair.name+")"}}),y=e.View.extend(g.default.LoggableMixin).extend(p.default.CollectionCreatorMixin).extend({_logNamespace:"collections",className:"list-of-pairs-collection-creator collection-creator flex-row-container",initialize:function(e){this.metric("PairedCollectionCreator.initialize",e),e=n.defaults(e,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:!0,strategy:"lcs",matchPercentage:.9,twoPassAutopairing:!0}),this.initialList=e.datasets,this.historyId=e.historyId,this.filters=this.commonFilters[e.filters]||this.commonFilters[this.DEFAULT_FILTERS],n.isArray(e.filters)&&(this.filters=e.filters),this.automaticallyPair=e.automaticallyPair,this.strategy=this.strategies[e.strategy]||this.strategies[this.DEFAULT_STRATEGY],n.isFunction(e.strategy)&&(this.strategy=e.strategy),this.matchPercentage=e.matchPercentage,this.twoPassAutopairing=e.twoPassAutopairing,this.removeExtensions=!0,this.oncancel=e.oncancel,this.oncreate=e.oncreate,this.autoscrollDist=e.autoscrollDist||24,this.unpairedPanelHidden=!1,this.pairedPanelHidden=!1,this.$dragging=null,this.blocking=!1,this._setUpCommonSettings(e),this._setUpBehaviors(),this._dataSetUp()},commonFilters:{illumina:["_1","_2"],Rs:["_R1","_R2"]},DEFAULT_FILTERS:"illumina",strategies:{simple:"autopairSimple",lcs:"autopairLCS",levenshtein:"autopairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[],this.unpaired=[],this.selectedIds=[],this._sortInitialList(),this._ensureIds(),this.unpaired=this.initialList.slice(0),this.automaticallyPair&&(this.autoPair(),this.once("rendered:initial",function(){this.trigger("autopair")}))},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(e){return e.sort(function(e,t){return(0,h.default)(e.name,t.name)}),e},_ensureIds:function(){return this.initialList.forEach(function(e){e.hasOwnProperty("id")||(e.id=n.uniqueId())}),this.initialList},_splitByFilters:function(){function e(e,t){return t.test(e.name)}var t=this.filters.map(function(e){return new RegExp(e)}),i=[[],[]];return this.unpaired.forEach(function(n){t.forEach(function(t,s){e(n,t)&&i[s].push(n)})}),i},_addToUnpaired:function(e){var t=this;this.unpaired.splice(function i(n,s){if(n===s)return n;var a=Math.floor((s-n)/2)+n,o=(0,h.default)(e.name,t.unpaired[a].name);if(o<0)return i(n,a);if(o>0)return i(a+1,s);for(;t.unpaired[a]&&t.unpaired[a].name===e.name;)a++;return a}(0,this.unpaired.length),0,e)},autoPair:function(e){var t=this._splitByFilters(),i=[];return this.twoPassAutopairing&&(i=this.autopairSimple({listA:t[0],listB:t[1]}),t=this._splitByFilters()),e=e||this.strategy,t=this._splitByFilters(),i=i.concat(this[e].call(this,{listA:t[0],listB:t[1]}))},autopairSimple:l({scoreThreshold:function(){return.6},match:function(e){return e=e||{},e.matchTo===e.possible?{index:e.index,score:1}:e.bestMatch}}),autopairLevenshtein:l({scoreThreshold:function(){return this.matchPercentage},match:function(e){e=e||{};var t=(0,c.default)(e.matchTo,e.possible),i=1-t/Math.max(e.matchTo.length,e.possible.length);return i>e.bestMatch.score?{index:e.index,score:i}:e.bestMatch}}),autopairLCS:l({scoreThreshold:function(){return this.matchPercentage},match:function(e){e=e||{};var t=this._naiveStartingAndEndingLCS(e.matchTo,e.possible).length,i=t/Math.max(e.matchTo.length,e.possible.length);return i>e.bestMatch.score?{index:e.index,score:i}:e.bestMatch}}),_naiveStartingAndEndingLCS:function(e,t){for(var i="",n="",s=0,a=0;s=0&&a>=0&&e[s]===t[a];)n=[e[s],n].join(""),s-=1,a-=1;return i+n},_pair:function(e,t,i){i=i||{},this.debug("_pair:",e,t);var s=this._createPair(e,t,i.name);return this.paired.push(s),this.unpaired=n.without(this.unpaired,e,t),i.silent||this.trigger("pair:new",s),s},_createPair:function(e,t,i){if(!e||!t||e===t)throw new Error("Bad pairing: "+[JSON.stringify(e),JSON.stringify(t)]);return i=i||this._guessNameForPair(e,t),{forward:e,name:i,reverse:t}},_guessNameForPair:function(e,t,i){i=void 0!==i?i:this.removeExtensions;var n=e.name,s=t.name,a=this._naiveStartingAndEndingLCS(n.replace(new RegExp(this.filters[0]),""),s.replace(new RegExp(this.filters[1]),""));if(i){var o=a.lastIndexOf(".");if(o>0){var l=a.slice(o,a.length);a=a.replace(l,""),n=n.replace(l,""),s=s.replace(l,"")}}return a||n+" & "+s},_unpair:function(e,t){if(t=t||{},!e)throw new Error("Bad pair: "+JSON.stringify(e));return this.paired=n.without(this.paired,e),this._addToUnpaired(e.forward),this._addToUnpaired(e.reverse),t.silent||this.trigger("pair:unpair",[e]),e},unpairAll:function(){for(var e=[];this.paired.length;)e.push(this._unpair(this.paired[0],{silent:!0}));this.trigger("pair:unpair",e)},_pairToJSON:function(e,t){return t=t||"hda",{collection_type:"paired",src:"new_collection",name:e.name,element_identifiers:[{name:"forward",id:e.forward.id,src:t},{name:"reverse",id:e.reverse.id,src:t}]}},createList:function(e){var t=this,i=Galaxy.root+"api/histories/"+this.historyId+"/contents/dataset_collections",a={type:"dataset_collection",collection_type:"list:paired",hide_source_items:t.hideOriginals||!1,name:n.escape(e||t.$(".collection-name").val()),element_identifiers:t.paired.map(function(e){return t._pairToJSON(e)})};return t.blocking=!0,s.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(a)}).always(function(){t.blocking=!1}).fail(function(e,i,n){t._ajaxErrHandler(e,i,n)}).done(function(e,i,n){t.trigger("collection:created",e,i,n),t.metric("collection:created",e),"function"==typeof t.oncreate&&t.oncreate.call(this,e,i,n)})},_ajaxErrHandler:function(e,t,i){this.error(e,t,i);var n=this,s=(0,v.default)("An error occurred while creating this collection");e&&(0===e.readyState&&0===e.status?s+=": "+(0,v.default)("Galaxy could not be reached and may be updating.")+(0,v.default)(" Try again in a few minutes."):e.responseJSON?s+="
",(0,v.default)(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"
","
",(0,v.default)(['Unpaired datasets are shown in the unpaired section ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the paired section.',"
To pair datasets, you can:","
Click a dataset in the ",'forward column ',"to select it then click a dataset in the ",'reverse column.',"
",'
Click one of the "Pair these datasets" buttons in the ','middle column ',"to pair the datasets in a particular row.","
",'
Click "Auto-pair" ',"to have your datasets automatically paired based on name.","
","
"].join("")),"","
",(0,v.default)(["
You can filter what is shown in the unpaired sections by:","
Entering partial dataset names in either the ",'forward filter or ','reverse filter.',"
","
Choosing from a list of preset filters by clicking the ",'"Choose filters" link.',"
Clearing the filters by clicking the ",'"Clear filters" link.',"
","
"].join("")),"","
",(0,v.default)(["To unpair individual dataset pairs, click the ",'unpair buttons ( ). ','Click the "Unpair all" link to unpair all pairs.'].join("")),"
","
",(0,v.default)(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','"Remove file extensions from pair names?" control.'].join("")),"
","
",(0,v.default)(['Once your collection is complete, enter a name and ','click "Create list". ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"
"].join(""))})}),b=function(e,t){var i,a=s.Deferred();if(t=n.defaults(t||{},{datasets:e,oncancel:function(){Galaxy.modal.hide(),a.reject("cancelled")},oncreate:function(e,t){Galaxy.modal.hide(),a.resolve(t)}}),!window.Galaxy||!Galaxy.modal)throw new Error("Galaxy or Galaxy.modal not found");return i=new y(t),Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:!0}),i.render(),window.creator=i,a};t.default={PairedCollectionCreator:y,pairedCollectionCreatorModal:b,createListOfPairsCollection:r}}).call(t,i(2),i(1),i(0),i(0))},function(e,t,i){"use strict";function n(e,t){if(0===e.length)return t.length;if(0===t.length)return e.length;var i,n=[];for(i=0;i<=t.length;i++)n[i]=[i];var s;for(s=0;s<=e.length;s++)n[0][s]=s;for(i=1;i<=t.length;i++)for(s=1;s<=e.length;s++)t.charAt(i-1)===e.charAt(s-1)?n[i][s]=n[i-1][s-1]:n[i][s]=Math.min(n[i-1][s-1]+1,Math.min(n[i][s-1]+1,n[i-1][s]+1));return n[t.length][e.length]}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(9),l=(a(o),i(6)),r=a(l),d=i(8),c=a(d),u=e.Model.extend({initialize:function(e){e=e||{},e.user_id=e.user_id||Galaxy.user.id,this.set({user_id:e.user_id,information:{title:"Manage information",description:"Edit your email, addresses and custom parameters or change your username.",url:"api/users/"+e.user_id+"/information/inputs",icon:"fa-user",redirect:"user"},password:{title:"Change password",description:"Allows you to change your login credentials.",icon:"fa-unlock-alt",url:"api/users/"+e.user_id+"/password/inputs",submit_title:"Save password",redirect:"user"},communication:{title:"Change communication settings",description:"Enable or disable the communication feature to chat with other users.",url:"api/users/"+e.user_id+"/communication/inputs",icon:"fa-comments-o",redirect:"user"},permissions:{title:"Set dataset permissions for new histories",description:"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.",url:"api/users/"+e.user_id+"/permissions/inputs",icon:"fa-users",submit_title:"Save permissions",redirect:"user"},api_key:{title:"Manage API key",description:"Access your current API key or create a new one.",url:"api/users/"+e.user_id+"/api_key/inputs",icon:"fa-key",submit_title:"Create a new key",submit_icon:"fa-check"},toolbox_filters:{title:"Manage Toolbox filters",description:"Customize your Toolbox by displaying or omitting sets of Tools.",url:"api/users/"+e.user_id+"/toolbox_filters/inputs",icon:"fa-filter",submit_title:"Save filters",redirect:"user"},openids:{title:"Manage OpenIDs",description:"Associate OpenIDs with your account.",icon:"fa-openid",onclick:function(){window.location.href=Galaxy.root+"user/openid_manage?cntrller=user&use_panels=True"}},custom_builds:{title:"Manage custom builds",description:"Add or remove custom builds using history datasets.",icon:"fa-cubes",onclick:function(){window.location.href=Galaxy.root+"custom_builds"}},logout:{title:"Sign out",description:"Click here to sign out of all sessions.",icon:"fa-sign-out",onclick:function(){Galaxy.modal.show({title:"Sign out",body:"Do you want to continue and sign out of all active sessions?",buttons:{Cancel:function(){Galaxy.modal.hide()},"Sign out":function(){window.location.href=Galaxy.root+"user/logout?session_csrf_token="+Galaxy.session_csrf_token}}})}}})}}),h=e.View.extend({title:"User Preferences",initialize:function(){this.model=new u,this.setElement(""),this.render()},render:function(){var e=this,t=Galaxy.config;n.getJSON(Galaxy.root+"api/users/"+Galaxy.user.id,function(i){e.$preferences=n("").addClass("ui-panel").append(n("").append("User preferences")).append(n("").append("You are logged in as "+s.escape(i.email)+".")).append(e.$table=n("
You are using '+e.nice_total_disk_usage+" of disk space in this Galaxy instance. "+(Galaxy.config.enable_quotas?"Your disk quota is: "+e.quota+". ":"")+'Is your usage more than expected? See the documentation for tips on how to find all of the data in your account.
'}});t.default={View:h,Model:u}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=(s(a),i(6)),l=s(o),r=i(9),d=s(r),c=i(68),u=s(c),h=e.Collection.extend({comparator:function(e,t){return e=e.get("name"),t=t.get("name"),e>t?1:e").append(n("").text("Current Custom Builds")).append(this.table.$el).append(this.$installed=n("").append(n("").text("System Installed Builds").addClass("ui-margin-top")).append(this.installed_builds.$el)).append(n("").text("Add a Custom Build").addClass("ui-margin-top")).append(n("").addClass("ui-column").append(n("").addClass("ui-column-left").append(this.message.$el).append(this.$form=n("").addClass("ui-margin-top"))).append(this.$help=n("").addClass("ui-column-right")))),this.listenTo(this.collection,"add remove reset",function(){i._renderTable()}),this.listenTo(this.model,"change",function(){i._renderForm()}),this.collection.fetch(),this.model.fetch()},render:function(){this._renderTable(),this._renderForm()},_renderTable:function(){var e=this;this.table.delAll(),this.collection.sort(),this.collection.each(function(t){e.table.add(t.get("name")),e.table.add(t.id),e.table.add(void 0!==t.get("count")?t.get("count"):"Processing..."),e.table.add(new l.default.ButtonIcon({icon:"fa-trash-o",cls:"ui-button-icon-plain",tooltip:"Delete custom build.",onclick:function(){t.destroy()}}).$el),e.table.append(t.id)})},_renderForm:function(){var e=this,t=new d.default({inputs:[{type:"text",name:"name",label:"Name",help:"Specify a build name e.g. Hamster."},{type:"text",name:"id",label:"Key",help:"Specify a build key e.g. hamster_v1."},{name:"len",type:"conditional",test_param:{name:"type",label:"Definition",help:"Provide the data source.",type:"select",value:"fasta",data:[{value:"fasta",label:"FASTA-file from history"},{value:"file",label:"Len-file from disk"},{value:"text",label:"Len-file by copy/paste"}]},cases:[{value:"fasta",inputs:[{type:"select",name:"value",label:"FASTA-file",data:this.model.get("fasta_hdas")}]},{value:"file",inputs:[{type:"upload",name:"value",label:"Len-file",data:this.model.get("len_hdas")}]},{value:"text",inputs:[{type:"text",area:!0,name:"value",label:"Edit/Paste"}]}]}],buttons:{save:new l.default.Button({icon:"fa-save",tooltip:"Create new Build",title:"Save",cls:"btn btn-primary ui-clear-float",onclick:function(){var i=t.data.create();i.id&&i.name?e.collection.create(i,{wait:!0,success:function(t){t.get("message")?e.message.update({message:t.get("message"),status:"warning"}):e.message.update({message:"Successfully added a new custom build.",status:"success"})},error:function(t,i){var n=i&&i.responseJSON&&i.responseJSON.err_msg;e.message.update({message:n||"Failed to create custom build.",status:"danger"})}}):e.message.update({message:"All inputs are required.",status:"danger"})}})},onchange:function(){var i=t.data.match("len|type");if(i){var n=t.field_list[i];e._renderHelp(n.value())}}});this.$form.empty().append(t.$el);var i=this.model.get("installed_builds");i&&i.length?(this.$installed.show(),this.installed_builds.update(this.model.get("installed_builds"))):this.$installed.hide(),this._renderHelp("fasta")},_renderHelp:function(e){this.$help.empty().addClass("alert alert-info").html("fasta"==e?this._templateFasta():this._templateLen())},_templateLen:function(){return"
Length Format
The length format is two-column, separated by whitespace, of the form:
chrom/contig length of chrom/contig
For example, the first few entries of mm9.len are as follows:
Trackster uses this information to populate the select box for chrom/contig, andto set the maximum basepair of the track browser. You may either upload a .len fileof this format (Len File option), or directly enter the information into the box (Len Entry option).
"},_templateFasta:function(){return"
FASTA format
This is a multi-fasta file from your current history that provides the genomesequences for each chromosome/contig in your build.
Here is a snippet from an example multi-fasta file:
")}),t.append(a)}else t.append("No "+this.model.get("plural").toLowerCase()+" have been shared with you.");return t}});t.default={View:l}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(54),l=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t.default=e,t}(o),r=i(22),d=a(r),c=i(168),u=a(c),h=i(8),f=a(h),p=e.View.extend({tagName:"tr",initialize:function(){n.bindAll(this,"render","_rowTemplate","renderTagEditor","_templateActions","removeWorkflow","copyWorkflow"),l.options.timeOut=1500},events:{"click #show-in-tool-panel":"showInToolPanel","click #delete-workflow":"removeWorkflow","click #rename-workflow":"renameWorkflow","click #copy-workflow":"copyWorkflow"},render:function(){return s(this.el).html(this._rowTemplate()),this},showInToolPanel:function(){this.model.set("show_in_tool_panel",!this.model.get("show_in_tool_panel")),this.model.save(),window.location=Galaxy.root+"workflow"},removeWorkflow:function(){var e=this.model.get("name");window.confirm("Are you sure you want to delete workflow '"+e+"'?")&&(this.model.destroy({success:function(){l.success("Successfully deleted workflow '"+e+"'")}}),this.remove())},renameWorkflow:function(){var e=this.model.get("name"),t=window.prompt("Enter a new Name for workflow '"+e+"'",e);t&&(this.model.save({name:t},{success:function(){l.success("Successfully renamed workflow '"+e+"' to '"+t+"'")}}),this.render())},copyWorkflow:function(){var e=this,t=this.model.get("name");s.getJSON(this.model.urlRoot+"/"+this.model.id+"/download",function(i){var n="Copy of "+t,s=e.model.get("owner");s!=Galaxy.user.attributes.username&&(n+=" shared by user "+s),i.name=n,e.collection.create(i,{at:0,wait:!0,success:function(){l.success("Successfully copied workflow '"+t+"' to '"+n+"'")},error:function(e,t,i){l.error(i.errorThrown)}})}).error(function(e,t,i){l.error(e.responseJSON.err_msg)})},_rowTemplate:function(){var e=this.model.get("show_in_tool_panel"),t=this.model.id,i='';return'
'}}),m=e.View.extend({title:"Workflows",initialize:function(){this.setElement(""),n.bindAll(this,"adjustActiondropdown"),this.collection=new u.default.WorkflowCollection,this.collection.fetch().done(this.render()),this.collection.bind("add",this.appendItem),this.collection.on("sync",this.render,this)},events:{dragleave:"unhighlightDropZone",drop:"drop",dragover:function(e){s(".hidden_description_layer").addClass("dragover"),s(".menubutton").addClass("background-none"),e.preventDefault()}},unhighlightDropZone:function(){s(".hidden_description_layer").removeClass("dragover"),s(".menubutton").removeClass("background-none")},drop:function(e){this.unhighlightDropZone(),e.preventDefault();for(var t,i=e.dataTransfer.files,n=this,s=0;t=i[s];s++)n.readWorkflowFiles(t)},readWorkflowFiles:function(e){var t=this,i=new FileReader;i.onload=function(n){var s;try{s=JSON.parse(i.result)}catch(t){l.error("Could not read file '"+e.name+"'. Verify it is a valid Galaxy workflow"),s=null}s&&t.collection.create(s,{at:0,wait:!0,success:function(){l.success("Successfully imported workflow '"+s.name+"'")},error:function(e,t,i){l.error(i.errorThrown)}})},i.readAsText(e,"utf-8")},_showArgErrors:n.once(function(){var e=f.default.get("message");"error"===f.default.get("status")?l.error(n.escape(e||"Unknown Error, please report this to an administrator.")):e&&l.info(n.escape(e))}),render:function(){var e=this._templateHeader(),t=this._templateActionButtons(),i=this._templateWorkflowTable();this.$el.html(e+t+i);var s=this;n(this.collection.models).each(function(e){s.appendItem(e),s.confirmDelete(e)},this);return this.searchWorkflow(this.$(".search-wf"),this.$(".workflow-search tr"),3),this.adjustActiondropdown(),this._showArgErrors(),this},appendItem:function(e){var t=new p({model:e,collection:this.collection});s(".workflow-search").append(t.render().el),t.renderTagEditor()},confirmDelete:function(e){this.$(".link-confirm-shared-"+e.id).click(function(){return window.confirm("Are you sure you want to remove the shared workflow '"+e.attributes.name+"'?")})},searchWorkflow:function(e,t,i){e.on("keyup",function(){var e=s(this).val();if(e.length>=i){var n=new RegExp(e,"i");t.hide(),t.filter(function(){return n.test(s(this).text())}).show()}else t.show()})},adjustActiondropdown:function(){s(this.el).on("show.bs.dropdown",function(){s(this.el).css("overflow","inherit")}),s(this.el).on("hide.bs.dropdown",function(){s(this.el).css("overflow","auto")})},_templateNoWorkflow:function(){return'
Click the link above to visit myExperiment and browse for Galaxy workflows.
"}});t.default={View:m,ImportWorkflowView:g}}).call(t,i(2),i(1),i(0))},function(e,t,i){"use strict";(function(e){Object.defineProperty(t,"__esModule",{value:!0});var n=i(5),s=function(e){return e&&e.__esModule?e:{default:e}}(n),a=e.Model.extend(s.default.LoggableMixin).extend({_logNamespace:"workflow",urlRoot:Galaxy.root+"api/workflows",toJSON:function(){return{workflow:this.attributes}}}),o=e.Collection.extend({model:a,url:Galaxy.root+"api/workflows"});t.default={WorkflowItem:a,WorkflowCollection:o}}).call(t,i(2))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=a(o),r=i(12),d=a(r),c=i(38),u=a(c),h=i(78),f=a(h),p=e.View.extend({title:"Histories",initialize:function(t){var i=this;this.setElement(n("")),this.model=new e.Model,l.default.get({url:Galaxy.root+"history/"+t.action_id+"?"+n.param(Galaxy.params),success:function(e){e.dict_format=!0,s.each(e.operations,function(e){"Copy"==e.label&&(e.onclick=function(e){i._showCopyDialog(e)})}),i.model.set(e),i.render()}})},render:function(){var e=new d.default(this.model.attributes);this.$el.empty().append(e.$el)},_showCopyDialog:function(e){var t=new u.default.History({id:e});t.fetch().fail(function(){alert("History could not be fetched. Please contact an administrator")}).done(function(){(0,f.default)(t,{}).done(function(){window.parent&&window.parent.Galaxy&&window.parent.Galaxy.currHistoryPanel&&window.parent.Galaxy.currHistoryPanel.loadCurrentHistory(),window.location.reload(!0)})})}});t.default={View:p}}).call(t,i(2),i(0),i(1))},function(e,t,i){"use strict";(function(e,n){function s(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=i(3),o=s(a),l=i(6),r=s(l),d=i(9),c=s(d),u=e.View.extend({initialize:function(){this.setElement(""),this.model=new e.Model({dataset_id:Galaxy.params.dataset_id}),this.render()},render:function(){var e=Galaxy.root+"api/datasets/"+this.model.get("dataset_id"),t=this;o.default.get({url:e,success:function(e){var i=Galaxy.root+"api/jobs/"+e.creating_job+"?full=True";o.default.get({url:i,success:function(i){Galaxy.root,e.creating_job;t.render_error_page(t,e,i)},error:function(e){var i={status:"error",message:"Error occured while loading the job.",persistent:!0,cls:"errormessage"};t.display_message(i,t.$(".response-message"))}})},error:function(e){var i={status:"error",message:"Error occured while loading the dataset.",persistent:!0,cls:"errormessage"};t.display_message(i,t.$(".response-message"))}})},render_error_page:function(e,t,i){e.$el.empty().append(e._templateHeader()),e.$el.append("
Dataset Error
"),e.$el.append("
An error occured while running the tool "+i.tool_id+".
"),e.$el.append("
Tool execution generated the following messages:
"),e.$el.append('
'+i.stderr+"
"),e.$el.append("
Report This Error"),e.$el.append("
Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.
'},_getBugFormTemplate:function(e,t){var i=this,n=[{help:"Your email address",options:[],type:"text",name:"email",label:"Your email",value:Galaxy.user.get("email")},{help:"Any additional comments you can provide regarding what you were doing at the time of the bug.",options:[],type:"text",area:!0,name:"message",label:"Message"}],s=new c.default({title:"Error Report",inputs:n,buttons:{save:new r.default.Button({icon:"fa-bug",title:"Report",cls:"ui-button btn btn-primary",floating:"clear",onclick:function(){var n=s.data.create(),a=Galaxy.root+"api/jobs/"+t.id+"/error";n.dataset_id=e.id,i.submit(n,a)}})}});return s.$el},submit:function(e,t){var i=this;n.ajax({type:"POST",url:t,data:e,success:function(e){i.$el.empty().append(i._templateHeader()),e.messages.forEach(function(e){i.display_message({status:e[1],message:e[0],persistent:!0},i.$(".response-message"),!0,!0)})},error:function(e){var t={status:"error",message:"Error occured while saving. Please fill all the required fields and try again.",persistent:!0,cls:"errormessage"};i.display_message(t,i.$(".response-message"))}})}});t.default={View:u}}).call(t,i(2),i(0))},function(e,t,i){"use strict";(function(e,n,s){function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=i(3),l=(a(o),i(28)),r=a(l),d=i(6),c=a(d),u=i(9),h=a(u),f=e.View.extend({initialize:function(){this.setElement(""),this.model=new e.Model({dataset_id:Galaxy.params.dataset_id}),this.message=new c.default.Message({persistent:!0}),this.tabs=this._createTabs(),this.$el.append(n("").append("Edit dataset attributes")).append(this.message.$el).append("").append(this.tabs.$el).hide(),this.render()},render:function(){var e=this;n.ajax({url:Galaxy.root+"dataset/get_edit?dataset_id="+e.model.get("dataset_id"),success:function(t){!e.initial_message&&e.message.update(t),e.initial_message=!0,s.each(e.forms,function(e,i){e.model.set("inputs",t[i+"_inputs"]),e.model.set("hide_operations",t[i+"_disable"]),e.render()}),e.$el.show()},error:function(t){var i=t.responseJSON&&t.responseJSON.err_msg;e.message.update({status:"danger",message:i||"Error occured while loading the dataset."})}})},_submit:function(e,t){var i=this,s=t.data.create();s.dataset_id=this.model.get("dataset_id"),s.operation=e,n.ajax({type:"PUT",url:Galaxy.root+"dataset/set_edit",data:s,success:function(e){i.message.update(e),i.render(),i._reloadHistory()},error:function(e){var t=e.responseJSON&&e.responseJSON.err_msg;i.message.update({status:"danger",message:t||"Error occured while editing the dataset attributes."})}})},_createTabs:function(){this.forms={attribute:this._getAttribute(),conversion:this._getConversion(),datatype:this._getDatatype(),permission:this._getPermission()};var e=new r.default.View;return e.add({id:"attribute",title:"Attributes",icon:"fa fa-bars",tooltip:"Edit dataset attributes",$el:this.forms.attribute.$el}),e.add({id:"convert",title:"Convert",icon:"fa-gear",tooltip:"Convert to new format",$el:this.forms.conversion.$el}),e.add({id:"datatype",title:"Datatypes",icon:"fa-database",tooltip:"Change data type",$el:this.forms.datatype.$el}),e.add({id:"permissions",title:"Permissions",icon:"fa-user",tooltip:"Permissions",$el:this.forms.permission.$el}),e},_getAttribute:function(){var e=this,t=new h.default({title:"Edit attributes",operations:{submit_attributes:new c.default.ButtonIcon({tooltip:"Save attributes of the dataset.",icon:"fa-floppy-o",title:"Save",onclick:function(){e._submit("attributes",t)}}),submit_autodetect:new c.default.ButtonIcon({tooltip:"This will inspect the dataset and attempt to correct the values of fields if they are not accurate.",icon:"fa-undo",title:"Auto-detect",onclick:function(){e._submit("autodetect",t)}})}});return t},_getConversion:function(){var e=this,t=new h.default({title:"Convert to new format",operations:{submit_conversion:new c.default.ButtonIcon({tooltip:"Convert the datatype to a new format.",title:"Convert datatype",icon:"fa-exchange",onclick:function(){e._submit("conversion",t)}})}});return t},_getDatatype:function(){var e=this,t=new h.default({title:"Change datatype",operations:{submit_datatype:new c.default.ButtonIcon({tooltip:"Change the datatype to a new type.",title:"Change datatype",icon:"fa-exchange",onclick:function(){e._submit("datatype",t)}})}});return t},_getPermission:function(){var e=this,t=new h.default({title:"Manage dataset permissions",operations:{submit_permission:new c.default.ButtonIcon({tooltip:"Save permissions.",title:"Save permissions",icon:"fa-floppy-o ",onclick:function(){e._submit("permission",t)}})}});return t},_reloadHistory:function(){window.Galaxy&&window.Galaxy.currHistoryPanel.loadCurrentHistory()}});t.default={View:f}}).call(t,i(2),i(0),i(1))}],[138]);
//# sourceMappingURL=analysis.bundled.js.map
\ No newline at end of file
diff --git a/static/scripts/bundled/analysis.bundled.js.map b/static/scripts/bundled/analysis.bundled.js.map
index 55d05c7f498d..7636c6782553 100644
--- a/static/scripts/bundled/analysis.bundled.js.map
+++ b/static/scripts/bundled/analysis.bundled.js.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack:///analysis.bundled.js","webpack:///./galaxy/scripts/mvc/ui/ui-popover.js","webpack:///./galaxy/scripts/mvc/dataset/states.js","webpack:///./galaxy/scripts/mvc/ui/ui-select.js","webpack:///./galaxy/scripts/ui/fa-icon-button.js","webpack:///./galaxy/scripts/mvc/upload/upload-model.js","webpack:///./galaxy/scripts/mvc/tag.js","webpack:///./galaxy/scripts/layout/router.js","webpack:///./galaxy/scripts/mvc/upload/upload-settings.js","webpack:///./galaxy/scripts/mvc/upload/upload-ftp.js","webpack:///./galaxy/scripts/mvc/upload/upload-extension.js","webpack:///./galaxy/scripts/utils/uploadbox.js","webpack:///./galaxy/scripts/mvc/collection/list-collection-creator.js","webpack:///./galaxy/scripts/mvc/history/hdca-model.js","webpack:///./galaxy/scripts/mvc/collection/collection-model.js","webpack:///./galaxy/scripts/mvc/history/history-model.js","webpack:///./galaxy/scripts/mvc/history/history-contents.js","webpack:///./galaxy/scripts/mvc/history/history-preferences.js","webpack:///./galaxy/scripts/mvc/list/list-item.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-li.js","webpack:///./galaxy/scripts/mvc/collection/collection-li.js","webpack:///./galaxy/scripts/mvc/form/form-wrapper.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-model.js","webpack:///./galaxy/scripts/mvc/history/history-content-model.js","webpack:///./galaxy/scripts/mvc/collection/base-creator.js","webpack:///./galaxy/scripts/utils/natural-sort.js","webpack:///./galaxy/scripts/ui/hoverhighlight.js","webpack:///./galaxy/scripts/mvc/tool/tool-form-composite.js","webpack:///./galaxy/scripts/mvc/history/copy-dialog.js","webpack:///./galaxy/scripts/mvc/ui/error-modal.js","webpack:///./galaxy/scripts/mvc/base/controlled-fetch-collection.js","webpack:///./galaxy/scripts/mvc/history/hda-model.js","webpack:///./galaxy/scripts/mvc/list/list-view.js","webpack:///./galaxy/scripts/ui/search-input.js","webpack:///./galaxy/scripts/mvc/history/hda-li.js","webpack:///./galaxy/scripts/mvc/history/hdca-li.js","webpack:///./galaxy/scripts/mvc/collection/collection-view.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-li-edit.js","webpack:///./galaxy/scripts/mvc/annotation.js","webpack:///./galaxy/scripts/apps/analysis.js","webpack:///./galaxy/scripts/apps/panels/tool-panel.js","webpack:///./galaxy/scripts/mvc/upload/upload-view.js","webpack:///./galaxy/scripts/mvc/upload/upload-button.js","webpack:///./galaxy/scripts/mvc/upload/default/default-view.js","webpack:///./galaxy/scripts/mvc/upload/default/default-row.js","webpack:///./galaxy/scripts/mvc/lazy/lazy-limited.js","webpack:///./galaxy/scripts/mvc/upload/composite/composite-view.js","webpack:///./galaxy/scripts/mvc/upload/composite/composite-row.js","webpack:///./galaxy/scripts/mvc/upload/collection/collection-view.js","webpack:///./galaxy/scripts/mvc/upload/collection/collection-row.js","webpack:///./galaxy/scripts/mvc/workflow/workflow-icons.js","webpack:///./galaxy/scripts/apps/panels/history-panel.js","webpack:///./galaxy/scripts/mvc/history/options-menu.js","webpack:///./galaxy/scripts/mvc/history/history-view-edit-current.js","webpack:///./galaxy/scripts/utils/ajax-queue.js","webpack:///./galaxy/scripts/mvc/history/history-view-edit.js","webpack:///./galaxy/scripts/mvc/history/history-view.js","webpack:///./galaxy/scripts/ui/loading-indicator.js","webpack:///./galaxy/scripts/mvc/history/hda-li-edit.js","webpack:///./galaxy/scripts/mvc/history/hdca-li-edit.js","webpack:///./galaxy/scripts/mvc/collection/collection-view-edit.js","webpack:///./galaxy/scripts/mvc/collection/collection-li-edit.js","webpack:///./galaxy/scripts/mvc/collection/pair-collection-creator.js","webpack:///./galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js","webpack:///./galaxy/scripts/utils/levenshtein.js","webpack:///./galaxy/scripts/mvc/user/user-preferences.js","webpack:///./galaxy/scripts/mvc/user/user-custom-builds.js","webpack:///./galaxy/scripts/mvc/grid/grid-shared.js","webpack:///./galaxy/scripts/mvc/workflow/workflow.js","webpack:///./galaxy/scripts/mvc/workflow/workflow-model.js","webpack:///./galaxy/scripts/mvc/history/history-list.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-error.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-edit-attributes.js"],"names":["webpackJsonp","module","exports","__webpack_require__","Backbone","_","$","Object","defineProperty","value","_utils","_utils2","obj","__esModule","default","View","extend","optionsDefault","with_close","title","placement","container","body","initialize","options","this","setElement","_template","uid","defaults","parent","append","el","$title","$close","$body","self","on","e","visible","is","target","has","length","hide","render","html","$el","removeClass","addClass","css","_get_placement","show","off","newTitle","undefined","empty","remove","top","left","width","_get_width","height","$container","container_width","container_height","_get_height","container_position","position","indexOf","parseInt","call","STATES","UPLOAD","QUEUED","RUNNING","SETTING_METADATA","NEW","EMPTY","OK","PAUSED","FAILED_METADATA","NOT_VIEWABLE","DISCARDED","ERROR","READY_STATES","NOT_READY_STATES","placeholder","data","multiple","minimumInputLength","initialData","merge","console","log","select_data","_refresh","_setValue","onchange","new_value","before","_getValue","after","text","select2","disabled","enable","disable","add","push","id","del","index","_getIndex","splice","update","key","select_opt","containerCssClass","ajax","dropdownCssClass","escapeMarkup","formatResult","formatSelection","initSelection","selected","dropdownAutoWidth","findIndex","_jquery","_jquery2","faIconButton","tooltipConfig","classes","concat","join","href","faIcon","$button","tooltip","isFunction","onclick","click","Model","extension","genome","url_paste","status","info","file_name","file_mode","file_size","file_type","file_path","file_data","percentage","space_to_tab","to_posix_lines","enabled","reset","attr","clear","set","Collection","model","_interopRequireDefault","_baseMvc","_baseMvc2","_localization","_localization2","TagsEditor","LoggableMixin","HiddenUntilActivatedViewMixin","tagName","className","select_width","events","show_editor","usePrompt","label","workflow_mode","keydown","hiddenUntilActivated","$activator","_workflowTemplate","_defaultTemplate","$input","tags","_getTagsUsed","_setUpBehaviors","_hashToName","tag","startsWith","slice","_nameToHash","_renderEditor","_renderTags","keydownHandler","which","hideEditor","showEditor","tagsToCSV","get","renderedArray","each","renderString","tagsArray","isArray","isEmpty","map","escape","sort","find","Galaxy","user","event","val","save","added","_addNewTagToTagsUsed","newTag","tagsUsed","contains","stopListening","prototype","toString","_queryStringParsing","_queryStringParsing2","_uiMisc","_uiMisc2","Router","page","url","__identifer","Math","random","substr","isEmptyObject","param","params","navigate","trigger","execute","callback","args","name","debug","queryObj","parse","pop","authenticate","apply","access_denied","display","Message","message","persistent","class_check","class_uncheck","parameters","$cover","$table","listenTo","parameter","$checkbox","cls","class_add","class_remove","class_partial","help_enabled","help_text","ftp_upload_site","collection","onadd","onremove","$content","$wait","$help","$number","$disk","$warning","$select","root","method","success","ftp_files","_index","_renderTable","error","rows","size","ftp_file","_renderRow","bytesToString","_all","attributes","$it","_templateRow","$icon","model_index","ftp_index","path","_switch","hasClass","new_index","counts","reduce","memo","element","ctime","_uiPopover","_uiPopover2","description","findWhere","list","extension_popup","_templateDescription","tmpl","description_url","jQuery","props","uploadpost","config","cnf","progress","maxfilesize","error_filesize","error_default","error_server","error_login","error_message","form","FormData","payload","sizes","files","d","file","xhr","XMLHttpRequest","open","setRequestHeader","onreadystatechange","readyState","DONE","response","extra_info","responseText","parseJSON","err_msg","statusText","upload","addEventListener","lengthComputable","round","loaded","total","emit","send","fn","uploadinput","opts","ondragover","ondragleave","change","dataTransfer","preventDefault","stopPropagation","dialog","uploadbox","queue_running","mode","filter","queue","f","duplicate","String","queue_index","announce","queue_length","process","queue_stop","complete","select","start","stop","configure","compatible","window","File","FileList","dragover","dragleave","m","alert","createListCollection","contents","defaultHideSourceItems","elements","toJSON","listCollectionCreatorModal","creationFn","hideSourceItems","src","history_content_type","createHDCA","_hdcaModel","_hdcaModel2","_states","_states2","_baseCreator","_baseCreator2","_uiModal","_uiModal2","_naturalSort","DatasetCollectionElementView","_logNamespace","dragStartHandler","bind","_dragstart","dragEndHandler","_dragend","handle","template","toggle","toggleClass","source","discard","view","parentWidth","animate","margin-right","destroy","click .name","click .discard","drop","_click","ev","_clickName","prompt","_clickDiscard","originalEvent","effectAllowed","setData","JSON","stringify","_sendToParent","ListCollectionCreator","CollectionCreatorMixin","elementViewClass","collectionClass","HistoryListDatasetCollection","minElements","defaultAttributes","TypeError","oncreate","oncancel","autoscrollDist","highlightClr","footerSettings",".hide-originals","metric","creator","initialElements","_setUpCommonSettings","_instanceSetUp","_elementsSetUp","selectedIds","$dragging","blocking","invalidElements","workingElements","elementViews","_ensureElementIds","_validateElements","_mangleDuplicateNames","_sortElements","forEach","hasOwnProperty","uniqueId","problem","_isElementInvalid","state","deleted","purged","counter","existingNames","currName","Error","speed","_renderInvalid","templates","main","_renderHeader","_renderMiddle","_renderFooter","_addPluginComponents","focus","invalidInitial","problems","$header","header","prepend","helpContent","_invalidElementsAlert","$middle","middle","_renderList","hoverhighlight","_showAlert","_disableNameAndCreate","isUndefined","prop","$list","_renderClearSelected","$tmp","removeElementView","elementView","_createElementView","children","invoke","_listenToElementView","addElementView","without","_renderNoElementsLeft","noElementsLeft","_elementToJSON","createList","hideOriginals","always","fail","done","_errorHandler","once","content","responseJSON","click .more-help","click .less-help","click .main-help","click .header .alert button","click .reset","click .clear-selected","click .collection-elements","dragover .collection-elements","drop .collection-elements","collection-element.dragstart .collection-elements","collection-element.dragend .collection-elements","change .collection-name","keydown .collection-name","change .hide-originals","click .cancel-create","click .create-collection","clearSelectedElements","_dragoverElements","_checkForAutoscroll","clientY","$nearest","_getNearestElement","$placeholder","$element","y","offset","scrollTop","upperDist","lowerDist","outerHeight","lis","toArray","i","$li","halfHeight","floor","_dropElements","dropEffect","insertBefore","insertAfter","last","_syncOrderToDom","newElements","_elementDragstart","_elementDragend","_creatorTemplates","footer","collectionCreatorModal","CreatorClass","deferred","Deferred","modal","reject","resolve","closing_events","_collectionCreator","buildHDCASave","_super","isNew","urlRoot","type","_collectionModel","_collectionModel2","_historyContentModel","_historyContentModel2","hcontentMixin","HistoryContentMixin","ListDC","ListDatasetCollection","PairDC","PairDatasetCollection","ListPairedDC","ListPairedDatasetCollection","ListOfListsDC","ListOfListsDatasetCollection","clone","collection_type","model_class","HistoryPairDatasetCollection","HistoryListPairedDatasetCollection","HistoryListOfListsDatasetCollection","_datasetModel","_datasetModel2","DatasetCollectionElementMixin","element_identifier","element_index","element_type","_mergeObject","object","element_id","constructor","idAttribute","arguments","DatasetCollectionElement","DCECollection","DatasetDCE","DatasetAssociation","mixin","warn","_downloadQueryParameters","hasDetails","DatasetDCECollection","DatasetCollection","SearchableModelMixin","_createElementsModel","unset","silent","parent_hdca_id","json","inReadyState","populated","isDeletedOrPurged","getVisibleContents","filters","parsed","create_time","Date","update_time","delete","when","undelete","searchAttributes","NestedDCDCE","NestedDCDCECollection","NestedPairDCDCE","NestedPairDCDCECollection","NestedListDCDCE","NestedListDCDCECollection","_historyContents","_historyContents2","_historyPreferences","_controlledFetchCollection","_controlledFetchCollection2","History","UPDATE_DELAY","contents_active","contents_states","contentsClass","HistoryContents","searchAliases","historyJSON","logger","history","historyId","order","_setUpListeners","_setUpCollectionListeners","updateTimeoutId","msg","details","clearUpdateTimeout","change:id","newId","makeArray","contentsShown","contentsActive","shown","active","includeDeleted","includeHidden","hidden","nice_size","ownedByCurrUser","isAnonymous","numOfUnfinishedJobs","unfinishedJobIds","numOfUnfinishedShownContents","runningAndActive","_fetchContentRelatedAttributes","contentRelatedAttrs","fetch","keys","refresh","lastUpdateTime","allFetched","currentPage","fetchPage","fetchUpdated","serverResponseDatetime","getResponseHeader","err","checkForUpdates","_delayThenUpdate","setTimeout","delay","historyData","clearTimeout","fetchWithContents","contentsOptions","then","setHistoryId","fetchContents","fetchCurrentPage","_delete","purge","copy","current","allDatasets","postData","history_id","all_datasets","post","setAsCurrent","getJSON","_collectionSuper","InfinitelyScrollingCollection","HistoryCollection","limitOnFirstFetch","limitPerFetch","models","currentHistoryId","setUpListeners","change:deleted","copied","original","newData","setCurrent","set-as-current","oldCurrentId","_buildFetchData","_buildFetchFilters","superFilters","fetchFirst","limit","encoded_id-in","fetchMore","comparators","buildComparator","ascending","name-dsc","size-asc","currentHistory","unshift","create","hdas","historyOptions","xhrOptions","_hdaModel","_hdaModel2","_historyPreferences2","_ajaxQueue","_ajaxQueue2","PaginatedCollection","limitPerPage","limitPerProgressiveFetch","attrs","HistoryDatasetAssociation","validationError","_setUpWebStorage","initialSettings","storage","HistoryPrefs","historyStorageKey","include-deleted","newVal","include-hidden","hid","hid-asc","running","c","getByHid","haveDetails","all","visibleAndUndeleted","setIncludeDeleted","setting","isBoolean","result","setIncludeHidden","prefs","expandedIds","values","v","_fetchParams","getTotalItemCount","since","update_time-ge","toISOString","fetchDeleted","fetchHidden","fetchAllDetails","detailsFlag","fetchCollectionCounts","_filterAndUpdate","filterParams","updateWhat","updateArgs","fetched","modelArray","currJson","ajaxQueue","ajaxFn","AjaxQueue","reverse","isString","progressivelyFetchDetails","_recursivelyFetch","_options","detailKeys","defer","notify","limitPerCall","isCopyable","contentsJSON","copyableModelClasses","isObject","contentType","LibraryDatasetDatasetAssociation","HistoryDatasetCollectionAssociation","elementIdentifiers","collectionType","hide_source_items","element_identifiers","haveSearchDetails","matches","matchesWhat","SessionStorageModel","show_deleted","show_hidden","addExpanded","removeExpanded","isExpanded","contentId","allExpanded","clearExpanded","storageKeyPrefix","clearAll","sessionStorage","removeItem","ExpandableView","expanded","fxSpeed","$newRender","_buildNewRender","_queueNewRender","$details","replaceWith","_renderDetails","_swapNewRender","next","fadeOut","fadeIn","$where","$newDetails","toggleExpanded","expand","collapse","_fetchModelDetails","_expand","slideDown","slideUp","ListItemView","SelectableViewMixin","DraggableViewMixin","isSelectable","_renderWarnings","_renderTitleBar","_renderPrimaryActions","_renderSubtitle","selectable","showSelector","draggable","draggableOn","$warnings","warnings","templateFn","titleBar","subtitle","click .title-bar","keydown .title-bar","click .selector","_clickTitleBar","altKey","toggleSelect","_keyDownTitleBar","keyCode","wrapTemplate","FoldoutListItemView","foldoutStyle","foldoutPanelClass","foldout","_createFoldoutPanel","_attachFoldout","FoldoutClass","_getFoldoutPanelClass","_getFoldoutPanelOptions","$whereTo","_expandByDrilldown","detailsTemplate","_listItem","_listItem2","_faIconButton","_faIconButton2","DatasetListItemView","linkTarget","changedAttributes","changed","_renderNametags","_renderDisplayButton","displayBtnData","urls","frame","addDataset","noAccess","_renderSecondaryActions","_renderSummary","_renderDetailMessages","_renderDisplayApplications","summaryRenderFn","summaries","unknown","detailMessages","displayApplications","_renderDownloadButton","_renderShowParamsButton","show_params","hasData","download","_renderMetaFileDownloadButton","meta_file","meta_download","click .display-btn","click .params-btn","click .download-btn","failed_metadata","noAccessTemplate","summaryTemplates","detailMessageTemplates","resubmitted","displayApplicationsTemplate","_datasetLi","_datasetLi2","DCListItemView","hasUser","$selector","titleBarTemplate","subtitleTemplate","DCEListItemView","DatasetDCEListItemView","NestedDCDCEListItemView","_formView","_formView2","redirect","icon","inputs","buttons","submit","Button","submit_tooltip","submit_title","submit_icon","_submit","success_message","location","matchModel","input","input_id","field_list","_showMessage","parents","first","searchableMixin","accessible","data_type","file_ext","meta_files","misc_blurb","misc_info","_generateUrls","edit","report_error","rerun","visualization","currModel","newState","previous","ready","dataset","wait","hda","responseObj","format","database","blurb","nameAndId","DatasetAssociationCollection","ids","item","notReady","startingLength","responses","ajaxFns","chain","curr","shift","isVisible","unhide","_validationWarning","what","_changeHideOriginals","_changeName","_getName","_nameCheckForEnter","_clickCreate","_clickMoreHelp","_clickLessHelp","_toggleHelp","alertClass","_hideAlert","_cancelCreate","$footer","property","selector","naturalSort","a","b","re","x","toLowerCase","nC","fromCharCode","xN","replace","split","yN","xD","getTime","yD","oFxNcL","oFyNcL","cLoc","numS","max","parseFloat","scope","color","$this","targetSelector","mouseover","background","mouseout","_deferred","_deferred2","_formData","_formData2","_toolFormBase","_toolFormBase2","_webhooks","_webhooks2","_workflowIcons","_workflowIcons2","$message","$steps","_configure","resize","step_index","margin","child","_handleWorkflowParameter","match","exec","wp_name","wp_inputs","wp_count","style","links","forms","steps","parms","step","step_type","step_label","step_name","annotation","step_version","fixed_title","help","citations","collapsible","collapsed","_isDataStep","sustain_version","sustain_repeats","sustain_conditionals","narrow","text_enable","text_disable","cls_enable","cls_disable","errors","messages","initial_errors","hide_operations","needs_refresh","always_refresh","visitInputs","output_connections","output_connection","sub_step","j","input_step_index","connections_by_name","connection","input_name","step_linked","output_name","wp_input","wp_linked","backdrop","post_job_actions","pja","action_arguments","arg","data_resolved","context","is_runtime_value","__class__","is_data_input","data_ref","is_workflow","default_value","flavor","optional","collapsible_value","collapsible_preview","_renderMessage","_renderParameters","_renderHistory","_renderStep","execute_btn","_execute","Label","fade","step_version_changes","wp_form","input_list","input_def","_refreshStep","_append","history_form","test_param","cases","promise","postchange","current_state","tool_id","tool_version","version","request","portlet","short_str","is_simple_input","hide_label","link","ignore","show_progress","wait_text","field","source_step","wp_field","wp_value","_refreshHistory","currHistoryPanel","_refresh_history","_enabled","history_form_data","job_def","new_history_name","replacement_params","parameters_normalized","batch","validated","job_inputs","job_input_id","input_value","highlight","_templateSuccess","WebhookView","toolId","toolVersion","input_found","err_data","step_related_errors","error_messages","matchResponse","_templateError","Close","lst","sanitize","_errorModal","_errorModal2","CopyDialog","defaultName","submitLabel","errorMessage","progressive","activeLabel","allLabel","anonWarning","_showAjaxIndicator","indicator","margin-top","checkNameAndCopy","copyAllDatasets","ajaxErrorModal","rejectWith","autoClose","defaultCopyNameFn","nameFn","defaultCopyName","defaultCopyWhat","allowAll","originalClosingCallback","closing_callback","isAnon","copyWhat","cancelled","ImportDialog","historyCopyDialog","useImport","Ok","appendTo","DETAILS_MSG","errorModal","offlineErrorModal","badGatewayErrorModal","CONTACT_MSG","DEFAULT_AJAX_ERR_MSG","_ajaxDetails","raven","Raven","userAgent","navigator","onLine","omit","functions","lastAjax","_interopRequireWildcard","newObj","_underscore","_backbone","ControlledFetchCollection","setOrder","changed-order","_buildFetchOptions","traditional","_fetchFiltersToAjaxData","pick","filterMap","q","qv","k","update_time-asc","create_time-asc","comparator","shouldPaginate","getLastPage","getPageCount","getPageLimitOffset","pageNum","constrainPageNum","min","fetchPrevPage","fetchNextPage","lastFetched","fetchedData","numFetched","fetchAll","_loadingIndicator","_loadingIndicator2","ListPanel","viewClass","emptyMsg","noneFoundMsg","searchPlaceholder","searchFor","selecting","lastSelected","dragItems","views","_createDefaultCollection","$scrollContainer","loading","_showLoadingIndicator","loading-done","_hideLoadingIndicator","_setUpViewListeners","changes","renderAll","removed","renderItems","addItemView","removeItemView","view:selected","shiftKey","lastSelectedView","viewFromModelId","selectRange","showSelectors","view:de-selected","_renderControls","_renderTitle","_renderSearch","$controls","controls","panel","_renderMultiselectActionMenu","$menu","actions","multiselectActions","$newMenu","$actions","action","func","$messages","$emptyMessage","freeViews","shownModels","_filterCollection","itemModel","_createItemView","_attachItems","_renderEmptyMessage","_filterItem","every","matchesAll","ViewClass","_getItemViewClass","_getItemViewOptions","_setUpItemViewListeners","_destroyItemView","_destroyItemViews","Array","getSelectedModels","_renderItemView$el","expandAll","collapseAll","modelIndex","_attachView","useFx","_insertIntoListAt","$what","eq","viewFromModel","viewsWhereModel","properties","isMatch","viewRange","viewA","viewB","indexA","indexB","searchInput","initialVal","onfirstsearch","_firstSearch","onsearch","searchItems","onclear","clearSearch","force","$search","THROTTLE_SELECTOR_FX_AT","hideSelectors","hideSelector","toggleSelectors","selectAll","deselectAll","deselect","range","getSelectedViews","scrollPosition","scrollTo","pos","scrollToTop","scrollToItem","scrollToId","click .select-all","click .deselect-all","ModelListPanel","modelCollectionKey","setModel","freeModel","oldModelId","_setUpModelListeners","controlsTemplate","parentNode","clearSearchInput","blur","search","searchTerms","firstSearch","inputTemplate","KEYCODE_ESC","KEYCODE_RETURN","$parentNode","inputVal","minSearchLen","escWillClear","oninit","keyup","_l","s","HDAListItemView","_collectionLi","_collectionLi2","_collectionView","_collectionView2","HDCAListItemView","change:tags change:populated change:visible","ListCollectionView","PairCollectionView","ListOfPairsCollectionView","ListOfListsCollectionView","_listView","_listView2","CollectionView","DatasetDCEViewClass","NestedDCDCEViewClass","panelStack","parentName","downloadUrl","expanded:drilldown","drilldown","_expandDrilldownPanel","collapsed:drilldown","_collapseDrilldownPanel","click .navigation .back","close","_tag","_tag2","_annotation","_annotation2","DatasetListItemEdit","purgeAllowed","tagsEditorShown","annotationEditorShown","_renderEditButton","_renderDeleteButton","editBtnData","router","dataset_id","deletedAlready","_renderAnnotation","_makeDbkeyEditLink","_renderToolHelpButton","datasetID","jobID","creating_job","parseToolBuild","helpString","parseHTML","parseToolID","_renderErrButton","_renderRerunButton","_renderVisualizationsButton","job_id","visualizations","$visualizations","_addScratchBookFn","addBack","$links","tagsEditor","onshowFirstTime","onshow","onhide","annotationEditor","AnnotationEditor","editableDbkey","click .undelete-link","click .purge-link","click .edit-btn","click .delete-btn","click .rerun-btn","click .report-err-btn","click .visualization-btn","click .dbkey a","_clickUndeleteLink","_clickPurgeLink","confirm","visualizationsTemplate","$annotation","make_text_editable","use_textarea","on_finish","newAnnotation","_galaxy","_galaxy2","_router","_router2","_toolPanel","_toolPanel2","_historyPanel","_historyPanel2","_page","_page2","_toolForm","_toolForm2","_formWrapper","_formWrapper2","_userPreferences","_userPreferences2","_userCustomBuilds","_userCustomBuilds2","_tours","_tours2","_gridView","_gridView2","_gridShared","_gridShared2","_workflow","_workflow2","_historyList","_historyList2","_toolFormComposite","_toolFormComposite2","_datasetError","_datasetError2","_datasetEditAttributes","_datasetEditAttributes2","app","bootstrapped","GalaxyApp","AnalysisRouter","routes","(/)","(/)root*","(/)tours(/)(:tour_id)","(/)user(/)","(/)user(/)(:form_id)","(/)workflow(/)","(/)workflow/run(/)","(/)pages(/)create(/)","(/)pages(/)edit(/)","(/)pages(/)(:action_id)","(/)visualizations(/)edit(/)","(/)visualizations/(:action_id)","(/)workflows/list_published(/)","(/)histories(/)rename(/)","(/)histories(/)permissions(/)","(/)histories(/)(:action_id)","(/)datasets(/)list(/)","(/)workflow/import_workflow","(/)custom_builds","(/)datasets/edit","(/)datasets/error","require_login","show_tours","tour_id","giveTour","ToursView","show_user","show_user_form","form_id","user_id","show_visualizations","action_id","plural","show_visualizations_edit","show_workflows_published","url_base","dict_format","show_histories","show_histories_rename","show_histories_permissions","show_datasets","show_pages","show_pages_create","show_pages_edit","show_workflows","show_run","_loadWorkflow","show_import_workflow","ImportWorkflowView","show_custom_builds","historyPanel","historyView","show_dataset_edit_attributes","show_dataset_error","home","toolPanel","_loadCenterIframe","_loadToolForm","workflow_id","m_c","m_a","decodeURIComponent","getQueryString","error_msg","Left","Right","_tools","_tools2","_uploadView","_uploadView2","ToolPanel","stored_workflow_menu_entries","tool_search","ToolSearch","tools","ToolCollection","toolbox","tool_panel","layout","toolbox_in_panel","tool_panel_view","ToolPanelView","upload_button","nginx_upload_path","default_genome","default_extension","_templateAllWorkflow","menu_entry","_templateWorkflowLink","stored_workflow","encoded_stored_workflow_id","_templateTool","tool","wf","_uiTabs","_uiTabs2","_uploadButton","_uploadButton2","_defaultView","_defaultView2","_compositeView","_compositeView2","auto","list_extensions","list_genomes","ui_button","onunload","datatypes","composite_files","a_text","b_text","datatypes_disable_auto","genomes","current_user","tabs","default_view","composite_view","collection_view","title_separator","currentFtp","toData","items","file_count","dbkey","it","prefix","$progress","_uploadModel","_uploadModel2","_defaultRow","_defaultRow2","_uploadFtp2","_uploadFtp3","_uploadExtension","_uploadExtension2","_uiSelect","_uiSelect2","_lazyLimited","_lazyLimited2","upload_size","$uploadbox","$uploadtable","btnLocal","btnFtp","_eventFtp","btnCreate","_eventCreate","btnStart","_eventStart","btnStop","_eventStop","btnReset","_eventReset","btnClose","button","_eventAnnounce","_eventProgress","_eventSuccess","_eventError","_eventComplete","ftp","select_extension","ext","_changeExtension","select_genome","_changeGenome","loader","new_content","upload_row","_eventRemove","enable_reset","enable_start","enable_sources","show_table","new_model","_uploadPercentage","upload_completed","refreshContents","_uploadFtp","defaults_only","_uploadSettings","_uploadSettings2","status_classes","init","queued","$mode","$text","$size","$info_text","$info_progress","$text_content","$settings","$symbol","$progress_bar","$percentage","settings","_removeRow","showExtensionInfo","_showSettings","_refreshPercentage","_refreshStatus","_refreshInfo","_refreshGenome","_refreshExtension","_refreshFileSize","_refreshType","content_list","_reset","_remove","_done","model_id","_compositeRow","_compositeRow2","file_desc","where","$source","$status","$file_name","$file_desc","$file_size","_refreshReady","button_menu","ButtonMenu","pull","addMenu","_showFtp","_refreshFileName","_refreshMode","offsetHeight","_collectionRow","_collectionRow2","_listCollectionCreator","btnBuild","_eventBuild","updateExtension","select_collection","updateCollectionType","updateGenome","_updateScreen","hids","pluck","allHids","selection","buildCollection","enable_build","data_input","data_collection_input","subworkflow","pause","_optionsMenu","_optionsMenu2","_historyViewEditCurrent","_historyViewEditCurrent2","HistoryPanel","userIsAnonymous","allow_user_dataset_purge","CurrentHistoryView","listenToGalaxy","buttonRefresh","ButtonLink","loadCurrentHistory","buttonOptions","buttonViewMulti","connectToQuotaMeter","quotaMeter","optionsMenu","anonymous","buildMenu","menu","menuOption","anon","galaxy_main","_popupMenu","_popupMenu2","_copyDialog","_copyDialog2","createNewHistory","user_action","async","webhooks","webhooks_menu","webhook","activate","_historyModel","_historyViewEdit","_historyViewEdit2","HistoryViewPrefs","storageKey","HistoryViewEdit","HDCAViewClass","preferences","currentContentId","loadHistory","switchToHistory","change:nice_size change:size","oldState","_debouncedScrollCaptureHandler","debounce","prependTo","_renderQuotaMessage","quotaMsg","_setCurrentContentById","setCurrentContent","delegateEvents","click .uploader-link","click .get-data-link","$toolMenu","galaxy","center-frame:load","pathToMatch","fullpath","hdaId","useToURLRegexMap","regex","use","center-panel:load","showQuotaMessage","hideQuotaMessage","isOverQuota","clearMessages","$target","currentTarget","not","$msg","unhideHidden","deleteHidden","quotaMsgTemplate","_possibleConstructorReturn","ReferenceError","_inherits","subClass","superClass","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","instance","Constructor","_get","receiver","Function","desc","getOwnPropertyDescriptor","getPrototypeOf","getter","_createClass","defineProperties","descriptor","protoProps","staticProps","initialFunctions","numToProcess","_this","_this2","fnIndex","causeFail","NamedAjaxQueue","_AjaxQueue","_this3","names","_historyView","_historyView2","_hdaLiEdit","_hdaLiEdit2","_hdcaLiEdit","_hdcaLiEdit2","_listCollectionCreator2","_pairCollectionCreator","_pairCollectionCreator2","_listOfPairsCollectionCreator","_listOfPairsCollectionCreator2","HistoryView","HDAViewClass","HDAListItemEdit","HDCAListItemEdit","droptarget:drop","dataDropped","dropTargetOff","view:attached view:removed","_renderCounts","search:loading-progress","_renderSearchProgress","search:searching","_renderSearchFindings","updateHistoryDiskSize","_handleItemDeletedChange","change:visible","_handleItemVisibleChange","change:purged","fetching-deleted","fetching-hidden","fetching-deleted-done fetching-hidden-done","toggleHDATagEditors","toggleHDAAnnotationEditors","newName","previousName","_collectionActions","createFunc","createPairCollection","createListOfPairsCollection","_handleItemDeletion","_handleItemUndeletion","_handleItemHidden","_handleItemUnhidden","showOrHide","click .show-selectors-btn","click .toggle-deleted-link","toggleShowDeleted","click .toggle-hidden-link","toggleShowHidden","found","dropTargetOn","dropTarget","dropHandlers","dragenter","$dropTarget","_renderDropTarget","_renderDropTargetHelp","evName","_dropHandlers","dropTargetToggle","getData","countsTemplate","foundTemplate","_historyModel2","_hdaLi","_hdaLi2","_hdcaLi","_hdcaLi2","_userModel","FETCH_COLLECTION_COUNTS_DELAY","detailedFetchTimeoutId","_clearDetailedFetchTimeout","errorHandler","views:ready view:attached view:removed","_renderSelectButton","view:attached","fetching-more","_toggleContentsLoadingIndicator","fetching-more-done","$indicator","$existing","$emptyMsg","_renderPagination","_renderSomeItems","$paginationControls","pagination","click > .controls .prev","click > .controls .next","change > .controls .pages","click .messages [class$=message]","_clickPrevPage","_clickNextPage","_changePageSelect","store","scrollToHid","ordinalIndicator","number","numStr","charAt","mainTemplate","paginationTemplate","LoadingIndicator","cover","z-index","bottom","right","opacity","background-color","text-align","font-style","_datasetLiEdit","_datasetLiEdit2","click .unhide-link","_collectionViewEdit","_collectionViewEdit2","ListCollectionViewEdit","PairCollectionViewEdit","ListOfPairsCollectionViewEdit","ListOfListsCollectionViewEdit","_collectionLiEdit","_collectionLiEdit2","CollectionViewEdit","DatasetDCEListItemEdit","NestedDCDCEListItemEdit","NestedPairCollectionViewEdit","DCListItemEdit","DCEListItemEdit","pairCollectionCreatorModal","PairedDatasetCollectionElementView","identifier","PairCollectionCreator","_createForwardElementView","_createReverseElementView","swap","click .swap","autoPairFnBuilder","getRegExps","_regexps","RegExp","createPair","listA","listB","aInBIndex","bInAIndex","_pair","preprocessMatch","regexps","matchTo","possible","bestMatch","score","paired","scoreThreshold","pairedCollectionCreatorModal","_levenshtein","_levenshtein2","_naturalSort2","PairView","pair","PairedCollectionCreator","datasets","DEFAULT_FILTERS","automaticallyPair","strategy","matchPercentage","twoPassAutopairing","initialList","commonFilters","strategies","DEFAULT_STRATEGY","removeExtensions","unpairedPanelHidden","pairedPanelHidden","_dataSetUp","illumina","Rs","simple","lcs","levenshtein","unpaired","_sortInitialList","_ensureIds","autoPair","_sortDatasetList","_splitByFilters","_filter","test","regexFilters","stringFilter","_addToUnpaired","binSearchSortedIndex","low","hi","mid","compared","autopairSimple","autopairLevenshtein","distance","autopairLCS","_naiveStartingAndEndingLCS","s1","s2","fwdLCS","revLCS","fwd","rev","_createPair","_guessNameForPair","forward","fwdName","revName","lastDotIndex","lastIndexOf","_unpair","unpairAll","pairs","_pairToJSON","ajaxData","dataType","_ajaxErrHandler","_renderFilters","_renderUnpaired","_renderPaired","$fwd","$rev","$prd","_renderUnpairedDisplayStr","_renderUnpairedEmpty","_renderPairButton","_renderUnpairedDataset","_adjUnpairedOnScrollbar","_renderUnpairedNotShown","numFiltered","$unpairedColumns","$firstDataset","ucRight","outerWidth","dsRight","rightDiff","_renderPairedEmpty","pairView",".remove-extensions","_chooseFiltersPopover","filterChoice","val1","val2","$popoverContent","filterSet","popover","splitView","msgClass","hideUnpaired","click .forward-column .column-title","click .reverse-column .column-title","click .unpair-all-link","change .forward-unpaired-filter input","focus .forward-unpaired-filter input","click .autopair-link","click .choose-filters .filter-choice","click .clear-filters-link","change .reverse-unpaired-filter input","focus .reverse-unpaired-filter input","click .forward-column .dataset.unpaired","click .reverse-column .dataset.unpaired","click .paired-column .dataset.unpaired","click .unpaired-columns","mousedown .unpaired-columns .dataset","click .paired-column-title","mousedown .flexible-partition-drag","click .paired-columns .dataset.paired","click .paired-columns","click .paired-columns .pair-name","click .unpair-btn","dragover .paired-columns .column-datasets","drop .paired-columns .column-datasets","pair.dragstart .paired-columns .column-datasets","pair.dragend .paired-columns .column-datasets","change .remove-extensions","toggleExtensions","_clickShowOnlyUnpaired","hidePaired","_clickShowOnlyPaired","_clickUnpairAll","_clickAutopair","_clickFilterChoice","$selected","_hideChooseFilters","_clearFilters","_clickUnpairedDataset","toggleSelectUnpaired","$dataset","waitToPair","pairAllSelected","fwds","revs","clearSelectedUnpaired","_mousedownUnpaired","$startTarget","moveListener","document","one","_clickPairRow","rowIndex","_startPartitionDrag","endDrag","unbind","trackMouse","pageY","startingY","adjPartition","mousemove","adj","$unpaired","$paired","unpairedHi","pairedHi","movingUpwards","flex","selectPair","clearSelectedPaired","_clickPairName","$name","$pair","customizedName","_clickUnpair","pairIndex","_dragoverPairedColumns","_getNearestPairedDatasetLi","_dropPairedColumns","_syncPairsToDom","newPaired","_pairDragstart","_pairDragend","_printList","_printPair","levenshteinDistance","matrix","information","password","communication","permissions","api_key","toolbox_filters","openids","custom_builds","logout","Cancel","Sign out","session_csrf_token","$preferences","email","use_remote_user","_addLink","enable_communication_server","has_user_tool_filters","enable_openid","_templateFooter","$row","_templateLink","$a","nice_total_disk_usage","enable_quotas","quota","_uiTable","_uiTable2","installed_builds","Select","empty_text","error_text","table","addHeader","appendHeader","$installed","$form","_renderForm","delAll","ButtonIcon","area","input_field","_renderHelp","len_type","_templateFasta","_templateLen","grid","_templateShared","$tmpl","shared_by_others","display_url","username","slug","_toastr","mod_toastr","_workflowModel","_workflowModel2","WorkflowItemView","bindAll","timeOut","click #show-in-tool-panel","click #delete-workflow","click #rename-workflow","click #copy-workflow","_rowTemplate","showInToolPanel","removeWorkflow","wfName","renameWorkflow","oldName","copyWorkflow","wfJson","currentOwner","at","resp","errorThrown","jqXHR","textStatus","wfId","checkboxHtml","trHtml","_templateActions","renderTagEditor","TagEditor","WorkflowListView","WorkflowCollection","appendItem","unhighlightDropZone","readWorkflowFiles","reader","FileReader","onload","theFile","wf_json","readAsText","_showArgErrors","msg_text","_templateHeader","templateActions","_templateActionButtons","tableTemplate","_templateWorkflowTable","confirmDelete","searchWorkflow","adjustActiondropdown","workflowItemView","workflow","$el_searchinput","$el_tabletr","min_querylen","query","regular_expression","_templateNoWorkflow","tableHtml","_mainTemplate","myexperiment_target_url","WorkflowItem","operation","_showCopyDialog","reload","data_url","job_url","job","render_error_page","error_response","display_message","stderr","_getBugFormTemplate","doNotClear","safe","UnescapedMessage","floating","form_data","_createTabs","initial_message","_reloadHistory","attribute","_getAttribute","conversion","_getConversion","datatype","_getDatatype","permission","_getPermission","operations","submit_attributes","submit_autodetect","submit_conversion","submit_datatype","submit_permission"],"mappings":"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oCACA,SACA,kDACA,oCACA,SACA,SACA,mCACA,gDACA,EAAA9P,EAAA1J,SAAG,kBACH,WACA,8BACA,iDACA,8BACA,SACA,0DACA,EAAA0J,EAAA1J,SAAG,cACH,OACA,SACA,SACA,+EACA,oCACA,UACFwH,KAAK,KAIX+b,OAAQhkB,EAAEia,UAEF,iCACA,sBACA,6CACA,EAAA9P,EAAA1J,SAAG,0BACH,IACA,8DACA,WACA,6CACA,EAAA0J,EAAA1J,SAAG,0CACH,IACA,iEACA,WACA,SACA,sBACA,0DACA,iBACA,EAAA0J,EAAA1J,SAAG,kCACH,OACA,mDACA,EAAA0J,EAAA1J,SAAG,QACH,UACA,SACA,SAEA,gDACA,wCACA,oDACA,EAAA0J,EAAA1J,SAAG,UACH,YACA,8CACA,2EACA,EAAA0J,EAAA1J,SAAG,yCACH,+BACA,YACA,yCACA,oBACA,EAAA0J,EAAA1J,SAAG,+BACH,YACA,oBACA,EAAA0J,EAAA1J,SAAG,6CACH,YACA,QACA,SACA,SAEA,wCACA,sDACA,EAAA0J,EAAA1J,SAAG,eACH,YACA,SACA,UACFwH,KAAK,KAIXgX,YAAajf,EAAEia,UAEP,OACA,EAAA9P,EAAA1J,UAEQ,wGACA,2GACA,yGACA,sCACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,8FACA,yDACA,wFACA,iCACA,8BACA,sEACA,yDACA,4CACA,sEACA,yDACA,QACA,6DACA,qEACA,uDACA,4CACA,QACA,6DACA,4DACA,QACA,SACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,gEACA,oDACA,yEACA,sEACA,QACA,8DACA,mEACA,QACA,iEACA,8FACA,uEACA,6CACA,QACA,4CACA,iEACA,QACA,SACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,iDACA,2FACA,0FACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,sGACA,qGACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,4FACA,gEACA,oEACFwH,KAAK,KAEX,QACF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","file":"analysis.bundled.js","sourcesContent":["webpackJsonp([0],[\n/* 0 */,\n/* 1 */,\n/* 2 */,\n/* 3 */,\n/* 4 */,\n/* 5 */,\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */,\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar View = Backbone.View.extend({\n optionsDefault: {\n with_close: true,\n title: null,\n placement: \"top\",\n container: \"body\",\n body: null\n },\n\n initialize: function initialize(options) {\n this.setElement(this._template());\n this.uid = _utils2.default.uid();\n this.options = _.defaults(options || {}, this.optionsDefault);\n this.options.container.parent().append(this.el);\n this.$title = this.$(\".popover-title-label\");\n this.$close = this.$(\".popover-close\");\n this.$body = this.$(\".popover-content\");\n\n // add initial content\n this.options.body && this.append(this.options.body);\n\n // add event to hide if click is outside of popup and not on container\n var self = this;\n $(\"body\").on(\"mousedown.\" + this.uid, function (e) {\n // the 'is' for buttons that trigger popups\n // the 'has' for icons within a button that triggers a popup\n self.visible && !$(self.options.container).is(e.target) && !$(self.el).is(e.target) && $(self.el).has(e.target).length === 0 && self.hide();\n });\n },\n\n /**\n * Render popover\n */\n render: function render() {\n this.$title.html(this.options.title);\n this.$el.removeClass().addClass(\"ui-popover popover fade in\").addClass(this.options.placement);\n this.$el.css(this._get_placement(this.options.placement));\n\n // configure close option\n var self = this;\n if (this.options.with_close) {\n this.$close.on(\"click\", function () {\n self.hide();\n }).show();\n } else {\n this.$close.off().hide();\n }\n },\n\n /**\n * Set the popover title\n * @params{ String } newTitle - New popover title\n */\n title: function title(newTitle) {\n if (newTitle !== undefined) {\n this.options.title = newTitle;\n this.$title.html(newTitle);\n }\n },\n\n /**\n * Show popover\n */\n show: function show() {\n this.render();\n this.$el.show();\n this.visible = true;\n },\n\n /**\n * Hide popover\n */\n hide: function hide() {\n this.$el.hide();\n this.visible = false;\n },\n\n /**\n * Append new content to the popover\n * @params{ Object } $el - Dom element\n */\n append: function append($el) {\n this.$body.append($el);\n },\n\n /**\n * Remove all content\n */\n empty: function empty() {\n this.$body.empty();\n },\n\n /**\n * Remove popover\n */\n remove: function remove() {\n $(\"body\").off(\"mousedown.\" + this.uid);\n this.$el.remove();\n },\n\n /**\n * Improve popover location/placement\n */\n _get_placement: function _get_placement(placement) {\n // get popover dimensions\n var width = this._get_width(this.$el);\n var height = this.$el.height();\n\n // get container details\n var $container = this.options.container;\n var container_width = this._get_width($container);\n var container_height = this._get_height($container);\n var container_position = $container.position();\n\n // get position\n var top;\n\n var left;\n top = left = 0;\n if ([\"top\", \"bottom\"].indexOf(placement) != -1) {\n left = container_position.left - width + (container_width + width) / 2;\n switch (placement) {\n case \"top\":\n top = container_position.top - height - 5;\n break;\n case \"bottom\":\n top = container_position.top + container_height + 5;\n break;\n }\n } else {\n top = container_position.top - height + (container_height + height) / 2;\n switch (placement) {\n case \"right\":\n left = container_position.left + container_width;\n break;\n }\n }\n return { top: top, left: left };\n },\n\n /**\n * Returns padding/margin corrected width\n */\n _get_width: function _get_width($el) {\n return $el.width() + parseInt($el.css(\"padding-left\")) + parseInt($el.css(\"margin-left\")) + parseInt($el.css(\"padding-right\")) + parseInt($el.css(\"margin-right\"));\n },\n\n /**\n * Returns padding corrected height\n */\n _get_height: function _get_height($el) {\n return $el.height() + parseInt($el.css(\"padding-top\")) + parseInt($el.css(\"padding-bottom\"));\n },\n\n /**\n * Return the popover template\n */\n _template: function _template(options) {\n return '
' + '
' + '
' + '
' + '' + \"
\" + '
' + \"
\";\n }\n}); /**\n * Popover wrapper\n */\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n//==============================================================================\n/** Map of possible HDA/collection/job states to their string equivalents.\n * A port of galaxy.model.Dataset.states.\n */\nvar STATES = {\n // NOT ready states\n /** is uploading and not ready */\n UPLOAD: \"upload\",\n /** the job that will produce the dataset queued in the runner */\n QUEUED: \"queued\",\n /** the job that will produce the dataset is running */\n RUNNING: \"running\",\n /** metadata for the dataset is being discovered/set */\n SETTING_METADATA: \"setting_metadata\",\n\n // ready states\n /** was created without a tool */\n NEW: \"new\",\n /** has no data */\n EMPTY: \"empty\",\n /** has successfully completed running */\n OK: \"ok\",\n\n /** the job that will produce the dataset paused */\n PAUSED: \"paused\",\n /** metadata discovery/setting failed or errored (but otherwise ok) */\n FAILED_METADATA: \"failed_metadata\",\n //TODO: not in trans.app.model.Dataset.states - is in database\n /** not accessible to the current user (i.e. due to permissions) */\n NOT_VIEWABLE: \"noPermission\",\n /** deleted while uploading */\n DISCARDED: \"discarded\",\n /** the tool producing this dataset failed */\n ERROR: \"error\"\n};\n\nSTATES.READY_STATES = [STATES.OK, STATES.EMPTY, STATES.PAUSED, STATES.FAILED_METADATA, STATES.NOT_VIEWABLE, STATES.DISCARDED, STATES.ERROR];\n\nSTATES.NOT_READY_STATES = [STATES.UPLOAD, STATES.QUEUED, STATES.RUNNING, STATES.SETTING_METADATA, STATES.NEW];\n\n//==============================================================================\nexports.default = STATES;\n\n/***/ }),\n/* 12 */,\n/* 13 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * A plugin for initializing select2 input items.\n * Make sure the select2 library itself is loaded beforehand.\n * Also the element to which select2 will be appended has to\n * be created before select2 initialization (and passed as option).\n */\nvar View = Backbone.View.extend({\n // options\n optionsDefault: {\n css: \"\",\n placeholder: \"No data available\",\n data: [],\n value: null,\n multiple: false,\n minimumInputLength: 0,\n // example format of initial data: \"id:name,55:anotherrole@role.com,27:role@role.com\"\n initialData: \"\"\n },\n\n // initialize\n initialize: function initialize(options) {\n // configure options\n this.options = _utils2.default.merge(options, this.optionsDefault);\n\n // create new element\n this.setElement(this._template(this.options));\n\n // check if container exists\n if (!this.options.container) {\n console.log(\"ui-select::initialize() : container not specified.\");\n return;\n }\n\n // add to dom\n this.options.container.append(this.$el);\n\n // link selection dictionary\n this.select_data = this.options.data;\n\n // refresh\n this._refresh();\n\n if (!this.options.multiple) {\n // initial value\n if (this.options.value) {\n this._setValue(this.options.value);\n }\n\n // add change event\n var self = this;\n if (this.options.onchange) {\n this.$el.on(\"change\", function () {\n self.options.onchange(self.value());\n });\n }\n }\n },\n\n // value\n value: function value(new_value) {\n // get current id/value\n var before = this._getValue();\n\n // check if new_value is defined\n if (new_value !== undefined) {\n this._setValue(new_value);\n }\n\n // get current id/value\n var after = this._getValue();\n\n // fire onchange\n if (after != before && this.options.onchange) {\n this.options.onchange(after);\n }\n\n // return current value\n return after;\n },\n\n // label\n text: function text() {\n return this.$el.select2(\"data\").text;\n },\n\n // disabled\n disabled: function disabled() {\n return !this.$el.select2(\"enable\");\n },\n\n // enable\n enable: function enable() {\n this.$el.select2(\"enable\", true);\n },\n\n // disable\n disable: function disable() {\n this.$el.select2(\"enable\", false);\n },\n\n // add\n add: function add(options) {\n // add options\n this.select_data.push({\n id: options.id,\n text: options.text\n });\n\n // refresh\n this._refresh();\n },\n\n // remove\n del: function del(id) {\n // search option\n var index = this._getIndex(id);\n\n // check if found\n if (index != -1) {\n // remove options\n this.select_data.splice(index, 1);\n\n // refresh\n this._refresh();\n }\n },\n\n // remove\n remove: function remove() {\n this.$el.select2(\"destroy\");\n },\n\n // update\n update: function update(options) {\n // copy options\n this.select_data = [];\n for (var key in options.data) {\n this.select_data.push(options.data[key]);\n }\n\n // refresh\n this._refresh();\n },\n\n // refresh\n _refresh: function _refresh() {\n // add select2 data based on type of input\n if (!this.options.multiple) {\n var selected = this._getValue();\n var select_opt = {\n data: this.select_data,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n dropdownAutoWidth: true\n };\n this.$el.select2(select_opt);\n // select previous value (if exists)\n this._setValue(selected);\n } else {\n var select_opt = {\n multiple: this.options.multiple,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n minimumInputLength: this.options.minimumInputLength,\n ajax: this.options.ajax,\n dropdownCssClass: this.options.dropdownCssClass,\n escapeMarkup: this.options.escapeMarkup,\n formatResult: this.options.formatResult,\n formatSelection: this.options.formatSelection,\n initSelection: this.options.initSelection,\n initialData: this.options.initialData\n };\n this.$el.select2(select_opt);\n }\n },\n\n // get index\n _getIndex: function _getIndex(value) {\n // returns the index of the searched value\n _.findIndex(this.select_data, { id: value });\n },\n\n // get value\n _getValue: function _getValue() {\n return this.$el.select2(\"val\");\n },\n\n // set value\n _setValue: function _setValue(new_value) {\n var index = this._getIndex(new_value);\n if (index == -1) {\n if (this.select_data.length > 0) {\n new_value = this.select_data[0].id;\n }\n }\n this.$el.select2(\"val\", new_value);\n },\n\n // element\n _template: function _template(options) {\n return \"\";\n }\n}); // dependencies\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n\"use_strict\";\n\nvar $ = _jquery2.default;\n//============================================================================\n/** Returns a jQuery object containing a clickable font-awesome button.\n * options:\n * tooltipConfig : option map for bootstrap tool tip\n * classes : array of class names (will always be classed as icon-btn)\n * disabled : T/F - add the 'disabled' class?\n * title : tooltip/title string\n * target : optional href target\n * href : optional href\n * faIcon : which font awesome icon to use\n * onclick : function to call when the button is clicked\n */\nvar faIconButton = function faIconButton(options) {\n options = options || {};\n options.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n\n options.classes = [\"icon-btn\"].concat(options.classes || []);\n if (options.disabled) {\n options.classes.push(\"disabled\");\n }\n\n var html = ['',\n // could go with something less specific here - like 'html'\n '', \"\"].join(\"\");\n var $button = $(html).tooltip(options.tooltipConfig);\n if (_.isFunction(options.onclick)) {\n $button.click(options.onclick);\n }\n return $button;\n};\n\n//============================================================================\nexports.default = faIconButton;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 15 */,\n/* 16 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nvar Model = Backbone.Model.extend({\n defaults: {\n extension: \"auto\",\n genome: \"?\",\n url_paste: \"\",\n status: \"init\",\n info: null,\n file_name: \"\",\n file_mode: \"\",\n file_size: 0,\n file_type: null,\n file_path: \"\",\n file_data: null,\n percentage: 0,\n space_to_tab: false,\n to_posix_lines: true,\n enabled: true\n },\n reset: function reset(attr) {\n this.clear().set(this.defaults).set(attr);\n }\n});\nvar Collection = Backbone.Collection.extend({ model: Model });\nexports.default = { Model: Model, Collection: Collection };\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 17 */,\n/* 18 */,\n/* 19 */,\n/* 20 */,\n/* 21 */,\n/* 22 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// =============================================================================\n/** A view on any model that has a 'tags' attribute (a list of tag strings)\n * Incorporates the select2 jQuery plugin for tags display/editing:\n * http://ivaynberg.github.io/select2/\n */\nvar TagsEditor = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.HiddenUntilActivatedViewMixin).extend({\n tagName: \"div\",\n className: \"tags-display\",\n select_width: \"100%\",\n events: {},\n\n /** Set up listeners, parse options */\n initialize: function initialize(options) {\n //console.debug( this, options );\n // only listen to the model only for changes to tags - re-render\n this.show_editor = false;\n if (options.usePrompt === false) {\n this.label = \"\";\n } else {\n this.label = \"\";\n }\n this.workflow_mode = options.workflow_mode || false;\n if (this.workflow_mode) {\n this.events.click = \"showEditor\";\n this.events.keydown = \"keydownHandler\";\n }\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function render() {\n var self = this;\n if (this.workflow_mode) {\n this.$el.html(this._workflowTemplate());\n } else {\n this.$el.html(this._defaultTemplate());\n }\n this.$input().select2({\n placeholder: \"Add tags\",\n width: this.workflow_mode ? this.width : this.select_width,\n tags: function tags() {\n // initialize possible tags in the dropdown based on all the tags the user has used so far\n return self._getTagsUsed();\n }\n });\n\n this._setUpBehaviors();\n return this;\n },\n\n _hashToName: function _hashToName(tag) {\n if (tag.startsWith(\"#\")) {\n return \"name:\" + tag.slice(1);\n }\n return tag;\n },\n\n _nameToHash: function _nameToHash(tag) {\n if (tag.startsWith(\"name:\")) {\n tag = \"#\" + tag.slice(5);\n }\n return tag;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _defaultTemplate: function _defaultTemplate() {\n return [this.label, this._renderEditor()].join(\"\");\n },\n\n _workflowTemplate: function _workflowTemplate() {\n // Shows labels by default, event handler controls whether we show tags or editor\n return [this.show_editor ? this._renderEditor() : this._renderTags()].join(\" \");\n },\n\n keydownHandler: function keydownHandler(e) {\n switch (e.which) {\n // esc\n case 27:\n // hide the tag editor when pressing escape\n this.hideEditor();\n break;\n }\n },\n\n showEditor: function showEditor() {\n this.show_editor = true;\n this.render();\n },\n\n hideEditor: function hideEditor() {\n this.show_editor = false;\n this.render();\n },\n\n _renderEditor: function _renderEditor() {\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n return \"\";\n },\n\n _renderTags: function _renderTags() {\n var tags = this.model.get(\"tags\");\n var addButton = \"static/images/fugue/tag--plus.png\";\n var renderedArray = [];\n _.each(tags, function (tag) {\n tag = tag.indexOf(\"name:\") == 0 ? tag.slice(5) : tag;\n var renderString = \"\" + tag + \"\";\n renderedArray.push(renderString);\n });\n if (renderedArray.length === 0) {\n // If there are no tags to render we just show the add-tag-button\n renderedArray.push(\"\");\n }\n return renderedArray.join(\" \");\n },\n\n /** @returns {String} the sorted, comma-separated tags from the model */\n tagsToCSV: function tagsToCSV() {\n var self = this;\n var tagsArray = this.model.get(\"tags\");\n if (!_.isArray(tagsArray) || _.isEmpty(tagsArray)) {\n return \"\";\n }\n return tagsArray.map(function (tag) {\n return _.escape(self._nameToHash(tag));\n }).sort().join(\",\");\n },\n\n /** @returns {jQuery} the input for this view */\n $input: function $input() {\n return this.$el.find(\"input.tags-input\");\n },\n\n /** @returns {String[]} all tags used by the current user */\n _getTagsUsed: function _getTagsUsed() {\n //TODO: global\n var self = this;\n return _.map(Galaxy.user.get(\"tags_used\"), self._nameToHash);\n },\n\n /** set up any event listeners on the view's DOM (mostly handled by select2) */\n _setUpBehaviors: function _setUpBehaviors() {\n var self = this;\n this.$input().on(\"change\", function (event) {\n // Modify any 'hashtag' 'nametags'\n event.val = _.map(event.val, self._hashToName);\n // save the model's tags in either remove or added event\n self.model.save({ tags: event.val });\n // if it's new, add the tag to the users tags\n if (event.added) {\n //??: solve weird behavior in FF on test.galaxyproject.org where\n // event.added.text is string object: 'String{ 0=\"o\", 1=\"n\", 2=\"e\" }'\n self._addNewTagToTagsUsed(\"\" + event.added.text);\n }\n });\n },\n\n /** add a new tag (if not already there) to the list of all tags used by the user\n * @param {String} newTag the tag to add to the list of used\n */\n _addNewTagToTagsUsed: function _addNewTagToTagsUsed(newTag) {\n //TODO: global\n var tagsUsed = Galaxy.user.get(\"tags_used\");\n if (!_.contains(tagsUsed, newTag)) {\n tagsUsed.push(newTag);\n tagsUsed.sort();\n Galaxy.user.set(\"tags_used\", tagsUsed);\n }\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function remove() {\n this.$input.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function toString() {\n return [\"TagsEditor(\", \"\" + this.model, \")\"].join(\"\");\n }\n});\n\nexports.default = {\n TagsEditor: TagsEditor\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 23 */,\n/* 24 */,\n/* 25 */,\n/* 26 */,\n/* 27 */,\n/* 28 */,\n/* 29 */,\n/* 30 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nvar _queryStringParsing = __webpack_require__(8);\n\nvar _queryStringParsing2 = _interopRequireDefault(_queryStringParsing);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar $ = _jquery2.default;\n\n\nvar Router = Backbone.Router.extend({\n // TODO: not many client routes at this point - fill and remove from server.\n // since we're at root here, this may be the last to be routed entirely on the client.\n initialize: function initialize(page, options) {\n this.page = page;\n this.options = options;\n },\n\n /** helper to push a new navigation state */\n push: function push(url, data) {\n data = data || {};\n data.__identifer = Math.random().toString(36).substr(2);\n if (!$.isEmptyObject(data)) {\n url += url.indexOf(\"?\") == -1 ? \"?\" : \"&\";\n url += $.param(data, true);\n }\n Galaxy.params = data;\n this.navigate(url, { trigger: true });\n },\n\n /** override to parse query string into obj and send to each route */\n execute: function execute(callback, args, name) {\n Galaxy.debug(\"router execute:\", callback, args, name);\n var queryObj = _queryStringParsing2.default.parse(args.pop());\n args.push(queryObj);\n if (callback) {\n if (this.authenticate(args, name)) {\n callback.apply(this, args);\n } else {\n this.access_denied();\n }\n }\n },\n\n authenticate: function authenticate(args, name) {\n return true;\n },\n\n access_denied: function access_denied() {\n this.page.display(new _uiMisc2.default.Message({\n status: \"danger\",\n message: \"You must be logged in with proper credentials to make this request.\",\n persistent: true\n }));\n }\n});\n\nexports.default = Router;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 31 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n options: {\n class_check: \"fa-check-square-o\",\n class_uncheck: \"fa-square-o\",\n parameters: [{\n id: \"space_to_tab\",\n title: \"Convert spaces to tabs\"\n }, {\n id: \"to_posix_lines\",\n title: \"Use POSIX standard\"\n }]\n },\n\n initialize: function initialize(options) {\n var self = this;\n this.model = options.model;\n this.setElement($(\"\").addClass(\"upload-settings\"));\n this.$el.append($(\"\").addClass(\"upload-settings-cover\"));\n this.$el.append($(\"
\";\n },\n\n /** Template of main view */\n _template: function _template() {\n return \"
\" + this.model.get(\"help_text\") + \"
Available files:
Name
Size
Created
Your FTP directory does not contain any files.
\";\n \"
\";\n }\n}); /** This renders the content of the ftp popup **/\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 33 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** This renders a popover with extension details **/\nexports.default = Backbone.View.extend({\n initialize: function initialize(options) {\n this.model = new Backbone.Model(options);\n this.setElement(\"\");\n this.render();\n },\n\n render: function render() {\n var self = this;\n var options = this.model.attributes;\n var description = _.findWhere(options.list, {\n id: options.extension\n });\n this.extension_popup && this.extension_popup.remove();\n this.extension_popup = new _uiPopover2.default.View({\n placement: options.placement || \"bottom\",\n container: options.$el\n });\n this.extension_popup.title(options.title);\n this.extension_popup.empty();\n this.extension_popup.append(this._templateDescription(description));\n this.extension_popup.show();\n },\n\n /** Template for extensions description */\n _templateDescription: function _templateDescription(options) {\n if (options.description) {\n var tmpl = options.description;\n if (options.description_url) {\n tmpl += \" (read more)\";\n }\n return tmpl;\n } else {\n return \"There is no description available for this file extension.\";\n }\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 34 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery, _) {\n\n/*\n galaxy upload plugins - requires FormData and XMLHttpRequest\n*/\n(function ($) {\n // add event properties\n jQuery.event.props.push(\"dataTransfer\");\n\n /**\n Posts file data to the API\n */\n $.uploadpost = function (config) {\n // parse options\n var cnf = $.extend({}, {\n data: {},\n success: function success() {},\n error: function error() {},\n progress: function progress() {},\n url: null,\n maxfilesize: 2048,\n error_filesize: \"File exceeds 2GB. Please use a FTP client.\",\n error_default: \"Please make sure the file is available.\",\n error_server: \"Upload request failed.\",\n error_login: \"Uploads require you to log in.\"\n }, config);\n\n // link data\n var data = cnf.data;\n\n // check errors\n if (data.error_message) {\n cnf.error(data.error_message);\n return;\n }\n\n // construct form data\n var form = new FormData();\n for (var key in data.payload) {\n form.append(key, data.payload[key]);\n }\n\n // add files to submission\n var sizes = 0;\n for (var key in data.files) {\n var d = data.files[key];\n form.append(d.name, d.file, d.file.name);\n sizes += d.file.size;\n }\n\n // check file size, unless it's an ftp file\n if (sizes > 1048576 * cnf.maxfilesize) {\n cnf.error(cnf.error_filesize);\n return;\n }\n\n // prepare request\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", cnf.url, true);\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n\n // captures state changes\n xhr.onreadystatechange = function () {\n // check for request completed, server connection closed\n if (xhr.readyState == xhr.DONE) {\n // parse response\n var response = null;\n var extra_info = \"\";\n if (xhr.responseText) {\n try {\n response = jQuery.parseJSON(xhr.responseText);\n extra_info = response.err_msg;\n } catch (e) {\n response = xhr.responseText;\n extra_info = response;\n }\n }\n // pass any error to the error option\n if (xhr.status < 200 || xhr.status > 299) {\n var text = xhr.statusText;\n if (xhr.status == 403) {\n text = cnf.error_login;\n } else if (xhr.status == 0) {\n text = cnf.error_server;\n } else if (!text) {\n text = cnf.error_default;\n }\n cnf.error(text + \" (\" + xhr.status + \"). \" + extra_info);\n } else {\n cnf.success(response);\n }\n }\n };\n\n // prepare upload progress\n xhr.upload.addEventListener(\"progress\", function (e) {\n if (e.lengthComputable) {\n cnf.progress(Math.round(e.loaded * 100 / e.total));\n }\n }, false);\n\n // send request\n Galaxy.emit.debug(\"uploadbox::uploadpost()\", \"Posting following data.\", cnf);\n xhr.send(form);\n };\n\n /**\n Handles the upload events drag/drop etc.\n */\n $.fn.uploadinput = function (options) {\n // initialize\n var el = this;\n var opts = $.extend({}, {\n ondragover: function ondragover() {},\n ondragleave: function ondragleave() {},\n onchange: function onchange() {},\n multiple: false\n }, options);\n\n // append hidden upload field\n var $input = $(\"\");\n el.append($input.change(function (e) {\n opts.onchange(e.target.files);\n $(this).val(\"\");\n }));\n\n // drag/drop events\n el.on(\"drop\", function (e) {\n opts.ondragleave(e);\n if (e.dataTransfer) {\n opts.onchange(e.dataTransfer.files);\n e.preventDefault();\n }\n });\n el.on(\"dragover\", function (e) {\n e.preventDefault();\n opts.ondragover(e);\n });\n el.on(\"dragleave\", function (e) {\n e.stopPropagation();\n opts.ondragleave(e);\n });\n\n // exports\n return {\n dialog: function dialog() {\n $input.trigger(\"click\");\n }\n };\n };\n\n /**\n Handles the upload queue and events such as drag/drop etc.\n */\n $.fn.uploadbox = function (options) {\n // parse options\n var opts = $.extend({}, {\n dragover: function dragover() {},\n dragleave: function dragleave() {},\n announce: function announce(d) {},\n initialize: function initialize(d) {},\n progress: function progress(d, m) {},\n success: function success(d, m) {},\n error: function error(d, m) {\n alert(m);\n },\n complete: function complete() {}\n }, options);\n\n // file queue\n var queue = {};\n\n // queue index/length counter\n var queue_index = 0;\n var queue_length = 0;\n\n // indicates if queue is currently running\n var queue_running = false;\n var queue_stop = false;\n\n // element\n var uploadinput = $(this).uploadinput({\n multiple: true,\n onchange: function onchange(files) {\n add(files);\n },\n ondragover: options.ondragover,\n ondragleave: options.ondragleave\n });\n\n // add new files to upload queue\n function add(files) {\n if (files && files.length && !queue_running) {\n var index = undefined;\n _.each(files, function (file, key) {\n if (file.mode !== \"new\" && _.filter(queue, function (f) {\n return f.name === file.name && f.size === file.size;\n }).length) {\n file.duplicate = true;\n }\n });\n _.each(files, function (file) {\n if (!file.duplicate) {\n index = String(queue_index++);\n queue[index] = file;\n opts.announce(index, queue[index]);\n queue_length++;\n }\n });\n return index;\n }\n }\n\n // remove file from queue\n function remove(index) {\n if (queue[index]) {\n delete queue[index];\n queue_length--;\n }\n }\n\n // process an upload, recursive\n function process() {\n // validate\n if (queue_length == 0 || queue_stop) {\n queue_stop = false;\n queue_running = false;\n opts.complete();\n return;\n } else {\n queue_running = true;\n }\n\n // get an identifier from the queue\n var index = -1;\n for (var key in queue) {\n index = key;\n break;\n }\n\n // get current file from queue\n var file = queue[index];\n\n // remove from queue\n remove(index);\n\n // create and submit data\n $.uploadpost({\n url: opts.url,\n data: opts.initialize(index),\n success: function success(message) {\n opts.success(index, message);\n process();\n },\n error: function error(message) {\n opts.error(index, message);\n process();\n },\n progress: function progress(percentage) {\n opts.progress(index, percentage);\n }\n });\n }\n\n /*\n public interface\n */\n\n // open file browser for selection\n function select() {\n uploadinput.dialog();\n }\n\n // remove all entries from queue\n function reset(index) {\n for (index in queue) {\n remove(index);\n }\n }\n\n // initiate upload process\n function start() {\n if (!queue_running) {\n queue_running = true;\n process();\n }\n }\n\n // stop upload process\n function stop() {\n queue_stop = true;\n }\n\n // set options\n function configure(options) {\n opts = $.extend({}, opts, options);\n return opts;\n }\n\n // verify browser compatibility\n function compatible() {\n return window.File && window.FormData && window.XMLHttpRequest && window.FileList;\n }\n\n // export functions\n return {\n select: select,\n add: add,\n remove: remove,\n start: start,\n stop: stop,\n reset: reset,\n configure: configure,\n compatible: compatible\n };\n };\n})(jQuery);\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 35 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _hdcaModel = __webpack_require__(36);\n\nvar _hdcaModel2 = _interopRequireDefault(_hdcaModel);\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _baseCreator = __webpack_require__(74);\n\nvar _baseCreator2 = _interopRequireDefault(_baseCreator);\n\nvar _uiModal = __webpack_require__(7);\n\nvar _uiModal2 = _interopRequireDefault(_uiModal);\n\nvar _naturalSort = __webpack_require__(75);\n\nvar _naturalSort2 = _interopRequireDefault(_naturalSort);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(76);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"collections\";\n\n/*==============================================================================\nTODO:\n use proper Element model and not just json\n straighten out createFn, collection.createHDCA\n possibly stop using modals for this\n It would be neat to do a drag and drop\n\n==============================================================================*/\n/** A view for both DatasetDCEs and NestedDCDCEs\n * (things that implement collection-model:DatasetCollectionElementMixin)\n */\nvar DatasetCollectionElementView = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))\n tagName: \"li\",\n className: \"collection-element\",\n\n initialize: function initialize(attributes) {\n this.element = attributes.element || {};\n this.selected = attributes.selected || false;\n },\n\n render: function render() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el.attr(\"data-element-id\", this.element.id).attr(\"draggable\", true).html(this.template({ element: this.element })).get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n if (this.selected) {\n this.$el.addClass(\"selected\");\n }\n return this;\n },\n\n //TODO: lots of unused space in the element - possibly load details and display them horiz.\n template: _.template(['', \"<%- element.name %>\", \"\", '\"].join(\"\")),\n\n /** select this element and pub */\n select: function select(toggle) {\n this.$el.toggleClass(\"selected\", toggle);\n this.trigger(\"select\", {\n source: this,\n selected: this.$el.hasClass(\"selected\")\n });\n },\n\n /** animate the removal of this element and pub */\n discard: function discard() {\n var view = this;\n var parentWidth = this.$el.parent().width();\n this.$el.animate({ \"margin-right\": parentWidth }, \"fast\", function () {\n view.trigger(\"discard\", {\n source: view\n });\n view.destroy();\n });\n },\n\n /** remove the DOM and any listeners */\n destroy: function destroy() {\n this.off();\n this.$el.remove();\n },\n\n events: {\n click: \"_click\",\n \"click .name\": \"_clickName\",\n \"click .discard\": \"_clickDiscard\",\n\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** select when the li is clicked */\n _click: function _click(ev) {\n ev.stopPropagation();\n this.select(ev);\n },\n\n /** rename a pair when the name is clicked */\n _clickName: function _clickName(ev) {\n ev.stopPropagation();\n ev.preventDefault();\n\n var promptString = [(0, _localization2.default)(\"Enter a new name for the element\"), \":\\n(\", (0, _localization2.default)(\"Note that changing the name here will not rename the dataset\"), \")\"].join(\"\");\n\n var response = prompt((0, _localization2.default)(\"Enter a new name for the element\") + \":\", this.element.name);\n\n if (response) {\n this.element.name = response;\n this.render();\n }\n //TODO: cancelling with ESC leads to closure of the creator...\n },\n\n /** discard when the discard button is clicked */\n _clickDiscard: function _clickDiscard(ev) {\n ev.stopPropagation();\n this.discard();\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function _dragstart(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.element));\n\n this.$el.addClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragstart\", [this]);\n },\n\n /** dragging for re-ordering */\n _dragend: function _dragend(ev) {\n this.$el.removeClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function _sendToParent(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function toString() {\n return \"DatasetCollectionElementView()\";\n }\n});\n\n// ============================================================================\n/** An interface for building collections.\n */\nvar ListCollectionCreator = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseCreator2.default.CollectionCreatorMixin).extend({\n _logNamespace: logNamespace,\n\n /** the class used to display individual elements */\n elementViewClass: DatasetCollectionElementView,\n /** the class this creator will create and save */\n collectionClass: _hdcaModel2.default.HistoryListDatasetCollection,\n className: \"list-collection-creator collection-creator flex-row-container\",\n\n /** minimum number of valid elements to start with in order to build a collection of this type */\n minElements: 1,\n\n defaultAttributes: {\n //TODO: remove - use new collectionClass().save()\n /** takes elements and creates the proper collection - returns a promise */\n creationFn: function creationFn() {\n throw new TypeError(\"no creation fn for creator\");\n },\n /** fn to call when the collection is created (scoped to this) */\n oncreate: function oncreate() {},\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n oncancel: function oncancel() {},\n /** distance from list edge to begin autoscrolling list */\n autoscrollDist: 24,\n /** Color passed to hoverhighlight */\n highlightClr: \"rgba( 64, 255, 255, 1.0 )\"\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\"\n },\n\n /** set up initial options, instance vars, behaviors */\n initialize: function initialize(attributes) {\n this.metric(\"ListCollectionCreator.initialize\", attributes);\n var creator = this;\n _.each(this.defaultAttributes, function (value, key) {\n value = attributes[key] || value;\n creator[key] = value;\n });\n\n /** unordered, original list - cache to allow reversal */\n creator.initialElements = attributes.elements || [];\n\n this._setUpCommonSettings(attributes);\n this._instanceSetUp();\n this._elementsSetUp();\n this._setUpBehaviors();\n },\n\n /** set up instance vars */\n _instanceSetUp: function _instanceSetUp() {\n /** Ids of elements that have been selected by the user - to preserve over renders */\n this.selectedIds = {};\n /** DOM elements currently being dragged */\n this.$dragging = null;\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n },\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data */\n _elementsSetUp: function _elementsSetUp() {\n //this.debug( '-- _dataSetUp' );\n /** a list of invalid elements and the reasons they aren't valid */\n this.invalidElements = [];\n //TODO: handle fundamental problem of syncing DOM, views, and list here\n /** data for list in progress */\n this.workingElements = [];\n /** views for workingElements */\n this.elementViews = [];\n\n // copy initial list, sort, add ids if needed\n this.workingElements = this.initialElements.slice(0);\n this._ensureElementIds();\n this._validateElements();\n this._mangleDuplicateNames();\n this._sortElements();\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureElementIds: function _ensureElementIds() {\n this.workingElements.forEach(function (element) {\n if (!element.hasOwnProperty(\"id\")) {\n element.id = _.uniqueId();\n }\n });\n return this.workingElements;\n },\n\n /** separate working list into valid and invalid elements for this collection */\n _validateElements: function _validateElements() {\n var creator = this;\n var existingNames = {};\n creator.invalidElements = [];\n\n this.workingElements = this.workingElements.filter(function (element) {\n var problem = creator._isElementInvalid(element);\n if (problem) {\n creator.invalidElements.push({\n element: element,\n text: problem\n });\n }\n return !problem;\n });\n return this.workingElements;\n },\n\n /** describe what is wrong with a particular element if anything */\n _isElementInvalid: function _isElementInvalid(element) {\n if (element.history_content_type !== \"dataset\") {\n return (0, _localization2.default)(\"is not a dataset\");\n }\n var validState = element.state === _states2.default.OK || _.contains(_states2.default.NOT_READY_STATES, element.state);\n if (!validState) {\n return (0, _localization2.default)(\"has errored, is paused, or is not accessible\");\n }\n if (element.deleted || element.purged) {\n return (0, _localization2.default)(\"has been deleted or purged\");\n }\n return null;\n },\n\n /** mangle duplicate names using a mac-like '(counter)' addition to any duplicates */\n _mangleDuplicateNames: function _mangleDuplicateNames() {\n var SAFETY = 900;\n var counter = 1;\n var existingNames = {};\n this.workingElements.forEach(function (element) {\n var currName = element.name;\n while (existingNames.hasOwnProperty(currName)) {\n currName = element.name + \" (\" + counter + \")\";\n counter += 1;\n if (counter >= SAFETY) {\n throw new Error(\"Safety hit in while loop - thats impressive\");\n }\n }\n element.name = currName;\n existingNames[element.name] = true;\n });\n },\n\n /** sort a list of elements */\n _sortElements: function _sortElements(list) {\n // // currently only natural sort by name\n // this.workingElements.sort( function( a, b ){ return naturalSort( a.name, b.name ); });\n // return this.workingElements;\n },\n\n // ------------------------------------------------------------------------ rendering\n // templates : ListCollectionCreator.templates,\n /** render the entire interface */\n render: function render(speed, callback) {\n //this.debug( '-- _render' );\n if (this.workingElements.length < this.minElements) {\n return this._renderInvalid(speed, callback);\n }\n\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.$(\".collection-name\").focus();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render a simplified interface aimed at telling the user why they can't move forward */\n _renderInvalid: function _renderInvalid(speed, callback) {\n //this.debug( '-- _render' );\n this.$el.empty().html(this.templates.invalidInitial({\n problems: this.invalidElements,\n elements: this.workingElements\n }));\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function _renderHeader(speed, callback) {\n var $header = this.$(\".header\").empty().html(this.templates.header()).find(\".help-content\").prepend($(this.templates.helpContent()));\n //TODO: should only show once despite calling _renderHeader again\n if (this.invalidElements.length) {\n this._invalidElementsAlert();\n }\n return $header;\n },\n\n /** render the middle including the elements */\n _renderMiddle: function _renderMiddle(speed, callback) {\n var $middle = this.$(\".middle\").empty().html(this.templates.middle());\n this._renderList(speed);\n return $middle;\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function _addPluginComponents() {\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", this.highlightClr);\n },\n\n /** build and show an alert describing any elements that could not be included due to problems */\n _invalidElementsAlert: function _invalidElementsAlert() {\n this._showAlert(this.templates.invalidElements({\n problems: this.invalidElements\n }), \"alert-warning\");\n },\n\n _disableNameAndCreate: function _disableNameAndCreate(disable) {\n disable = !_.isUndefined(disable) ? disable : true;\n if (disable) {\n this.$(\".collection-name\").prop(\"disabled\", true);\n this.$(\".create-collection\").toggleClass(\"disabled\", true);\n // } else {\n // this.$( '.collection-name' ).prop( 'disabled', false );\n // this.$( '.create-collection' ).removeClass( 'disable' );\n }\n },\n\n // ------------------------------------------------------------------------ rendering elements\n /** conv. to the main list display DOM */\n $list: function $list() {\n return this.$(\".collection-elements\");\n },\n\n /** show or hide the clear selected control based on the num of selected elements */\n _renderClearSelected: function _renderClearSelected() {\n if (_.size(this.selectedIds)) {\n this.$(\".collection-elements-controls > .clear-selected\").show();\n } else {\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n }\n },\n\n /** render the elements in order (or a warning if no elements found) */\n _renderList: function _renderList(speed, callback) {\n //this.debug( '-- _renderList' );\n var creator = this;\n\n var $tmp = jQuery(\"\");\n var $list = creator.$list();\n\n _.each(this.elementViews, function (view) {\n view.destroy();\n creator.removeElementView(view);\n });\n\n // if( !this.workingElements.length ){\n // this._renderNoValidElements();\n // return;\n // }\n\n creator.workingElements.forEach(function (element) {\n var elementView = creator._createElementView(element);\n $tmp.append(elementView.$el);\n });\n\n creator._renderClearSelected();\n $list.empty().append($tmp.children());\n _.invoke(creator.elementViews, \"render\");\n\n if ($list.height() > $list.css(\"max-height\")) {\n $list.css(\"border-width\", \"1px 0px 1px 0px\");\n } else {\n $list.css(\"border-width\", \"0px\");\n }\n },\n\n /** create an element view, cache in elementViews, set up listeners, and return */\n _createElementView: function _createElementView(element) {\n var elementView = new this.elementViewClass({\n //TODO: use non-generic class or not all\n // model : COLLECTION.DatasetDCE( element )\n element: element,\n selected: _.has(this.selectedIds, element.id)\n });\n this.elementViews.push(elementView);\n this._listenToElementView(elementView);\n return elementView;\n },\n\n /** listen to any element events */\n _listenToElementView: function _listenToElementView(view) {\n var creator = this;\n creator.listenTo(view, {\n select: function select(data) {\n var element = data.source.element;\n if (data.selected) {\n creator.selectedIds[element.id] = true;\n } else {\n delete creator.selectedIds[element.id];\n }\n creator.trigger(\"elements:select\", data);\n },\n discard: function discard(data) {\n creator.trigger(\"elements:discard\", data);\n }\n });\n },\n\n /** add a new element view based on the json in element */\n addElementView: function addElementView(element) {\n //TODO: workingElements is sorted, add element in appropo index\n // add element, sort elements, find element index\n // var view = this._createElementView( element );\n // return view;\n },\n\n /** stop listening to view and remove from caches */\n removeElementView: function removeElementView(view) {\n delete this.selectedIds[view.element.id];\n this._renderClearSelected();\n\n this.elementViews = _.without(this.elementViews, view);\n this.stopListening(view);\n },\n\n /** render a message in the list that no elements remain to create a collection */\n _renderNoElementsLeft: function _renderNoElementsLeft() {\n this._disableNameAndCreate(true);\n this.$(\".collection-elements\").append(this.templates.noElementsLeft());\n },\n\n // /** render a message in the list that no valid elements were found to create a collection */\n // _renderNoValidElements : function(){\n // this._disableNameAndCreate( true );\n // this.$( '.collection-elements' ).append( this.templates.noValidElements() );\n // },\n\n // ------------------------------------------------------------------------ API\n /** convert element into JSON compatible with the collections API */\n _elementToJSON: function _elementToJSON(element) {\n // return element.toJSON();\n return element;\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function createList(name) {\n if (!this.workingElements.length) {\n var message = (0, _localization2.default)(\"No valid elements for final list\") + \". \";\n message += \"\" + (0, _localization2.default)(\"Cancel\") + \" \";\n message += (0, _localization2.default)(\"or\");\n message += \" \" + (0, _localization2.default)(\"start over\") + \".\";\n this._showAlert(message);\n return;\n }\n\n var creator = this;\n\n var elements = this.workingElements.map(function (element) {\n return creator._elementToJSON(element);\n });\n\n creator.blocking = true;\n return creator.creationFn(elements, name, creator.hideOriginals).always(function () {\n creator.blocking = false;\n }).fail(function (xhr, status, message) {\n creator.trigger(\"error\", {\n xhr: xhr,\n status: status,\n message: (0, _localization2.default)(\"An error occurred while creating this collection\")\n });\n }).done(function (response, message, xhr) {\n creator.trigger(\"collection:created\", response, message, xhr);\n creator.metric(\"collection:created\", response);\n if (typeof creator.oncreate === \"function\") {\n creator.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n // ------------------------------------------------------------------------ events\n /** set up event handlers on self */\n _setUpBehaviors: function _setUpBehaviors() {\n this.on(\"error\", this._errorHandler);\n\n this.once(\"rendered\", function () {\n this.trigger(\"rendered:initial\", this);\n });\n\n this.on(\"elements:select\", function (data) {\n this._renderClearSelected();\n });\n\n this.on(\"elements:discard\", function (data) {\n var element = data.source.element;\n this.removeElementView(data.source);\n\n this.workingElements = _.without(this.workingElements, element);\n if (!this.workingElements.length) {\n this._renderNoElementsLeft();\n }\n });\n\n //this.on( 'all', function(){\n // this.info( arguments );\n //});\n return this;\n },\n\n /** handle errors with feedback and details to the user (if available) */\n _errorHandler: function _errorHandler(data) {\n this.error(data);\n\n var creator = this;\n var content = data.message || (0, _localization2.default)(\"An error occurred\");\n if (data.xhr) {\n var xhr = data.xhr;\n var message = data.message;\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += \": \" + (0, _localization2.default)(\"Galaxy could not be reached and may be updating.\") + (0, _localization2.default)(\" Try again in a few minutes.\");\n } else if (xhr.responseJSON) {\n content += \":
\" + JSON.stringify(xhr.responseJSON) + \"
\";\n } else {\n content += \": \" + message;\n }\n }\n creator._showAlert(content, \"alert-danger\");\n },\n\n events: {\n // header\n \"click .more-help\": \"_clickMoreHelp\",\n \"click .less-help\": \"_clickLessHelp\",\n \"click .main-help\": \"_toggleHelp\",\n \"click .header .alert button\": \"_hideAlert\",\n\n \"click .reset\": \"reset\",\n \"click .clear-selected\": \"clearSelectedElements\",\n\n // elements - selection\n \"click .collection-elements\": \"clearSelectedElements\",\n\n // elements - drop target\n // 'dragenter .collection-elements': '_dragenterElements',\n // 'dragleave .collection-elements': '_dragleaveElements',\n \"dragover .collection-elements\": \"_dragoverElements\",\n \"drop .collection-elements\": \"_dropElements\",\n\n // these bubble up from the elements as custom events\n \"collection-element.dragstart .collection-elements\": \"_elementDragstart\",\n \"collection-element.dragend .collection-elements\": \"_elementDragend\",\n\n // footer\n \"change .collection-name\": \"_changeName\",\n \"keydown .collection-name\": \"_nameCheckForEnter\",\n \"change .hide-originals\": \"_changeHideOriginals\",\n \"click .cancel-create\": \"_cancelCreate\",\n \"click .create-collection\": \"_clickCreate\" //,\n },\n\n // ........................................................................ elements\n /** reset all data to the initial state */\n reset: function reset() {\n this._instanceSetUp();\n this._elementsSetUp();\n this.render();\n },\n\n /** deselect all elements */\n clearSelectedElements: function clearSelectedElements(ev) {\n this.$(\".collection-elements .collection-element\").removeClass(\"selected\");\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n },\n\n //_dragenterElements : function( ev ){\n // //this.debug( '_dragenterElements:', ev );\n //},\n //TODO: if selected are dragged out of the list area - remove the placeholder - cuz it won't work anyway\n // _dragleaveElements : function( ev ){\n // //this.debug( '_dragleaveElements:', ev );\n // },\n\n /** track the mouse drag over the list adding a placeholder to show where the drop would occur */\n _dragoverElements: function _dragoverElements(ev) {\n //this.debug( '_dragoverElements:', ev );\n ev.preventDefault();\n\n var $list = this.$list();\n this._checkForAutoscroll($list, ev.originalEvent.clientY);\n var $nearest = this._getNearestElement(ev.originalEvent.clientY);\n\n //TODO: no need to re-create - move instead\n this.$(\".element-drop-placeholder\").remove();\n var $placeholder = $('');\n if (!$nearest.length) {\n $list.append($placeholder);\n } else {\n $nearest.before($placeholder);\n }\n },\n\n /** If the mouse is near enough to the list's top or bottom, scroll the list */\n _checkForAutoscroll: function _checkForAutoscroll($element, y) {\n var AUTOSCROLL_SPEED = 2;\n var offset = $element.offset();\n var scrollTop = $element.scrollTop();\n var upperDist = y - offset.top;\n var lowerDist = offset.top + $element.outerHeight() - y;\n if (upperDist >= 0 && upperDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop - AUTOSCROLL_SPEED);\n } else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop + AUTOSCROLL_SPEED);\n }\n },\n\n /** get the nearest element based on the mouse's Y coordinate.\n * If the y is at the end of the list, return an empty jQuery object.\n */\n _getNearestElement: function _getNearestElement(y) {\n var WIGGLE = 4;\n\n var lis = this.$(\".collection-elements li.collection-element\").toArray();\n\n for (var i = 0; i < lis.length; i++) {\n var $li = $(lis[i]);\n var top = $li.offset().top;\n var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;\n if (top + halfHeight > y && top - halfHeight < y) {\n return $li;\n }\n }\n return $();\n },\n\n /** drop (dragged/selected elements) onto the list, re-ordering the internal list */\n _dropElements: function _dropElements(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n // both required for firefox\n ev.preventDefault();\n ev.dataTransfer.dropEffect = \"move\";\n\n // insert before the nearest element or after the last.\n var $nearest = this._getNearestElement(ev.clientY);\n if ($nearest.length) {\n this.$dragging.insertBefore($nearest);\n } else {\n // no nearest before - insert after last element\n this.$dragging.insertAfter(this.$(\".collection-elements .collection-element\").last());\n }\n // resync the creator's list based on the new DOM order\n this._syncOrderToDom();\n return false;\n },\n\n /** resync the creator's list of elements based on the DOM order */\n _syncOrderToDom: function _syncOrderToDom() {\n var creator = this;\n var newElements = [];\n //TODO: doesn't seem wise to use the dom to store these - can't we sync another way?\n this.$(\".collection-elements .collection-element\").each(function () {\n var id = $(this).attr(\"data-element-id\");\n\n var element = _.findWhere(creator.workingElements, {\n id: id\n });\n\n if (element) {\n newElements.push(element);\n } else {\n console.error(\"missing element: \", id);\n }\n });\n this.workingElements = newElements;\n this._renderList();\n },\n\n /** drag communication with element sub-views: dragstart */\n _elementDragstart: function _elementDragstart(ev, element) {\n // auto select the element causing the event and move all selected\n element.select(true);\n this.$dragging = this.$(\".collection-elements .collection-element.selected\");\n },\n\n /** drag communication with element sub-views: dragend - remove the placeholder */\n _elementDragend: function _elementDragend(ev, element) {\n $(\".element-drop-placeholder\").remove();\n this.$dragging = null;\n },\n\n // ------------------------------------------------------------------------ templates\n //TODO: move to require text plugin and load these as text\n //TODO: underscore currently unnecc. bc no vars are used\n //TODO: better way of localizing text-nodes in long strings\n /** underscore template fns attached to class */\n templates: _.extend({}, _baseCreator2.default.CollectionCreatorMixin._creatorTemplates, {\n /** the header (not including help text) */\n header: _.template(['
\"].join(\"\")),\n\n /** help content */\n helpContent: _.template([\"
\", (0, _localization2.default)([\"Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and \", \"workflows in order to have analyses done on each member of the entire group. This interface allows \", \"you to create a collection and re-order the final collection.\"].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)([\"Rename elements in the list by clicking on \", 'the existing name.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)([\"Discard elements from the final created list by clicking on the \", '\"Discard\" button.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)([\"Reorder the list by clicking and dragging elements. Select multiple elements by clicking on \", 'them and you can then move those selected by dragging the ', \"entire group. Deselect them by clicking them again or by clicking the \", 'the \"Clear selected\" link.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Click the \"Start over\" link to begin again as if you had just opened ', \"the interface.\"].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Click the \"Cancel\" button to exit the interface.'].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)(['Once your collection is complete, enter a name and ', 'click \"Create list\".'].join(\"\")), \"
\"].join(\"\")),\n\n /** shown in list when all elements are discarded */\n invalidElements: _.template([(0, _localization2.default)(\"The following selections could not be included due to problems:\"), \"
<% _.each( problems, function( problem ){ %>\", \"
<%- problem.element.name %>: <%- problem.text %>
\", \"<% }); %>
\"].join(\"\")),\n\n /** shown in list when all elements are discarded */\n noElementsLeft: _.template(['
\"].join(\"\")),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(['
', '
', '', \"<% if( _.size( problems ) ){ %>\", (0, _localization2.default)(\"The following selections could not be included due to problems\"), \":\", \"
<% _.each( problems, function( problem ){ %>\", \"
<%- problem.element.name %>: <%- problem.text %>
\", \"<% }); %>
\", \"<% } else if( _.size( elements ) < 1 ){ %>\", (0, _localization2.default)(\"No datasets were selected\"), \".\", \"<% } %>\", \" \", (0, _localization2.default)(\"At least one element is needed for the collection\"), \". \", (0, _localization2.default)(\"You may need to \"), '', (0, _localization2.default)(\"cancel\"), \" \", (0, _localization2.default)(\"and reselect new elements\"), \".\", \"\", \"
\", \"
\", '\"].join(\"\"))\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function toString() {\n return \"ListCollectionCreator\";\n }\n});\n\n//=============================================================================\n/** Create a modal and load its body with the given CreatorClass creator type\n * @returns {Deferred} resolved when creator has built a collection.\n */\nvar collectionCreatorModal = function _collectionCreatorModal(elements, options, CreatorClass) {\n var deferred = jQuery.Deferred();\n var modal = Galaxy.modal || new _uiModal2.default.View();\n var creator;\n\n options = _.defaults(options || {}, {\n elements: elements,\n oncancel: function oncancel() {\n modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function oncreate(creator, response) {\n modal.hide();\n deferred.resolve(response);\n }\n });\n\n creator = new CreatorClass(options);\n modal.show({\n title: options.title || (0, _localization2.default)(\"Create a collection\"),\n body: creator.$el,\n width: \"80%\",\n height: \"100%\",\n closing_events: true\n });\n creator.render();\n window._collectionCreator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n/** List collection flavor of collectionCreatorModal. */\nvar listCollectionCreatorModal = function _listCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = (0, _localization2.default)(\"Create a collection from a list of datasets\");\n return collectionCreatorModal(elements, options, ListCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a list collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createListCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = listCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function creationFn(elements, name, hideSourceItems) {\n elements = elements.map(function (element) {\n return {\n id: element.id,\n name: element.name,\n\n //TODO: this allows for list:list even if the filter above does not - reconcile\n src: element.history_content_type === \"dataset\" ? \"hda\" : \"hdca\"\n };\n });\n return contents.createHDCA(elements, \"list\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexports.default = {\n DatasetCollectionElementView: DatasetCollectionElementView,\n ListCollectionCreator: ListCollectionCreator,\n\n collectionCreatorModal: collectionCreatorModal,\n listCollectionCreatorModal: listCollectionCreatorModal,\n createListCollection: createListCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 36 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _collectionModel = __webpack_require__(37);\n\nvar _collectionModel2 = _interopRequireDefault(_collectionModel);\n\nvar _historyContentModel = __webpack_require__(73);\n\nvar _historyContentModel2 = _interopRequireDefault(_historyContentModel);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/*==============================================================================\n\nModels for DatasetCollections contained within a history.\n\nTODO:\n these might be compactable to one class if some duplication with\n collection-model is used.\n\n==============================================================================*/\nvar hcontentMixin = _historyContentModel2.default.HistoryContentMixin;\n\nvar ListDC = _collectionModel2.default.ListDatasetCollection;\nvar PairDC = _collectionModel2.default.PairDatasetCollection;\nvar ListPairedDC = _collectionModel2.default.ListPairedDatasetCollection;\nvar ListOfListsDC = _collectionModel2.default.ListOfListsDatasetCollection;\n\n//==============================================================================\n/** Override to post to contents route w/o id. */\nfunction buildHDCASave(_super) {\n return function _save(attributes, options) {\n if (this.isNew()) {\n options = options || {};\n options.url = this.urlRoot + this.get(\"history_id\") + \"/contents\";\n attributes = attributes || {};\n attributes.type = \"dataset_collection\";\n }\n return _super.call(this, attributes, options);\n };\n}\n\n//==============================================================================\n/** @class Backbone model for List Dataset Collection within a History.\n */\nvar HistoryListDatasetCollection = ListDC.extend(hcontentMixin).extend(\n/** @lends HistoryListDatasetCollection.prototype */{\n defaults: _.extend(_.clone(ListDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"History\" + ListDC.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** @class Backbone model for Pair Dataset Collection within a History.\n * @constructs\n */\nvar HistoryPairDatasetCollection = PairDC.extend(hcontentMixin).extend(\n/** @lends HistoryPairDatasetCollection.prototype */{\n defaults: _.extend(_.clone(PairDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(PairDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"History\" + PairDC.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Pairs Dataset Collection within a History. */\nvar HistoryListPairedDatasetCollection = ListPairedDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListPairedDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListPairedDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"History\" + ListPairedDC.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Lists Dataset Collection within a History. */\nvar HistoryListOfListsDatasetCollection = ListOfListsDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListOfListsDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListOfListsDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return [\"HistoryListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n HistoryListDatasetCollection: HistoryListDatasetCollection,\n HistoryPairDatasetCollection: HistoryPairDatasetCollection,\n HistoryListPairedDatasetCollection: HistoryListPairedDatasetCollection,\n HistoryListOfListsDatasetCollection: HistoryListOfListsDatasetCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 37 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, Backbone, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _datasetModel = __webpack_require__(72);\n\nvar _datasetModel2 = _interopRequireDefault(_datasetModel);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/*\nNotes:\n\nTerminology:\n DatasetCollection/DC : a container of datasets or nested DatasetCollections\n Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection\n HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history\n\n\nThis all seems too complex unfortunately:\n\n- Terminology collision between DatasetCollections (DCs) and Backbone Collections.\n- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*\n either a dataset or a nested DC. This would make the hierarchy much taller. I've\n decided to merge the contained JSON with the DC element json - making the 'has a'\n relation into an 'is a' relation. This seems simpler to me and allowed a lot of\n DRY in both models and views, but may make tracking or tracing within these models\n more difficult (since DatasetCollectionElements are now *also* DatasetAssociations\n or DatasetCollections (nested)). This also violates the rule of thumb about\n favoring aggregation over inheritance.\n- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.\n These each should a) be usable on their own, b) be usable in the context of\n nesting within a collection model (at least in the case of ListPaired), and\n c) be usable within the context of other container models (like History or\n LibraryFolder, etc.). I've tried to separate/extract classes in order to\n handle those three situations, but it's proven difficult to do in a simple,\n readable manner.\n- Ideally, histories and libraries would inherit from the same server models as\n dataset collections do since they are (in essence) dataset collections themselves -\n making the whole nested structure simpler. This would be a large, error-prone\n refactoring and migration.\n\nMany of the classes and heirarchy are meant as extension points so, while the\nrelations and flow may be difficult to understand initially, they'll allow us to\nhandle the growth or flux dataset collection in the future (w/o actually implementing\nany YAGNI).\n\n*/\n//_________________________________________________________________________________________________ ELEMENTS\n/** @class mixin for Dataset collection elements.\n * When collection elements are passed from the API, the underlying element is\n * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).\n * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues\n * effectively changing a DCE from a container to a subclass (has a --> is a).\n */\nvar DatasetCollectionElementMixin = {\n /** default attributes used by elements in a dataset collection */\n defaults: {\n model_class: \"DatasetCollectionElement\",\n element_identifier: null,\n element_index: null,\n element_type: null\n },\n\n /** merge the attributes of the sub-object 'object' into this model */\n _mergeObject: function _mergeObject(attributes) {\n // if we don't preserve and correct ids here, the element id becomes the object id\n // and collision in backbone's _byId will occur and only\n _.extend(attributes, attributes.object, {\n element_id: attributes.id\n });\n delete attributes.object;\n return attributes;\n },\n\n /** override to merge this.object into this */\n constructor: function constructor(attributes, options) {\n // console.debug( '\\t DatasetCollectionElement.constructor:', attributes, options );\n attributes = this._mergeObject(attributes);\n this.idAttribute = \"element_id\";\n Backbone.Model.apply(this, arguments);\n },\n\n /** when the model is fetched, merge this.object into this */\n parse: function parse(response, options) {\n var attributes = response;\n attributes = this._mergeObject(attributes);\n return attributes;\n }\n};\n\n/** @class Concrete class of Generic DatasetCollectionElement */\nvar DatasetCollectionElement = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(DatasetCollectionElementMixin).extend({ _logNamespace: \"collections\" });\n\n//==============================================================================\n/** @class Base/Abstract Backbone collection for Generic DCEs. */\nvar DCECollection = Backbone.Collection.extend(_baseMvc2.default.LoggableMixin).extend(\n/** @lends DCECollection.prototype */{\n _logNamespace: \"collections\",\n\n model: DatasetCollectionElement,\n\n /** String representation. */\n toString: function toString() {\n return [\"DatasetCollectionElementCollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone model for a dataset collection element that is a dataset (HDA).\n */\nvar DatasetDCE = _datasetModel2.default.DatasetAssociation.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends DatasetDCE.prototype */{\n /** url fn */\n url: function url() {\n // won't always be an hda\n if (!this.has(\"history_id\")) {\n console.warn(\"no endpoint for non-hdas within a collection yet\");\n // (a little silly since this api endpoint *also* points at hdas)\n return Galaxy.root + \"api/datasets\";\n }\n return Galaxy.root + \"api/histories/\" + this.get(\"history_id\") + \"/contents/\" + this.get(\"id\");\n },\n\n defaults: _.extend({}, _datasetModel2.default.DatasetAssociation.prototype.defaults, DatasetCollectionElementMixin.defaults),\n\n _downloadQueryParameters: function _downloadQueryParameters() {\n return \"?to_ext=\" + this.get(\"file_ext\") + \"&hdca_id=\" + this.get(\"parent_hdca_id\") + \"&element_identifier=\" + this.get(\"element_identifier\");\n },\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually for now\n /** call the mixin constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t DatasetDCE.constructor:\", attributes, options);\n //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function hasDetails() {\n return this.elements && this.elements.length;\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.get(\"element_identifier\");\n return [\"DatasetDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).\n */\nvar DatasetDCECollection = DCECollection.extend(\n/** @lends DatasetDCECollection.prototype */{\n model: DatasetDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"DatasetDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//_________________________________________________________________________________________________ COLLECTIONS\n/** @class Backbone model for Dataset Collections.\n * The DC API returns an array of JSON objects under the attribute elements.\n * This model:\n * - removes that array/attribute ('elements') from the model,\n * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),\n * - passes that json onto the bbone collection\n * - caches the bbone collection in this.elements\n */\nvar DatasetCollection = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.SearchableModelMixin).extend(\n/** @lends DatasetCollection.prototype */{\n _logNamespace: \"collections\",\n\n /** default attributes for a model */\n defaults: {\n /* 'list', 'paired', or 'list:paired' */\n collection_type: null,\n //??\n deleted: false\n },\n\n /** Which class to use for elements */\n collectionClass: DCECollection,\n\n /** set up: create elements instance var and (on changes to elements) update them */\n initialize: function initialize(model, options) {\n this.debug(this + \"(DatasetCollection).initialize:\", model, options, this);\n this.elements = this._createElementsModel();\n this.on(\"change:elements\", function () {\n this.log(\"change:elements\");\n //TODO: prob. better to update the collection instead of re-creating it\n this.elements = this._createElementsModel();\n });\n },\n\n /** move elements model attribute to full collection */\n _createElementsModel: function _createElementsModel() {\n this.debug(this + \"._createElementsModel\", this.collectionClass, this.get(\"elements\"), this.elements);\n //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?\n var elements = this.get(\"elements\") || [];\n this.unset(\"elements\", { silent: true });\n var self = this;\n _.each(elements, function (element, index) {\n _.extend(element, {\n parent_hdca_id: self.get(\"id\")\n });\n });\n this.elements = new this.collectionClass(elements);\n //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );\n return this.elements;\n },\n\n // ........................................................................ common queries\n /** pass the elements back within the model json when this is serialized */\n toJSON: function toJSON() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n if (this.elements) {\n json.elements = this.elements.toJSON();\n }\n return json;\n },\n\n /** Is this collection in a 'ready' state no processing (for the collection) is left\n * to do on the server.\n */\n inReadyState: function inReadyState() {\n var populated = this.get(\"populated\");\n return this.isDeletedOrPurged() || populated;\n },\n\n //TODO:?? the following are the same interface as DatasetAssociation - can we combine?\n /** Does the DC contain any elements yet? Is a fetch() required? */\n hasDetails: function hasDetails() {\n return this.elements.length !== 0;\n },\n\n /** Given the filters, what models in this.elements would be returned? */\n getVisibleContents: function getVisibleContents(filters) {\n // filters unused for now\n return this.elements;\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function parse(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function _delete(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function undelete(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Is this collection deleted or purged? */\n isDeletedOrPurged: function isDeletedOrPurged() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n // ........................................................................ searchable\n /** searchable attributes for collections */\n searchAttributes: [\"name\", \"tags\"],\n\n // ........................................................................ misc\n /** String representation */\n toString: function toString() {\n var idAndName = [this.get(\"id\"), this.get(\"name\") || this.get(\"element_identifier\")];\n return \"DatasetCollection(\" + idAndName.join(\",\") + \")\";\n }\n});\n\n//==============================================================================\n/** Model for a DatasetCollection containing datasets (non-nested).\n */\nvar ListDatasetCollection = DatasetCollection.extend(\n/** @lends ListDatasetCollection.prototype */{\n /** override since we know the collection will only contain datasets */\n collectionClass: DatasetDCECollection,\n\n /** String representation. */\n toString: function toString() {\n return \"List\" + DatasetCollection.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).\n */\nvar PairDatasetCollection = ListDatasetCollection.extend(\n/** @lends PairDatasetCollection.prototype */{\n /** String representation. */\n toString: function toString() {\n return \"Pair\" + DatasetCollection.prototype.toString.call(this);\n }\n});\n\n//_________________________________________________________________________________________________ NESTED COLLECTIONS\n// this is where things get weird, man. Weird.\n//TODO: it might be possible to compact all the following...I think.\n//==============================================================================\n/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection\n * (a nested collection). Currently only list:paired.\n */\nvar NestedDCDCE = DatasetCollection.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends NestedDCDCE.prototype */{\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** call the mixin constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t NestedDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.object ? \"\" + this.object : this.get(\"element_identifier\");\n return [\"NestedDCDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).\n */\nvar NestedDCDCECollection = DCECollection.extend(\n/** @lends NestedDCDCECollection.prototype */{\n /** This is a collection of nested collections */\n model: NestedDCDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"NestedDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.\n */\nvar NestedPairDCDCE = PairDatasetCollection.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends NestedPairDCDCE.prototype */{\n //TODO:?? possibly rename to NestedDatasetCollection?\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** This is both a collection and a collection element - call the constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t NestedPairDCDCE.constructor:\", attributes, options);\n //DatasetCollection.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.object ? \"\" + this.object : this.get(\"element_identifier\");\n return [\"NestedPairDCDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection for a backbone collection containing paired dataset collections.\n */\nvar NestedPairDCDCECollection = NestedDCDCECollection.extend(\n/** @lends PairDCDCECollection.prototype */{\n /** We know this collection is composed of only nested pair collections */\n model: NestedPairDCDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"NestedPairDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).\n */\nvar ListPairedDatasetCollection = DatasetCollection.extend(\n/** @lends ListPairedDatasetCollection.prototype */{\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedPairDCDCECollection,\n\n /** String representation. */\n toString: function toString() {\n return [\"ListPairedDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone model for a list dataset collection within a list:list dataset collection. */\nvar NestedListDCDCE = ListDatasetCollection.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends NestedListDCDCE.prototype */{\n /** This is both a collection and a collection element - call the constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t NestedListDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.object ? \"\" + this.object : this.get(\"element_identifier\");\n return [\"NestedListDCDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection containing list dataset collections. */\nvar NestedListDCDCECollection = NestedDCDCECollection.extend({\n /** We know this collection is composed of only nested pair collections */\n model: NestedListDCDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"NestedListDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains other lists. */\nvar ListOfListsDatasetCollection = DatasetCollection.extend({\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedListDCDCECollection,\n\n /** String representation. */\n toString: function toString() {\n return [\"ListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n ListDatasetCollection: ListDatasetCollection,\n PairDatasetCollection: PairDatasetCollection,\n ListPairedDatasetCollection: ListPairedDatasetCollection,\n ListOfListsDatasetCollection: ListOfListsDatasetCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 38 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, jQuery, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _historyContents = __webpack_require__(39);\n\nvar _historyContents2 = _interopRequireDefault(_historyContents);\n\nvar _historyPreferences = __webpack_require__(40);\n\nvar _historyPreferences2 = _interopRequireDefault(_historyPreferences);\n\nvar _controlledFetchCollection = __webpack_require__(80);\n\nvar _controlledFetchCollection2 = _interopRequireDefault(_controlledFetchCollection);\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/** @class Model for a Galaxy history resource - both a record of user\n * tool use and a collection of the datasets those tools produced.\n * @name History\n * @augments Backbone.Model\n */\nvar History = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.mixin(_baseMvc2.default.SearchableModelMixin,\n/** @lends History.prototype */{\n _logNamespace: \"history\",\n\n /** ms between fetches when checking running jobs/datasets for updates */\n UPDATE_DELAY: 4000,\n\n // values from api (may need more)\n defaults: {\n model_class: \"History\",\n id: null,\n name: \"Unnamed History\",\n state: \"new\",\n\n deleted: false,\n contents_active: {},\n contents_states: {}\n },\n\n urlRoot: Galaxy.root + \"api/histories\",\n\n contentsClass: _historyContents2.default.HistoryContents,\n\n /** What model fields to search with */\n searchAttributes: [\"name\", \"annotation\", \"tags\"],\n\n /** Adding title and singular tag */\n searchAliases: {\n title: \"name\",\n tag: \"tags\"\n },\n\n // ........................................................................ set up/tear down\n /** Set up the model\n * @param {Object} historyJSON model data for this History\n * @param {Object} options any extra settings including logger\n */\n initialize: function initialize(historyJSON, options) {\n options = options || {};\n this.logger = options.logger || null;\n this.log(this + \".initialize:\", historyJSON, options);\n\n /** HistoryContents collection of the HDAs contained in this history. */\n this.contents = new this.contentsClass([], {\n history: this,\n historyId: this.get(\"id\"),\n order: options.order\n });\n\n this._setUpListeners();\n this._setUpCollectionListeners();\n\n /** cached timeout id for the dataset updater */\n this.updateTimeoutId = null;\n },\n\n /** set up any event listeners for this history including those to the contained HDAs\n * events: error:contents if an error occurred with the contents collection\n */\n _setUpListeners: function _setUpListeners() {\n // if the model's id changes ('current' or null -> an actual id), update the contents history_id\n return this.on({\n error: function error(model, xhr, options, msg, details) {\n this.clearUpdateTimeout();\n },\n \"change:id\": function changeId(model, newId) {\n if (this.contents) {\n this.contents.historyId = newId;\n }\n }\n });\n },\n\n /** event handlers for the contents submodels */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n if (!this.contents) {\n return this;\n }\n // bubble up errors\n return this.listenTo(this.contents, {\n error: function error() {\n this.trigger.apply(this, jQuery.makeArray(arguments));\n }\n });\n },\n\n // ........................................................................ derived attributes\n /** */\n contentsShown: function contentsShown() {\n var contentsActive = this.get(\"contents_active\");\n var shown = contentsActive.active || 0;\n shown += this.contents.includeDeleted ? contentsActive.deleted : 0;\n shown += this.contents.includeHidden ? contentsActive.hidden : 0;\n return shown;\n },\n\n /** convert size in bytes to a more human readable version */\n nice_size: function nice_size() {\n var size = this.get(\"size\");\n return size ? _utils2.default.bytesToString(size, true, 2) : (0, _localization2.default)(\"(empty)\");\n },\n\n /** override to add nice_size */\n toJSON: function toJSON() {\n return _.extend(Backbone.Model.prototype.toJSON.call(this), {\n nice_size: this.nice_size()\n });\n },\n\n /** override to allow getting nice_size */\n get: function get(key) {\n if (key === \"nice_size\") {\n return this.nice_size();\n }\n return Backbone.Model.prototype.get.apply(this, arguments);\n },\n\n // ........................................................................ common queries\n /** T/F is this history owned by the current user (Galaxy.user)\n * Note: that this will return false for an anon user even if the history is theirs.\n */\n ownedByCurrUser: function ownedByCurrUser() {\n // no currUser\n if (!Galaxy || !Galaxy.user) {\n return false;\n }\n // user is anon or history isn't owned\n if (Galaxy.user.isAnonymous() || Galaxy.user.id !== this.get(\"user_id\")) {\n return false;\n }\n return true;\n },\n\n /** Return the number of running jobs assoc with this history (note: unknown === 0) */\n numOfUnfinishedJobs: function numOfUnfinishedJobs() {\n var unfinishedJobIds = this.get(\"non_ready_jobs\");\n return unfinishedJobIds ? unfinishedJobIds.length : 0;\n },\n\n /** Return the number of running hda/hdcas in this history (note: unknown === 0) */\n numOfUnfinishedShownContents: function numOfUnfinishedShownContents() {\n return this.contents.runningAndActive().length || 0;\n },\n\n // ........................................................................ updates\n _fetchContentRelatedAttributes: function _fetchContentRelatedAttributes() {\n var contentRelatedAttrs = [\"size\", \"non_ready_jobs\", \"contents_active\", \"hid_counter\"];\n return this.fetch({\n data: $.param({\n keys: contentRelatedAttrs.join(\",\")\n })\n });\n },\n\n /** check for any changes since the last time we updated (or fetch all if ) */\n refresh: function refresh(options) {\n // console.log( this + '.refresh' );\n options = options || {};\n var self = this;\n\n // note if there was no previous update time, all summary contents will be fetched\n var lastUpdateTime = self.lastUpdateTime;\n // if we don't flip this, then a fully-fetched list will not be re-checked via fetch\n this.contents.allFetched = false;\n var fetchFn = self.contents.currentPage !== 0 ? function () {\n return self.contents.fetchPage(self.contents.currentPage);\n } : function () {\n return self.contents.fetchUpdated(lastUpdateTime);\n };\n // note: if there was no previous update time, all summary contents will be fetched\n return fetchFn().done(function (response, status, xhr) {\n var serverResponseDatetime;\n try {\n serverResponseDatetime = new Date(xhr.getResponseHeader(\"Date\"));\n } catch (err) {}\n self.lastUpdateTime = serverResponseDatetime || new Date();\n self.checkForUpdates(options);\n });\n },\n\n /** continuously fetch updated contents every UPDATE_DELAY ms if this history's datasets or jobs are unfinished */\n checkForUpdates: function checkForUpdates(options) {\n // console.log( this + '.checkForUpdates' );\n options = options || {};\n var delay = this.UPDATE_DELAY;\n var self = this;\n if (!self.id) {\n return;\n }\n\n function _delayThenUpdate() {\n // prevent buildup of updater timeouts by clearing previous if any, then set new and cache id\n self.clearUpdateTimeout();\n self.updateTimeoutId = setTimeout(function () {\n self.refresh(options);\n }, delay);\n }\n\n // if there are still datasets in the non-ready state, recurse into this function with the new time\n var nonReadyContentCount = this.numOfUnfinishedShownContents();\n // console.log( 'nonReadyContentCount:', nonReadyContentCount );\n if (nonReadyContentCount > 0) {\n _delayThenUpdate();\n } else {\n // no datasets are running, but currently runnning jobs may still produce new datasets\n // see if the history has any running jobs and continue to update if so\n // (also update the size for the user in either case)\n self._fetchContentRelatedAttributes().done(function (historyData) {\n // console.log( 'non_ready_jobs:', historyData.non_ready_jobs );\n if (self.numOfUnfinishedJobs() > 0) {\n _delayThenUpdate();\n } else {\n // otherwise, let listeners know that all updates have stopped\n self.trigger(\"ready\");\n }\n });\n }\n },\n\n /** clear the timeout and the cached timeout id */\n clearUpdateTimeout: function clearUpdateTimeout() {\n if (this.updateTimeoutId) {\n clearTimeout(this.updateTimeoutId);\n this.updateTimeoutId = null;\n }\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function parse(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** fetch this histories data (using options) then it's contents (using contentsOptions) */\n fetchWithContents: function fetchWithContents(options, contentsOptions) {\n options = options || {};\n var self = this;\n\n // console.log( this + '.fetchWithContents' );\n // TODO: push down to a base class\n options.view = \"dev-detailed\";\n\n // fetch history then use history data to fetch (paginated) contents\n return this.fetch(options).then(function getContents(history) {\n self.contents.history = self;\n self.contents.setHistoryId(history.id);\n return self.fetchContents(contentsOptions);\n });\n },\n\n /** fetch this histories contents, adjusting options based on the stored history preferences */\n fetchContents: function fetchContents(options) {\n options = options || {};\n var self = this;\n\n // we're updating, reset the update time\n self.lastUpdateTime = new Date();\n return self.contents.fetchCurrentPage(options);\n },\n\n /** save this history, _Mark_ing it as deleted (just a flag) */\n _delete: function _delete(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */\n purge: function purge(options) {\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true, purged: true }, options);\n },\n /** save this history, _Mark_ing it as undeleted */\n undelete: function undelete(options) {\n if (!this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Make a copy of this history on the server\n * @param {Boolean} current if true, set the copy as the new current history (default: true)\n * @param {String} name name of new history (default: none - server sets to: Copy of )\n * @fires copied passed this history and the response JSON from the copy\n * @returns {xhr}\n */\n copy: function copy(current, name, allDatasets) {\n current = current !== undefined ? current : true;\n if (!this.id) {\n throw new Error(\"You must set the history ID before copying it.\");\n }\n\n var postData = { history_id: this.id };\n if (current) {\n postData.current = true;\n }\n if (name) {\n postData.name = name;\n }\n if (!allDatasets) {\n postData.all_datasets = false;\n }\n postData.view = \"dev-detailed\";\n\n var history = this;\n var copy = jQuery.post(this.urlRoot, postData);\n // if current - queue to setAsCurrent before firing 'copied'\n if (current) {\n return copy.then(function (response) {\n var newHistory = new History(response);\n return newHistory.setAsCurrent().done(function () {\n history.trigger(\"copied\", history, response);\n });\n });\n }\n return copy.done(function (response) {\n history.trigger(\"copied\", history, response);\n });\n },\n\n setAsCurrent: function setAsCurrent() {\n var history = this;\n\n var xhr = jQuery.getJSON(Galaxy.root + \"history/set_as_current?id=\" + this.id);\n\n xhr.done(function () {\n history.trigger(\"set-as-current\", history);\n });\n return xhr;\n },\n\n // ........................................................................ misc\n toString: function toString() {\n return \"History(\" + this.get(\"id\") + \",\" + this.get(\"name\") + \")\";\n }\n}));\n\n//==============================================================================\nvar _collectionSuper = _controlledFetchCollection2.default.InfinitelyScrollingCollection;\n/** @class A collection of histories (per user)\n * that maintains the current history as the first in the collection.\n * New or copied histories become the current history.\n */\nvar HistoryCollection = _collectionSuper.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n model: History,\n /** @type {String} initial order used by collection */\n order: \"update_time\",\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: 10,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 10,\n\n initialize: function initialize(models, options) {\n options = options || {};\n this.log(\"HistoryCollection.initialize\", models, options);\n _collectionSuper.prototype.initialize.call(this, models, options);\n\n /** @type {boolean} should deleted histories be included */\n this.includeDeleted = options.includeDeleted || false;\n\n /** @type {String} encoded id of the history that's current */\n this.currentHistoryId = options.currentHistoryId;\n\n this.setUpListeners();\n // note: models are sent to reset *after* this fn ends; up to this point\n // the collection *is empty*\n },\n\n urlRoot: Galaxy.root + \"api/histories\",\n url: function url() {\n return this.urlRoot;\n },\n\n /** set up reflexive event handlers */\n setUpListeners: function setUpListeners() {\n return this.on({\n // when a history is deleted, remove it from the collection (if optionally set to do so)\n \"change:deleted\": function changeDeleted(history) {\n // TODO: this becomes complicated when more filters are used\n this.debug(\"change:deleted\", this.includeDeleted, history.get(\"deleted\"));\n if (!this.includeDeleted && history.get(\"deleted\")) {\n this.remove(history);\n }\n },\n // listen for a history copy, setting it to current\n copied: function copied(original, newData) {\n this.setCurrent(new History(newData, []));\n },\n // when a history is made current, track the id in the collection\n \"set-as-current\": function setAsCurrent(history) {\n var oldCurrentId = this.currentHistoryId;\n this.trigger(\"no-longer-current\", oldCurrentId);\n this.currentHistoryId = history.id;\n }\n });\n },\n\n /** override to change view */\n _buildFetchData: function _buildFetchData(options) {\n return _.extend(_collectionSuper.prototype._buildFetchData.call(this, options), {\n view: \"dev-detailed\"\n });\n },\n\n /** override to filter out deleted and purged */\n _buildFetchFilters: function _buildFetchFilters(options) {\n var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n } else {\n // force API to return both deleted and non\n //TODO: when the API is updated, remove this\n filters.deleted = null;\n }\n return _.defaults(superFilters, filters);\n },\n\n /** override to fetch current as well (as it may be outside the first 10, etc.) */\n fetchFirst: function fetchFirst(options) {\n var self = this;\n // TODO: batch?\n var xhr = $.when();\n if (this.currentHistoryId) {\n xhr = _collectionSuper.prototype.fetchFirst.call(self, {\n silent: true,\n limit: 1,\n filters: {\n // without these a deleted current history will return [] here and block the other xhr\n purged: \"\",\n deleted: \"\",\n \"encoded_id-in\": this.currentHistoryId\n }\n });\n }\n return xhr.then(function () {\n options = options || {};\n options.offset = 0;\n return self.fetchMore(options);\n });\n },\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_collectionSuper.prototype.comparators), {\n name: _baseMvc2.default.buildComparator(\"name\", {\n ascending: true\n }),\n \"name-dsc\": _baseMvc2.default.buildComparator(\"name\", {\n ascending: false\n }),\n size: _baseMvc2.default.buildComparator(\"size\", {\n ascending: false\n }),\n \"size-asc\": _baseMvc2.default.buildComparator(\"size\", {\n ascending: true\n })\n }),\n\n /** override to always have the current history first */\n sort: function sort(options) {\n options = options || {};\n var silent = options.silent;\n var currentHistory = this.remove(this.get(this.currentHistoryId));\n _collectionSuper.prototype.sort.call(this, _.defaults({ silent: true }, options));\n this.unshift(currentHistory, { silent: true });\n if (!silent) {\n this.trigger(\"sort\", this, options);\n }\n return this;\n },\n\n /** create a new history and by default set it to be the current history */\n create: function create(data, hdas, historyOptions, xhrOptions) {\n //TODO: .create is actually a collection function that's overridden here\n var collection = this;\n\n var xhr = jQuery.getJSON(Galaxy.root + \"history/create_new_current\");\n return xhr.done(function (newData) {\n collection.setCurrent(new History(newData, [], historyOptions || {}));\n });\n },\n\n /** set the current history to the given history, placing it first in the collection.\n * Pass standard bbone options for use in unshift.\n * @triggers new-current passed history and this collection\n */\n setCurrent: function setCurrent(history, options) {\n options = options || {};\n // new histories go in the front\n this.unshift(history, options);\n this.currentHistoryId = history.get(\"id\");\n if (!options.silent) {\n this.trigger(\"new-current\", history, this);\n }\n return this;\n },\n\n toString: function toString() {\n return \"HistoryCollection(\" + this.length + \",current:\" + this.currentHistoryId + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n History: History,\n HistoryCollection: HistoryCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 39 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, jQuery, Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _controlledFetchCollection = __webpack_require__(80);\n\nvar _controlledFetchCollection2 = _interopRequireDefault(_controlledFetchCollection);\n\nvar _hdaModel = __webpack_require__(81);\n\nvar _hdaModel2 = _interopRequireDefault(_hdaModel);\n\nvar _hdcaModel = __webpack_require__(36);\n\nvar _hdcaModel2 = _interopRequireDefault(_hdcaModel);\n\nvar _historyPreferences = __webpack_require__(40);\n\nvar _historyPreferences2 = _interopRequireDefault(_historyPreferences);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _ajaxQueue = __webpack_require__(152);\n\nvar _ajaxQueue2 = _interopRequireDefault(_ajaxQueue);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _controlledFetchCollection2.default.PaginatedCollection;\n/** @class Backbone collection for history content.\n * NOTE: history content seems like a dataset collection, but differs in that it is mixed:\n * each element can be either an HDA (dataset) or a DatasetCollection and co-exist on\n * the same level.\n * Dataset collections on the other hand are not mixed and (so far) can only contain either\n * HDAs or child dataset collections on one level.\n * This is why this does not inherit from any of the DatasetCollections (currently).\n */\nvar HistoryContents = _super.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n // ........................................................................ set up\n limitPerPage: 500,\n\n /** @type {Integer} how many contents per call to fetch when using progressivelyFetchDetails */\n limitPerProgressiveFetch: 500,\n\n /** @type {String} order used here and when fetching from server */\n order: \"hid\",\n\n /** root api url */\n urlRoot: Galaxy.root + \"api/histories\",\n\n /** complete api url */\n url: function url() {\n return this.urlRoot + \"/\" + this.historyId + \"/contents\";\n },\n\n /** Set up */\n initialize: function initialize(models, options) {\n options = options || {};\n _super.prototype.initialize.call(this, models, options);\n\n this.history = options.history || null;\n this.setHistoryId(options.historyId || null);\n /** @type {Boolean} does this collection contain and fetch deleted elements */\n this.includeDeleted = options.includeDeleted || this.includeDeleted;\n /** @type {Boolean} does this collection contain and fetch non-visible elements */\n this.includeHidden = options.includeHidden || this.includeHidden;\n\n // backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection\n // and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute\n // manually here - if we don't, contents will not merge but be replaced/swapped.\n this.model.prototype.idAttribute = \"type_id\";\n },\n\n // ........................................................................ composite collection\n /** since history content is a mix, override model fn into a factory, creating based on history_content_type */\n model: function model(attrs, options) {\n if (attrs.history_content_type === \"dataset\") {\n return new _hdaModel2.default.HistoryDatasetAssociation(attrs, options);\n } else if (attrs.history_content_type === \"dataset_collection\") {\n switch (attrs.collection_type) {\n case \"list\":\n return new _hdcaModel2.default.HistoryListDatasetCollection(attrs, options);\n case \"paired\":\n return new _hdcaModel2.default.HistoryPairDatasetCollection(attrs, options);\n case \"list:paired\":\n return new _hdcaModel2.default.HistoryListPairedDatasetCollection(attrs, options);\n case \"list:list\":\n return new _hdcaModel2.default.HistoryListOfListsDatasetCollection(attrs, options);\n }\n // This is a hack inside a hack:\n // Raise a plain object with validationError to fake a model.validationError\n // (since we don't have a model to use validate with)\n // (the outer hack being the mixed content/model function in this collection)\n var msg = \"Unknown collection_type: \" + attrs.collection_type;\n console.warn(msg, attrs);\n return { validationError: msg };\n }\n return {\n validationError: \"Unknown history_content_type: \" + attrs.history_content_type\n };\n },\n\n setHistoryId: function setHistoryId(newId) {\n this.historyId = newId;\n this._setUpWebStorage();\n },\n\n /** Set up client side storage. Currently PersistanStorage keyed under 'history:' */\n _setUpWebStorage: function _setUpWebStorage(initialSettings) {\n // TODO: use initialSettings\n if (!this.historyId) {\n return;\n }\n this.storage = new _historyPreferences2.default.HistoryPrefs({\n id: _historyPreferences2.default.HistoryPrefs.historyStorageKey(this.historyId)\n });\n this.trigger(\"new-storage\", this.storage, this);\n\n this.on({\n \"include-deleted\": function includeDeleted(newVal) {\n this.storage.includeDeleted(newVal);\n },\n \"include-hidden\": function includeHidden(newVal) {\n this.storage.includeHidden(newVal);\n }\n });\n\n this.includeDeleted = this.storage.includeDeleted() || false;\n this.includeHidden = this.storage.includeHidden() || false;\n return this;\n },\n\n // ........................................................................ common queries\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_super.prototype.comparators), {\n name: _baseMvc2.default.buildComparator(\"name\", { ascending: true }),\n \"name-dsc\": _baseMvc2.default.buildComparator(\"name\", {\n ascending: false\n }),\n hid: _baseMvc2.default.buildComparator(\"hid\", { ascending: false }),\n \"hid-asc\": _baseMvc2.default.buildComparator(\"hid\", { ascending: true })\n }),\n\n /** Get every model in this collection not in a 'ready' state (running). */\n running: function running() {\n return this.filter(function (c) {\n return !c.inReadyState();\n });\n },\n\n /** return contents that are not ready and not deleted/hidden */\n runningAndActive: function runningAndActive() {\n return this.filter(function (c) {\n return !c.inReadyState() && c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\");\n });\n },\n\n /** Get the model with the given hid\n * @param {Int} hid the hid to search for\n * @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found\n */\n getByHid: function getByHid(hid) {\n // note: there *can* be more than one content with a given hid, this finds the first based on order\n return this.findWhere({ hid: hid });\n },\n\n /** return true if all contents have details */\n haveDetails: function haveDetails() {\n return this.all(function (c) {\n return c.hasDetails();\n });\n },\n\n // ........................................................................ hidden / deleted\n /** return a new contents collection of only hidden items */\n hidden: function hidden() {\n return this.filter(function (c) {\n return c.hidden();\n });\n },\n\n /** return a new contents collection of only hidden items */\n deleted: function deleted() {\n return this.filter(function (c) {\n return c.get(\"deleted\");\n });\n },\n\n /** return a new contents collection of only hidden items */\n visibleAndUndeleted: function visibleAndUndeleted() {\n return this.filter(function (c) {\n return c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\");\n });\n },\n\n /** create a setter in order to publish the change */\n setIncludeDeleted: function setIncludeDeleted(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeDeleted) {\n this.includeDeleted = setting;\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-deleted\", setting, this);\n }\n },\n\n /** create a setter in order to publish the change */\n setIncludeHidden: function setIncludeHidden(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeHidden) {\n this.includeHidden = setting;\n options = options || {};\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-hidden\", setting, this);\n }\n },\n\n // ........................................................................ ajax\n // ............ controlled fetch collection\n /** override to get expanded ids from sessionStorage and pass to API as details */\n fetch: function fetch(options) {\n options = options || {};\n if (this.historyId && !options.details) {\n var prefs = _historyPreferences2.default.HistoryPrefs.get(this.historyId).toJSON();\n if (!_.isEmpty(prefs.expandedIds)) {\n options.details = _.values(prefs.expandedIds).join(\",\");\n }\n }\n return _super.prototype.fetch.call(this, options);\n },\n\n // ............. ControlledFetch stuff\n /** override to include the API versioning flag */\n _buildFetchData: function _buildFetchData(options) {\n return _.extend(_super.prototype._buildFetchData.call(this, options), {\n v: \"dev\"\n });\n },\n\n /** Extend to include details and version */\n _fetchParams: _super.prototype._fetchParams.concat([\n // TODO: remove (the need for) both\n /** version */\n \"v\",\n /** dataset ids to get full details of */\n \"details\"]),\n\n /** override to add deleted/hidden filters */\n _buildFetchFilters: function _buildFetchFilters(options) {\n var superFilters = _super.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n }\n if (!this.includeHidden) {\n filters.visible = true;\n }\n return _.defaults(superFilters, filters);\n },\n\n // ............ paginated collection\n getTotalItemCount: function getTotalItemCount() {\n return this.history.contentsShown();\n },\n\n // ............ history contents specific ajax\n /** override to filter requested contents to those updated after the Date 'since' */\n fetchUpdated: function fetchUpdated(since, options) {\n if (since) {\n options = options || { filters: {} };\n options.remove = false;\n options.filters = {\n \"update_time-ge\": since.toISOString(),\n // workflows will produce hidden datasets (non-output datasets) that still\n // need to be updated in the collection or they'll update forever\n // we can remove the default visible filter by using an 'empty' value\n visible: \"\"\n };\n }\n return this.fetch(options);\n },\n\n /** fetch all the deleted==true contents of this collection */\n fetchDeleted: function fetchDeleted(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n // all deleted, purged or not\n deleted: true,\n purged: undefined\n });\n options.remove = false;\n\n self.trigger(\"fetching-deleted\", self);\n return self.fetch(options).always(function () {\n self.trigger(\"fetching-deleted-done\", self);\n });\n },\n\n /** fetch all the visible==false contents of this collection */\n fetchHidden: function fetchHidden(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n visible: false\n });\n options.remove = false;\n\n self.trigger(\"fetching-hidden\", self);\n return self.fetch(options).always(function () {\n self.trigger(\"fetching-hidden-done\", self);\n });\n },\n\n /** fetch detailed model data for all contents in this collection */\n fetchAllDetails: function fetchAllDetails(options) {\n options = options || {};\n var detailsFlag = { details: \"all\" };\n options.data = _.extend(options.data || {}, detailsFlag);\n return this.fetch(options);\n },\n\n /** specialty fetch method for retrieving the element_counts of all hdcas in the history */\n fetchCollectionCounts: function fetchCollectionCounts(options) {\n options = options || {};\n options.keys = [\"type_id\", \"element_count\"].join(\",\");\n options.filters = _.extend(options.filters || {}, {\n history_content_type: \"dataset_collection\"\n });\n options.remove = false;\n return this.fetch(options);\n },\n\n // ............. quasi-batch ops\n // TODO: to batch\n /** helper that fetches using filterParams then calls save on each fetched using updateWhat as the save params */\n _filterAndUpdate: function _filterAndUpdate(filterParams, updateWhat) {\n var self = this;\n var idAttribute = self.model.prototype.idAttribute;\n var updateArgs = [updateWhat];\n\n return self.fetch({ filters: filterParams, remove: false }).then(function (fetched) {\n // convert filtered json array to model array\n fetched = fetched.reduce(function (modelArray, currJson, i) {\n var model = self.get(currJson[idAttribute]);\n return model ? modelArray.concat(model) : modelArray;\n }, []);\n return self.ajaxQueue(\"save\", updateArgs, fetched);\n });\n },\n\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function ajaxQueue(ajaxFn, args, collection) {\n collection = collection || this.models;\n return new _ajaxQueue2.default.AjaxQueue(collection.slice().reverse().map(function (content, i) {\n var fn = _.isString(ajaxFn) ? content[ajaxFn] : ajaxFn;\n return function () {\n return fn.apply(content, args);\n };\n })).deferred;\n },\n\n /** fetch contents' details in batches of limitPerCall - note: only get searchable details here */\n progressivelyFetchDetails: function progressivelyFetchDetails(options) {\n options = options || {};\n var deferred = jQuery.Deferred();\n var self = this;\n var limit = options.limitPerCall || self.limitPerProgressiveFetch;\n // TODO: only fetch tags and annotations if specifically requested\n var searchAttributes = _hdaModel2.default.HistoryDatasetAssociation.prototype.searchAttributes;\n var detailKeys = searchAttributes.join(\",\");\n\n function _recursivelyFetch(offset) {\n offset = offset || 0;\n var _options = _.extend(_.clone(options), {\n view: \"summary\",\n keys: detailKeys,\n limit: limit,\n offset: offset,\n reset: offset === 0,\n remove: false\n });\n\n _.defer(function () {\n self.fetch.call(self, _options).fail(deferred.reject).done(function (response) {\n deferred.notify(response, limit, offset);\n if (response.length !== limit) {\n self.allFetched = true;\n deferred.resolve(response, limit, offset);\n } else {\n _recursivelyFetch(offset + limit);\n }\n });\n });\n }\n _recursivelyFetch();\n return deferred;\n },\n\n /** does some bit of JSON represent something that can be copied into this contents collection */\n isCopyable: function isCopyable(contentsJSON) {\n var copyableModelClasses = [\"HistoryDatasetAssociation\", \"HistoryDatasetCollectionAssociation\"];\n return _.isObject(contentsJSON) && contentsJSON.id && _.contains(copyableModelClasses, contentsJSON.model_class);\n },\n\n /** copy an existing, accessible hda into this collection */\n copy: function copy(json) {\n // TODO: somehow showhorn all this into 'save'\n var id;\n\n var type;\n var contentType;\n if (_.isString(json)) {\n id = json;\n contentType = \"hda\";\n type = \"dataset\";\n } else {\n id = json.id;\n contentType = {\n HistoryDatasetAssociation: \"hda\",\n LibraryDatasetDatasetAssociation: \"ldda\",\n HistoryDatasetCollectionAssociation: \"hdca\"\n }[json.model_class] || \"hda\";\n type = contentType === \"hdca\" ? \"dataset_collection\" : \"dataset\";\n }\n var collection = this;\n\n var xhr = jQuery.ajax(this.url(), {\n method: \"POST\",\n contentType: \"application/json\",\n data: JSON.stringify({\n content: id,\n source: contentType,\n type: type\n })\n }).done(function (response) {\n collection.add([response], { parse: true });\n }).fail(function (error, status, message) {\n collection.trigger(\"error\", collection, xhr, {}, \"Error copying contents\", {\n type: type,\n id: id,\n source: contentType\n });\n });\n\n return xhr;\n },\n\n /** create a new HDCA in this collection */\n createHDCA: function createHDCA(elementIdentifiers, collectionType, name, hideSourceItems, options) {\n // normally collection.create returns the new model, but we need the promise from the ajax, so we fake create\n //precondition: elementIdentifiers is an array of plain js objects\n // in the proper form to create the collectionType\n var hdca = this.model({\n history_content_type: \"dataset_collection\",\n collection_type: collectionType,\n history_id: this.historyId,\n name: name,\n hide_source_items: hideSourceItems || false,\n // should probably be able to just send in a bunch of json here and restruct per class\n // note: element_identifiers is now (incorrectly) an attribute\n element_identifiers: elementIdentifiers\n // do not create the model on the client until the ajax returns\n });\n return hdca.save(options);\n },\n\n // ........................................................................ searching\n /** return true if all contents have the searchable attributes */\n haveSearchDetails: function haveSearchDetails() {\n return this.allFetched && this.all(function (content // null (which is a valid returned annotation value)\n ) {\n return (\n // will return false when using content.has( 'annotation' )\n //TODO: a bit hacky - formalize\n _.has(content.attributes, \"annotation\")\n );\n });\n },\n\n /** return a new collection of contents whose attributes contain the substring matchesWhat */\n matches: function matches(matchesWhat) {\n return this.filter(function (content) {\n return content.matches(matchesWhat);\n });\n },\n\n // ........................................................................ misc\n /** In this override, copy the historyId to the clone */\n clone: function clone() {\n var clone = Backbone.Collection.prototype.clone.call(this);\n clone.historyId = this.historyId;\n return clone;\n },\n\n /** String representation. */\n toString: function toString() {\n return [\"HistoryContents(\", [this.historyId, this.length].join(), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n HistoryContents: HistoryContents\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(2)))\n\n/***/ }),\n/* 40 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"history\";\n\n// ============================================================================\n/** session storage for individual history preferences */\nvar HistoryPrefs = _baseMvc2.default.SessionStorageModel.extend(\n/** @lends HistoryPrefs.prototype */{\n //TODO:?? move to user prefs?\n defaults: {\n //TODO:?? expandedIds to array?\n expandedIds: {},\n show_deleted: false,\n show_hidden: false\n },\n\n /** add an hda id to the hash of expanded hdas */\n addExpanded: function addExpanded(model) {\n //TODO: use type_id and not model\n var current = this.get(\"expandedIds\");\n current[model.id] = model.get(\"id\");\n this.save(\"expandedIds\", current);\n },\n\n /** remove an hda id from the hash of expanded hdas */\n removeExpanded: function removeExpanded(model) {\n var current = this.get(\"expandedIds\");\n delete current[model.id];\n this.save(\"expandedIds\", current);\n },\n\n isExpanded: function isExpanded(contentId) {\n return _.result(this.get(\"expandedIds\"), contentId, false);\n },\n\n allExpanded: function allExpanded() {\n return _.values(this.get(\"expandedIds\"));\n },\n\n clearExpanded: function clearExpanded() {\n this.set(\"expandedIds\", {});\n },\n\n includeDeleted: function includeDeleted(val) {\n // moving the invocation here so other components don't need to know the key\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_deleted\", val);\n }\n return this.get(\"show_deleted\");\n },\n\n includeHidden: function includeHidden(val) {\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_hidden\", val);\n }\n return this.get(\"show_hidden\");\n },\n\n toString: function toString() {\n return \"HistoryPrefs(\" + this.id + \")\";\n }\n}, {\n // ........................................................................ class vars\n // class lvl for access w/o instantiation\n storageKeyPrefix: \"history:\",\n\n /** key string to store each histories settings under */\n historyStorageKey: function historyStorageKey(historyId) {\n if (!historyId) {\n throw new Error(\"HistoryPrefs.historyStorageKey needs valid id: \" + historyId);\n }\n // single point of change\n return HistoryPrefs.storageKeyPrefix + historyId;\n },\n\n /** return the existing storage for the history with the given id (or create one if it doesn't exist) */\n get: function get(historyId) {\n return new HistoryPrefs({\n id: HistoryPrefs.historyStorageKey(historyId)\n });\n },\n\n /** clear all history related items in sessionStorage */\n clearAll: function clearAll(historyId) {\n for (var key in sessionStorage) {\n if (key.indexOf(HistoryPrefs.storageKeyPrefix) === 0) {\n sessionStorage.removeItem(key);\n }\n }\n }\n});\n\n//==============================================================================\nexports.default = {\n HistoryPrefs: HistoryPrefs\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 41 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"list\";\n//==============================================================================\n/** A view which, when first rendered, shows only summary data/attributes, but\n * can be expanded to show further details (and optionally fetch those\n * details from the server).\n */\nvar ExpandableView = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: Although the reasoning behind them is different, this shares a lot with HiddenUntilActivated above: combine them\n //PRECONDITION: model must have method hasDetails\n //PRECONDITION: subclasses must have templates.el and templates.details\n\n initialize: function initialize(attributes) {\n /** are the details of this view expanded/shown or not? */\n this.expanded = attributes.expanded || false;\n this.log(\"\\t expanded:\", this.expanded);\n this.fxSpeed = attributes.fxSpeed !== undefined ? attributes.fxSpeed : this.fxSpeed;\n },\n\n // ........................................................................ render main\n /** jq fx speed */\n fxSpeed: \"fast\",\n\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function render(speed) {\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n * If the view is already expanded, build the details as well.\n */\n _buildNewRender: function _buildNewRender() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = $(this.templates.el(this.model.toJSON(), this));\n if (this.expanded) {\n this.$details($newRender).replaceWith(this._renderDetails().show());\n }\n return $newRender;\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function _queueNewRender($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var view = this;\n\n if (speed === 0) {\n view._swapNewRender($newRender);\n view.trigger(\"rendered\", view);\n } else {\n $(view).queue(\"fx\", [function (next) {\n view.$el.fadeOut(speed, next);\n }, function (next) {\n view._swapNewRender($newRender);\n next();\n }, function (next) {\n view.$el.fadeIn(speed, next);\n }, function (next) {\n view.trigger(\"rendered\", view);\n next();\n }]);\n }\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function _swapNewRender($newRender) {\n return this.$el.empty().attr(\"class\", _.isFunction(this.className) ? this.className() : this.className).append($newRender.children());\n },\n\n /** set up js behaviors, event handlers for elements within the given container\n * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)\n */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)\n //make_popup_menus( $where );\n $where.find(\"[title]\").tooltip({ placement: \"bottom\" });\n },\n\n // ......................................................................... details\n /** shortcut to details DOM (as jQ) */\n $details: function $details($where) {\n $where = $where || this.$el;\n return $where.find(\"> .details\");\n },\n\n /** build the DOM for the details and set up behaviors on it */\n _renderDetails: function _renderDetails() {\n var $newDetails = $(this.templates.details(this.model.toJSON(), this));\n this._setUpBehaviors($newDetails);\n return $newDetails;\n },\n\n // ......................................................................... expansion/details\n /** Show or hide the details\n * @param {Boolean} expand if true, expand; if false, collapse\n */\n toggleExpanded: function toggleExpanded(expand) {\n expand = expand === undefined ? !this.expanded : expand;\n if (expand) {\n this.expand();\n } else {\n this.collapse();\n }\n return this;\n },\n\n /** Render and show the full, detailed body of this view including extra data and controls.\n * note: if the model does not have detailed data, fetch that data before showing the body\n * @fires expanded when a body has been expanded\n */\n expand: function expand() {\n var view = this;\n return view._fetchModelDetails().always(function () {\n view._expand();\n });\n },\n\n /** Check for model details and, if none, fetch them.\n * @returns {jQuery.promise} the model.fetch.xhr if details are being fetched, an empty promise if not\n */\n _fetchModelDetails: function _fetchModelDetails() {\n if (!this.model.hasDetails()) {\n return this.model.fetch();\n }\n return jQuery.when();\n },\n\n /** Inner fn called when expand (public) has fetched the details */\n _expand: function _expand() {\n var view = this;\n var $newDetails = view._renderDetails();\n view.$details().replaceWith($newDetails);\n // needs to be set after the above or the slide will not show\n view.expanded = true;\n view.$details().slideDown(view.fxSpeed, function () {\n view.trigger(\"expanded\", view);\n });\n },\n\n /** Hide the body/details of an HDA.\n * @fires collapsed when a body has been collapsed\n */\n collapse: function collapse() {\n this.debug(this + \"(ExpandableView).collapse\");\n var view = this;\n view.expanded = false;\n this.$details().slideUp(view.fxSpeed, function () {\n view.trigger(\"collapsed\", view);\n });\n }\n});\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * Inherits from Expandable, Selectable, Draggable.\n * The DOM contains warnings, a title bar, and a series of primary action controls.\n * Primary actions are meant to be easily accessible item functions (such as delete)\n * that are rendered in the title bar.\n *\n * Details are rendered when the user clicks the title bar or presses enter/space when\n * the title bar is in focus.\n *\n * Designed as a base class for history panel contents - but usable elsewhere (I hope).\n */\nvar ListItemView = ExpandableView.extend(_baseMvc2.default.mixin(_baseMvc2.default.SelectableViewMixin, _baseMvc2.default.DraggableViewMixin, {\n tagName: \"div\",\n className: \"list-item\",\n\n /** Set up the base class and all mixins */\n initialize: function initialize(attributes) {\n ExpandableView.prototype.initialize.call(this, attributes);\n _baseMvc2.default.SelectableViewMixin.initialize.call(this, attributes);\n _baseMvc2.default.DraggableViewMixin.initialize.call(this, attributes);\n this._setUpListeners();\n },\n\n /** event listeners */\n _setUpListeners: function _setUpListeners() {\n // hide the primary actions in the title bar when selectable and narrow\n this.on(\"selectable\", function (isSelectable) {\n if (isSelectable) {\n this.$(\".primary-actions\").hide();\n } else {\n this.$(\".primary-actions\").show();\n }\n }, this);\n return this;\n },\n\n // ........................................................................ rendering\n /** In this override, call methods to build warnings, titlebar and primary actions */\n _buildNewRender: function _buildNewRender() {\n var $newRender = ExpandableView.prototype._buildNewRender.call(this);\n $newRender.children(\".warnings\").replaceWith(this._renderWarnings());\n $newRender.children(\".title-bar\").replaceWith(this._renderTitleBar());\n $newRender.children(\".primary-actions\").append(this._renderPrimaryActions());\n $newRender.find(\"> .title-bar .subtitle\").replaceWith(this._renderSubtitle());\n return $newRender;\n },\n\n /** In this override, render the selector controls and set up dragging before the swap */\n _swapNewRender: function _swapNewRender($newRender) {\n ExpandableView.prototype._swapNewRender.call(this, $newRender);\n if (this.selectable) {\n this.showSelector(0);\n }\n if (this.draggable) {\n this.draggableOn();\n }\n return this.$el;\n },\n\n /** Render any warnings the item may need to show (e.g. \"I'm deleted\") */\n _renderWarnings: function _renderWarnings() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.warnings, function (templateFn) {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderTitleBar: function _renderTitleBar() {\n return $(this.templates.titleBar(this.model.toJSON(), this));\n },\n\n /** Return an array of jQ objects containing common/easily-accessible item controls */\n _renderPrimaryActions: function _renderPrimaryActions() {\n // override this\n return [];\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderSubtitle: function _renderSubtitle() {\n return $(this.templates.subtitle(this.model.toJSON(), this));\n },\n\n // ......................................................................... events\n /** event map */\n events: {\n // expand the body when the title is clicked or when in focus and space or enter is pressed\n \"click .title-bar\": \"_clickTitleBar\",\n \"keydown .title-bar\": \"_keyDownTitleBar\",\n \"click .selector\": \"toggleSelect\"\n },\n\n /** expand when the title bar is clicked */\n _clickTitleBar: function _clickTitleBar(event) {\n event.stopPropagation();\n if (event.altKey) {\n this.toggleSelect(event);\n if (!this.selectable) {\n this.showSelector();\n }\n } else {\n this.toggleExpanded();\n }\n },\n\n /** expand when the title bar is in focus and enter or space is pressed */\n _keyDownTitleBar: function _keyDownTitleBar(event) {\n // bail (with propagation) if keydown and not space or enter\n var KEYCODE_SPACE = 32;\n\n var KEYCODE_RETURN = 13;\n if (event && event.type === \"keydown\" && (event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN)) {\n this.toggleExpanded();\n event.stopPropagation();\n return false;\n }\n return true;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"ListItemView(\" + modelString + \")\";\n }\n}));\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListItemView.prototype.templates = function () {\n var elTemplato = _baseMvc2.default.wrapTemplate(['
\",\n // space for title bar buttons - gen. floated to the right\n '', '',\n\n // expandable area for more details\n '', \"
\"]);\n\n var warnings = {};\n\n var titleBarTemplate = _baseMvc2.default.wrapTemplate([\n // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display\n '
',\n //TODO: prob. belongs in dataset-list-item\n '', '
', '<%- element.name %>', \"
\", '', \"
\"], \"element\");\n\n var subtitleTemplate = _baseMvc2.default.wrapTemplate([\n // override this\n '']);\n\n var detailsTemplate = _baseMvc2.default.wrapTemplate([\n // override this\n '']);\n\n return {\n el: elTemplato,\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate,\n details: detailsTemplate\n };\n}();\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * *AND* can display some sub-list of it's own when expanded (e.g. dataset collections).\n * This list will 'foldout' when the item is expanded depending on this.foldoutStyle:\n * If 'foldout': will expand vertically to show the nested list\n * If 'drilldown': will overlay the parent list\n *\n * Inherits from ListItemView.\n *\n * _renderDetails does the work of creating this.details: a sub-view that shows the nested list\n */\nvar FoldoutListItemView = ListItemView.extend({\n /** If 'foldout': show the sub-panel inside the expanded item\n * If 'drilldown': only fire events and handle by pub-sub\n * (allow the panel containing this item to attach it, hide itself, etc.)\n */\n foldoutStyle: \"foldout\",\n /** Panel view class to instantiate for the sub-panel */\n foldoutPanelClass: null,\n\n /** override to:\n * add attributes foldoutStyle and foldoutPanelClass for config poly\n * disrespect attributes.expanded if drilldown\n */\n initialize: function initialize(attributes) {\n if (this.foldoutStyle === \"drilldown\") {\n this.expanded = false;\n }\n this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;\n this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;\n\n ListItemView.prototype.initialize.call(this, attributes);\n this.foldout = this._createFoldoutPanel();\n },\n\n /** in this override, attach the foldout panel when rendering details */\n _renderDetails: function _renderDetails() {\n if (this.foldoutStyle === \"drilldown\") {\n return $();\n }\n var $newDetails = ListItemView.prototype._renderDetails.call(this);\n return this._attachFoldout(this.foldout, $newDetails);\n },\n\n /** In this override, handle collection expansion. */\n _createFoldoutPanel: function _createFoldoutPanel() {\n var model = this.model;\n var FoldoutClass = this._getFoldoutPanelClass(model);\n var options = this._getFoldoutPanelOptions(model);\n\n var foldout = new FoldoutClass(_.extend(options, {\n model: model\n }));\n\n return foldout;\n },\n\n /** Stub to return proper foldout panel class */\n _getFoldoutPanelClass: function _getFoldoutPanelClass() {\n // override\n return this.foldoutPanelClass;\n },\n\n /** Stub to return proper foldout panel options */\n _getFoldoutPanelOptions: function _getFoldoutPanelOptions() {\n return {\n // propagate foldout style down\n foldoutStyle: this.foldoutStyle,\n fxSpeed: this.fxSpeed\n };\n },\n\n /** Render the foldout panel inside the view, hiding controls */\n _attachFoldout: function _attachFoldout(foldout, $whereTo) {\n $whereTo = $whereTo || this.$(\"> .details\");\n this.foldout = foldout.render(0);\n foldout.$(\"> .controls\").hide();\n return $whereTo.append(foldout.$el);\n },\n\n /** In this override, branch on foldoutStyle to show expanded */\n expand: function expand() {\n var view = this;\n return view._fetchModelDetails().always(function () {\n if (view.foldoutStyle === \"foldout\") {\n view._expand();\n } else if (view.foldoutStyle === \"drilldown\") {\n view._expandByDrilldown();\n }\n });\n },\n\n /** For drilldown, set up close handler and fire expanded:drilldown\n * containing views can listen to this and handle other things\n * (like hiding themselves) by listening for expanded/collapsed:drilldown\n */\n _expandByDrilldown: function _expandByDrilldown() {\n var view = this;\n // attachment and rendering done by listener\n view.listenTo(view.foldout, \"close\", function () {\n view.trigger(\"collapsed:drilldown\", view, view.foldout);\n });\n view.trigger(\"expanded:drilldown\", view, view.foldout);\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nFoldoutListItemView.prototype.templates = function () {\n var detailsTemplate = _baseMvc2.default.wrapTemplate(['
',\n // override with more info (that goes above the panel)\n \"
\"], \"collection\");\n\n return _.extend({}, ListItemView.prototype.templates, {\n details: detailsTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n ExpandableView: ExpandableView,\n ListItemView: ListItemView,\n FoldoutListItemView: FoldoutListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 42 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, jQuery, Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listItem = __webpack_require__(41);\n\nvar _listItem2 = _interopRequireDefault(_listItem);\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"dataset\";\n/*==============================================================================\nTODO:\n straighten out state rendering and templates used\n inaccessible/STATES.NOT_VIEWABLE is a special case\n simplify button rendering\n\n==============================================================================*/\nvar _super = _listItem2.default.ListItemView;\n/** @class Read only list view for either LDDAs, HDAs, or HDADCEs.\n * Roughly, any DatasetInstance (and not a raw Dataset).\n */\nvar DatasetListItemView = _super.extend(\n/** @lends DatasetListItemView.prototype */{\n _logNamespace: logNamespace,\n\n className: _super.prototype.className + \" dataset\",\n //TODO:?? doesn't exactly match an hda's type_id\n id: function id() {\n return [\"dataset\", this.model.get(\"id\")].join(\"-\");\n },\n\n /** Set up: instance vars, options, and event handlers */\n initialize: function initialize(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(this + \".initialize:\", attributes);\n _super.prototype.initialize.call(this, attributes);\n\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n },\n\n /** event listeners */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n var self = this;\n\n // re-rendering on any model changes\n return self.listenTo(self.model, {\n change: function change(model) {\n // if the model moved into the ready state and is expanded without details, fetch those details now\n if (self.model.changedAttributes().state && self.model.inReadyState() && self.expanded && !self.model.hasDetails()) {\n // normally, will render automatically (due to fetch -> change),\n // but! setting_metadata sometimes doesn't cause any other changes besides state\n // so, not rendering causes it to seem frozen in setting_metadata state\n self.model.fetch({ silent: true }).done(function () {\n self.render();\n });\n } else {\n if (_.has(model.changed, \"tags\") && _.keys(model.changed).length === 1) {\n // If only the tags have changed, rerender specifically\n // the titlebar region. Otherwise default to the full\n // render.\n self.$(\".nametags\").html(self._renderNametags());\n } else {\n self.render();\n }\n }\n }\n });\n },\n\n // ......................................................................... expandable\n /** In this override, only get details if in the ready state, get rerunnable if in other states.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function _fetchModelDetails() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... removal\n /** Remove this view's html from the DOM and remove all event listeners.\n * @param {Number or String} speed jq effect speed\n * @param {Function} callback an optional function called when removal is done (scoped to this view)\n */\n remove: function remove(speed, callback) {\n var view = this;\n speed = speed || this.fxSpeed;\n this.$el.fadeOut(speed, function () {\n Backbone.View.prototype.remove.call(view);\n if (callback) {\n callback.call(view);\n }\n });\n },\n\n // ......................................................................... rendering\n /* TODO:\n dataset states are the issue primarily making dataset rendering complex\n each state should have it's own way of displaying/set of details\n often with different actions that can be applied\n throw in deleted/purged/visible and things get complicated easily\n I've considered (a couple of times) - creating a view for each state\n - but recreating the view during an update...seems wrong\n */\n /** In this override, add the dataset state as a class for use with state-based CSS */\n _swapNewRender: function _swapNewRender($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n if (this.model.has(\"state\")) {\n this.$el.addClass(\"state-\" + this.model.get(\"state\"));\n }\n return this.$el;\n },\n\n // ................................................................................ titlebar\n /** In this override, add the dataset display button. */\n _renderPrimaryActions: function _renderPrimaryActions() {\n // render just the display for read-only\n return [this._renderDisplayButton()];\n },\n\n /** Render icon-button to display dataset data */\n _renderDisplayButton: function _renderDisplayButton() {\n // don't show display if not viewable or not accessible\n var state = this.model.get(\"state\");\n if (state === _states2.default.NOT_VIEWABLE || state === _states2.default.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n\n var displayBtnData = {\n target: this.linkTarget,\n classes: \"display-btn\"\n };\n\n // show a disabled display if the data's been purged\n if (this.model.get(\"purged\")) {\n displayBtnData.disabled = true;\n displayBtnData.title = (0, _localization2.default)(\"Cannot display datasets removed from disk\");\n\n // disable if still uploading\n } else if (state === _states2.default.UPLOAD) {\n displayBtnData.disabled = true;\n displayBtnData.title = (0, _localization2.default)(\"This dataset must finish uploading before it can be viewed\");\n\n // disable if still new\n } else if (state === _states2.default.NEW) {\n displayBtnData.disabled = true;\n displayBtnData.title = (0, _localization2.default)(\"This dataset is not yet viewable\");\n } else {\n displayBtnData.title = (0, _localization2.default)(\"View data\");\n\n // default link for dataset\n displayBtnData.href = this.model.urls.display;\n\n // add frame manager option onclick event\n var self = this;\n displayBtnData.onclick = function (ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n // Add dataset to frames.\n Galaxy.frame.addDataset(self.model.get(\"id\"));\n ev.preventDefault();\n }\n };\n }\n displayBtnData.faIcon = \"fa-eye\";\n return (0, _faIconButton2.default)(displayBtnData);\n },\n\n // ......................................................................... rendering details\n /** Render the enclosing div of the hda body and, if expanded, the html in the body\n * @returns {jQuery} rendered DOM\n */\n _renderDetails: function _renderDetails() {\n //TODO: generalize to be allow different details for each state\n\n // no access - render nothing but a message\n if (this.model.get(\"state\") === _states2.default.NOT_VIEWABLE) {\n return $(this.templates.noAccess(this.model.toJSON(), this));\n }\n\n var $details = _super.prototype._renderDetails.call(this);\n $details.find(\".actions .left\").empty().append(this._renderSecondaryActions());\n $details.find(\".summary\").html(this._renderSummary()).prepend(this._renderDetailMessages());\n $details.find(\".display-applications\").html(this._renderDisplayApplications());\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /** Defer to the appropo summary rendering fn based on state */\n _renderSummary: function _renderSummary() {\n var json = this.model.toJSON();\n var summaryRenderFn = this.templates.summaries[json.state];\n summaryRenderFn = summaryRenderFn || this.templates.summaries.unknown;\n return summaryRenderFn(json, this);\n },\n\n /** Render messages to be displayed only when the details are shown */\n _renderDetailMessages: function _renderDetailMessages() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.detailMessages, function (templateFn) {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the external display application links */\n _renderDisplayApplications: function _renderDisplayApplications() {\n if (this.model.isDeletedOrPurged()) {\n return \"\";\n }\n // render both old and new display apps using the same template\n return [this.templates.displayApplications(this.model.get(\"display_apps\"), this), this.templates.displayApplications(this.model.get(\"display_types\"), this)].join(\"\");\n },\n\n // ......................................................................... secondary/details actions\n /** A series of links/buttons for less commonly used actions: re-run, info, etc. */\n _renderSecondaryActions: function _renderSecondaryActions() {\n this.debug(\"_renderSecondaryActions\");\n switch (this.model.get(\"state\")) {\n case _states2.default.NOT_VIEWABLE:\n return [];\n case _states2.default.OK:\n case _states2.default.FAILED_METADATA:\n case _states2.default.ERROR:\n return [this._renderDownloadButton(), this._renderShowParamsButton()];\n }\n return [this._renderShowParamsButton()];\n },\n\n /** Render icon-button to show the input and output (stdout/err) for the job that created this.\n * @returns {jQuery} rendered DOM\n */\n _renderShowParamsButton: function _renderShowParamsButton() {\n // gen. safe to show in all cases\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"View details\"),\n classes: \"params-btn\",\n href: this.model.urls.show_params,\n target: this.linkTarget,\n faIcon: \"fa-info-circle\",\n onclick: function onclick(ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Dataset details\",\n url: this.href\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n }\n });\n },\n\n /** Render icon-button/popupmenu to download the data (and/or the associated meta files (bai, etc.)) for this.\n * @returns {jQuery} rendered DOM\n */\n _renderDownloadButton: function _renderDownloadButton() {\n // don't show anything if the data's been purged\n if (this.model.get(\"purged\") || !this.model.hasData()) {\n return null;\n }\n\n // return either: a popupmenu with links to download assoc. meta files (if there are meta files)\n // or a single download icon-button (if there are no meta files)\n if (!_.isEmpty(this.model.get(\"meta_files\"))) {\n return this._renderMetaFileDownloadButton();\n }\n\n return $(['\", '', \"\"].join(\"\"));\n },\n\n /** Render the download button which opens a dropdown with links to download assoc. meta files (indeces, etc.) */\n _renderMetaFileDownloadButton: function _renderMetaFileDownloadButton() {\n var urls = this.model.urls;\n return $(['
'], \"dataset\");\n\n // messages to be displayed only within the details section ('below the fold')\n var detailMessageTemplates = {\n resubmitted: _baseMvc2.default.wrapTemplate([\n // deleted not purged\n \"<% if( model.resubmitted ){ %>\", '
', (0, _localization2.default)(\"The job creating this dataset has been resubmitted\"), \"
\", \"<% } %>\"])\n };\n\n // this is applied to both old and new style display apps\n var displayApplicationsTemplate = _baseMvc2.default.wrapTemplate([\"<% _.each( apps, function( app ){ %>\", '
\"], \"collection\");\n\n return _.extend({}, FoldoutListItemView.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate\n });\n}();\n\n//==============================================================================\n/** @class Read only view for DatasetCollectionElement.\n */\nvar DCEListItemView = ListItemView.extend(\n/** @lends DCEListItemView.prototype */{\n /** add the DCE class to the list item */\n className: ListItemView.prototype.className + \" dataset-collection-element\",\n\n /** set up */\n initialize: function initialize(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DCEListItemView.initialize:\", attributes);\n ListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"DCEListItemView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDCEListItemView.prototype.templates = function () {\n // use the element identifier here - since that will persist and the user will need it\n var titleBarTemplate = _baseMvc2.default.wrapTemplate(['
', '
', '<%- element.element_identifier %>', \"
\", '', \"
\"], \"element\");\n\n return _.extend({}, ListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n}();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation\n * (a dataset contained in a dataset collection).\n */\nvar DatasetDCEListItemView = _datasetLi2.default.DatasetListItemView.extend(\n/** @lends DatasetDCEListItemView.prototype */{\n className: _datasetLi2.default.DatasetListItemView.prototype.className + \" dataset-collection-element\",\n\n /** set up */\n initialize: function initialize(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DatasetDCEListItemView.initialize:\", attributes);\n _datasetLi2.default.DatasetListItemView.prototype.initialize.call(this, attributes);\n },\n\n /** In this override, only get details if in the ready state.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function _fetchModelDetails() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"DatasetDCEListItemView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetDCEListItemView.prototype.templates = function () {\n // use the element identifier here and not the dataset name\n //TODO:?? can we steal the DCE titlebar?\n var titleBarTemplate = _baseMvc2.default.wrapTemplate(['
', '', '
', '<%- element.element_identifier %>', \"
\", \"
\"], \"element\");\n\n return _.extend({}, _datasetLi2.default.DatasetListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n}();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection\n * (a nested DC).\n */\nvar NestedDCDCEListItemView = DCListItemView.extend(\n/** @lends NestedDCDCEListItemView.prototype */{\n className: DCListItemView.prototype.className + \" dataset-collection-element\",\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function _swapNewRender($newRender) {\n DCListItemView.prototype._swapNewRender.call(this, $newRender);\n var state = this.model.get(\"state\") || \"ok\";\n this.$el.addClass(\"state-\" + state);\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"NestedDCDCEListItemView(\" + modelString + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n DCListItemView: DCListItemView,\n DCEListItemView: DCEListItemView,\n DatasetDCEListItemView: DatasetDCEListItemView,\n NestedDCDCEListItemView: NestedDCDCEListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 44 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Generic form view */\nvar View = Backbone.View.extend({\n initialize: function initialize(options) {\n this.model = new Backbone.Model(options);\n this.url = this.model.get(\"url\");\n this.redirect = this.model.get(\"redirect\");\n this.setElement(\"\");\n this.render();\n },\n\n render: function render() {\n var self = this;\n $.ajax({\n url: Galaxy.root + this.url,\n type: \"GET\"\n }).done(function (response) {\n var options = $.extend({}, self.model.attributes, response);\n var form = new _formView2.default({\n title: options.title,\n message: options.message,\n status: options.status || \"warning\",\n icon: options.icon,\n inputs: options.inputs,\n buttons: {\n submit: new _uiMisc2.default.Button({\n tooltip: options.submit_tooltip,\n title: options.submit_title || \"Save\",\n icon: options.submit_icon || \"fa-save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function onclick() {\n self._submit(form);\n }\n })\n }\n });\n self.$el.empty().append(form.$el);\n }).fail(function (response) {\n self.$el.empty().append(new _uiMisc2.default.Message({\n message: \"Failed to load resource \" + self.url + \".\",\n status: \"danger\",\n persistent: true\n }).$el);\n });\n },\n\n _submit: function _submit(form) {\n var self = this;\n $.ajax({\n url: Galaxy.root + self.url,\n data: JSON.stringify(form.data.create()),\n type: \"PUT\",\n contentType: \"application/json\"\n }).done(function (response) {\n var success_message = {\n message: response.message,\n status: \"success\",\n persistent: false\n };\n if (self.redirect) {\n window.location = Galaxy.root + self.redirect + \"?\" + $.param(success_message);\n } else {\n form.data.matchModel(response, function (input, input_id) {\n form.field_list[input_id].value(input.value);\n });\n self._showMessage(form, success_message);\n }\n }).fail(function (response) {\n self._showMessage(form, {\n message: response.responseJSON.err_msg,\n status: \"danger\",\n persistent: false\n });\n });\n },\n\n _showMessage: function _showMessage(form, options) {\n var $panel = form.$el.parents().filter(function () {\n return [\"auto\", \"scroll\"].indexOf($(this).css(\"overflow\")) != -1;\n }).first();\n $panel.animate({ scrollTop: 0 }, 500);\n form.message.update(options);\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 45 */,\n/* 46 */,\n/* 47 */,\n/* 48 */,\n/* 49 */,\n/* 50 */,\n/* 51 */,\n/* 52 */,\n/* 53 */,\n/* 54 */,\n/* 55 */,\n/* 56 */,\n/* 57 */,\n/* 58 */,\n/* 59 */,\n/* 60 */,\n/* 61 */,\n/* 62 */,\n/* 63 */,\n/* 64 */,\n/* 65 */,\n/* 66 */,\n/* 67 */,\n/* 68 */,\n/* 69 */,\n/* 70 */,\n/* 71 */,\n/* 72 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"dataset\";\n//==============================================================================\nvar searchableMixin = _baseMvc2.default.SearchableModelMixin;\n/** @class base model for any DatasetAssociation (HDAs, LDDAs, DatasetCollectionDAs).\n * No knowledge of what type (HDA/LDDA/DCDA) should be needed here.\n * The DA's are made searchable (by attribute) by mixing in SearchableModelMixin.\n */\nvar DatasetAssociation = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.mixin(searchableMixin,\n/** @lends DatasetAssociation.prototype */{\n _logNamespace: logNamespace,\n\n /** default attributes for a model */\n defaults: {\n state: _states2.default.NEW,\n deleted: false,\n purged: false,\n name: \"(unnamed dataset)\",\n accessible: true,\n // sniffed datatype (sam, tabular, bed, etc.)\n data_type: \"\",\n file_ext: \"\",\n file_size: 0,\n\n // array of associated file types (eg. [ 'bam_index', ... ])\n meta_files: [],\n\n misc_blurb: \"\",\n misc_info: \"\",\n\n tags: []\n // do NOT default on annotation, as this default is valid and will be passed on 'save'\n // which is incorrect behavior when the model is only partially fetched (annos are not passed in summary data)\n //annotation : ''\n },\n\n /** instance vars and listeners */\n initialize: function initialize(attributes, options) {\n this.debug(this + \"(Dataset).initialize\", attributes, options);\n\n //!! this state is not in trans.app.model.Dataset.states - set it here -\n if (!this.get(\"accessible\")) {\n this.set(\"state\", _states2.default.NOT_VIEWABLE);\n }\n\n /** Datasets rely/use some web controllers - have the model generate those URLs on startup */\n this.urls = this._generateUrls();\n\n this._setUpListeners();\n },\n\n /** returns misc. web urls for rendering things like re-run, display, etc. */\n _generateUrls: function _generateUrls() {\n var id = this.get(\"id\");\n if (!id) {\n return {};\n }\n var urls = {\n purge: \"datasets/\" + id + \"/purge_async\",\n display: \"datasets/\" + id + \"/display/?preview=True\",\n edit: \"datasets/edit?dataset_id=\" + id,\n download: \"datasets/\" + id + \"/display\" + this._downloadQueryParameters(),\n report_error: \"dataset/errors?id=\" + id,\n rerun: \"tool_runner/rerun?id=\" + id,\n show_params: \"datasets/\" + id + \"/show_params\",\n visualization: \"visualization\",\n meta_download: \"dataset/get_metadata_file?hda_id=\" + id + \"&metadata_name=\"\n };\n _.each(urls, function (value, key) {\n urls[key] = Galaxy.root + value;\n });\n this.urls = urls;\n return urls;\n },\n\n _downloadQueryParameters: function _downloadQueryParameters() {\n return \"?to_ext=\" + this.get(\"file_ext\");\n },\n\n /** set up any event listeners\n * event: state:ready fired when this DA moves into/is already in a ready state\n */\n _setUpListeners: function _setUpListeners() {\n // if the state has changed and the new state is a ready state, fire an event\n this.on(\"change:state\", function (currModel, newState) {\n this.log(this + \" has changed state:\", currModel, newState);\n if (this.inReadyState()) {\n this.trigger(\"state:ready\", currModel, newState, this.previous(\"state\"));\n }\n });\n // the download url (currently) relies on having a correct file extension\n this.on(\"change:id change:file_ext\", function (currModel) {\n this._generateUrls();\n });\n },\n\n // ........................................................................ common queries\n /** override to add urls */\n toJSON: function toJSON() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n //console.warn( 'returning json?' );\n //return json;\n return _.extend(json, {\n urls: this.urls\n });\n },\n\n /** Is this dataset deleted or purged? */\n isDeletedOrPurged: function isDeletedOrPurged() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n /** Is this dataset in a 'ready' state; where 'Ready' states are states where no\n * processing (for the ds) is left to do on the server.\n */\n inReadyState: function inReadyState() {\n var ready = _.contains(_states2.default.READY_STATES, this.get(\"state\"));\n return this.isDeletedOrPurged() || ready;\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function hasDetails() {\n // if it's inaccessible assume it has everything it needs\n if (!this.get(\"accessible\")) {\n return true;\n }\n return this.has(\"annotation\");\n },\n\n /** Convenience function to match dataset.has_data. */\n hasData: function hasData() {\n return this.get(\"file_size\") > 0;\n },\n\n // ........................................................................ ajax\n fetch: function fetch(options) {\n var dataset = this;\n return Backbone.Model.prototype.fetch.call(this, options).always(function () {\n dataset._generateUrls();\n });\n },\n\n /** override to use actual Dates objects for create/update times */\n parse: function parse(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** override to wait by default */\n save: function save(attrs, options) {\n options = options || {};\n options.wait = _.isUndefined(options.wait) ? true : options.wait;\n return Backbone.Model.prototype.save.call(this, attrs, options);\n },\n\n //NOTE: subclasses of DA's will need to implement url and urlRoot in order to have these work properly\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function _delete(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function undelete(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** remove the file behind this dataset from the filesystem (if permitted) */\n purge: function _purge(options) {\n //TODO: use, override model.destroy, HDA.delete({ purge: true })\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n options = options || {};\n options.url = this.urls.purge;\n\n //TODO: ideally this would be a DELETE call to the api\n // using purge async for now\n var hda = this;\n\n var xhr = jQuery.ajax(options);\n xhr.done(function (message, status, responseObj) {\n hda.set({ deleted: true, purged: true });\n });\n xhr.fail(function (xhr, status, message) {\n // Exception messages are hidden within error page including: '...not allowed in this Galaxy instance.'\n // unbury and re-add to xhr\n var error = (0, _localization2.default)(\"Unable to purge dataset\");\n var messageBuriedInUnfortunatelyFormattedError = \"Removal of datasets by users \" + \"is not allowed in this Galaxy instance\";\n if (xhr.responseJSON && xhr.responseJSON.error) {\n error = xhr.responseJSON.error;\n } else if (xhr.responseText.indexOf(messageBuriedInUnfortunatelyFormattedError) !== -1) {\n error = messageBuriedInUnfortunatelyFormattedError;\n }\n xhr.responseText = error;\n hda.trigger(\"error\", hda, xhr, options, (0, _localization2.default)(error), {\n error: error\n });\n });\n return xhr;\n },\n\n // ........................................................................ searching\n /** what attributes of an HDA will be used in a text search */\n searchAttributes: [\"name\", \"file_ext\", \"genome_build\", \"misc_blurb\", \"misc_info\", \"annotation\", \"tags\"],\n\n /** our attr keys don't often match the labels we display to the user - so, when using\n * attribute specifiers ('name=\"bler\"') in a term, allow passing in aliases for the\n * following attr keys.\n */\n searchAliases: {\n title: \"name\",\n format: \"file_ext\",\n database: \"genome_build\",\n blurb: \"misc_blurb\",\n description: \"misc_blurb\",\n info: \"misc_info\",\n tag: \"tags\"\n },\n\n // ........................................................................ misc\n /** String representation */\n toString: function toString() {\n var nameAndId = this.get(\"id\") || \"\";\n if (this.get(\"name\")) {\n nameAndId = \"\\\"\" + this.get(\"name\") + \"\\\",\" + nameAndId;\n }\n return \"Dataset(\" + nameAndId + \")\";\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection for dataset associations.\n */\nvar DatasetAssociationCollection = Backbone.Collection.extend(_baseMvc2.default.LoggableMixin).extend(\n/** @lends HistoryContents.prototype */{\n _logNamespace: logNamespace,\n\n model: DatasetAssociation,\n\n /** root api url */\n urlRoot: Galaxy.root + \"api/datasets\",\n\n /** url fn */\n url: function url() {\n return this.urlRoot;\n },\n\n // ........................................................................ common queries\n /** Get the ids of every item in this collection\n * @returns array of encoded ids\n */\n ids: function ids() {\n return this.map(function (item) {\n return item.get(\"id\");\n });\n },\n\n /** Get contents that are not ready\n * @returns array of content models\n */\n notReady: function notReady() {\n return this.filter(function (content) {\n return !content.inReadyState();\n });\n },\n\n /** return true if any datasets don't have details */\n haveDetails: function haveDetails() {\n return this.all(function (dataset) {\n return dataset.hasDetails();\n });\n },\n\n // ........................................................................ ajax\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function ajaxQueue(ajaxFn, options) {\n var deferred = jQuery.Deferred();\n var startingLength = this.length;\n var responses = [];\n\n if (!startingLength) {\n deferred.resolve([]);\n return deferred;\n }\n\n // use reverse order (stylistic choice)\n var ajaxFns = this.chain().reverse().map(function (dataset, i) {\n return function () {\n var xhr = ajaxFn.call(dataset, options);\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(function (response) {\n deferred.notify({\n curr: i,\n total: startingLength,\n response: response,\n model: dataset\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(function (response) {\n responses.push(response);\n if (ajaxFns.length) {\n ajaxFns.shift()();\n } else {\n deferred.resolve(responses);\n }\n });\n };\n }).value();\n // start the queue\n ajaxFns.shift()();\n\n return deferred;\n },\n\n // ........................................................................ sorting/filtering\n /** return a new collection of datasets whose attributes contain the substring matchesWhat */\n matches: function matches(matchesWhat) {\n return this.filter(function (dataset) {\n return dataset.matches(matchesWhat);\n });\n },\n\n /** String representation. */\n toString: function toString() {\n return [\"DatasetAssociationCollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n DatasetAssociation: DatasetAssociation,\n DatasetAssociationCollection: DatasetAssociationCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 73 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/** @class Mixin for HistoryContents content (HDAs, HDCAs).\n */\nvar HistoryContentMixin = {\n /** default attributes for a model */\n defaults: {\n /** parent (containing) history */\n history_id: null,\n /** some content_type (HistoryContents can contain mixed model classes) */\n history_content_type: null,\n /** indicating when/what order the content was generated in the context of the history */\n hid: null,\n /** whether the user wants the content shown (visible) */\n visible: true\n },\n\n // ........................................................................ mixed content element\n // In order to be part of a MIXED bbone collection, we can't rely on the id\n // (which may collide btwn models of different classes)\n // Instead, use type_id which prefixes the history_content_type so the bbone collection can differentiate\n idAttribute: \"type_id\",\n\n // ........................................................................ common queries\n /** the more common alias of visible */\n hidden: function hidden() {\n return !this.get(\"visible\");\n },\n\n //TODO: remove\n /** based on includeDeleted, includeHidden (gen. from the container control),\n * would this ds show in the list of ds's?\n * @param {Boolean} includeDeleted are we showing deleted hdas?\n * @param {Boolean} includeHidden are we showing hidden hdas?\n */\n isVisible: function isVisible(includeDeleted, includeHidden) {\n var isVisible = true;\n if (!includeDeleted && (this.get(\"deleted\") || this.get(\"purged\"))) {\n isVisible = false;\n }\n if (!includeHidden && !this.get(\"visible\")) {\n isVisible = false;\n }\n return isVisible;\n },\n\n // ........................................................................ ajax\n //TODO?: these are probably better done on the leaf classes\n /** history content goes through the 'api/histories' API */\n urlRoot: Galaxy.root + \"api/histories/\",\n\n /** full url spec. for this content */\n url: function url() {\n var url = this.urlRoot + this.get(\"history_id\") + \"/contents/\" + this.get(\"history_content_type\") + \"s/\" + this.get(\"id\");\n return url;\n },\n\n /** save this content as not visible */\n hide: function hide(options) {\n if (!this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: false }, options);\n },\n /** save this content as visible */\n unhide: function unhide(options) {\n if (this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: true }, options);\n },\n\n // ........................................................................ misc\n toString: function toString() {\n return [this.get(\"type_id\"), this.get(\"hid\"), this.get(\"name\")].join(\":\");\n }\n};\n\n//==============================================================================\nexports.default = {\n HistoryContentMixin: HistoryContentMixin\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n\n/***/ }),\n/* 74 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/* For presentation-related functionality shared across collection creators.\n Particularily overlapping functionality related to name processing and help.\n*/\nvar CollectionCreatorMixin = {\n /** add (or clear if clear is truthy) a validation warning to the DOM element described in what */\n _validationWarning: function _validationWarning(what, clear) {\n var VALIDATION_CLASS = \"validation-warning\";\n if (what === \"name\") {\n what = this.$(\".collection-name\").add(this.$(\".collection-name-prompt\"));\n this.$(\".collection-name\").focus().select();\n }\n if (clear) {\n what = what || this.$(\".\" + VALIDATION_CLASS);\n what.removeClass(VALIDATION_CLASS);\n } else {\n what.addClass(VALIDATION_CLASS);\n }\n },\n\n _changeHideOriginals: function _changeHideOriginals(ev) {\n this.hideOriginals = this.$(\".hide-originals\").prop(\"checked\");\n },\n\n // ........................................................................ footer\n /** handle a collection name change */\n _changeName: function _changeName(ev) {\n this._validationWarning(\"name\", !!this._getName());\n },\n\n /** check for enter key press when in the collection name and submit */\n _nameCheckForEnter: function _nameCheckForEnter(ev) {\n if (ev.keyCode === 13 && !this.blocking) {\n this._clickCreate();\n }\n },\n\n /** get the current collection name */\n _getName: function _getName() {\n return _.escape(this.$(\".collection-name\").val());\n },\n\n // ........................................................................ header\n /** expand help */\n _clickMoreHelp: function _clickMoreHelp(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").addClass(\"expanded\");\n this.$(\".more-help\").hide();\n },\n /** collapse help */\n _clickLessHelp: function _clickLessHelp(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").removeClass(\"expanded\");\n this.$(\".more-help\").show();\n },\n /** toggle help */\n _toggleHelp: function _toggleHelp(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").toggleClass(\"expanded\");\n this.$(\".more-help\").toggle();\n },\n\n /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */\n _showAlert: function _showAlert(message, alertClass) {\n alertClass = alertClass || \"alert-danger\";\n this.$(\".main-help\").hide();\n this.$(\".header .alert\").attr(\"class\", \"alert alert-dismissable\").addClass(alertClass).show().find(\".alert-message\").html(message);\n },\n /** hide the alerts at the top */\n _hideAlert: function _hideAlert(message) {\n this.$(\".main-help\").show();\n this.$(\".header .alert\").hide();\n },\n\n _cancelCreate: function _cancelCreate(ev) {\n if (typeof this.oncancel === \"function\") {\n this.oncancel.call(this);\n }\n },\n\n /** attempt to create the current collection */\n _clickCreate: function _clickCreate(ev) {\n var name = this._getName();\n if (!name) {\n this._validationWarning(\"name\");\n } else if (!this.blocking) {\n this.createList(name);\n }\n },\n\n _setUpCommonSettings: function _setUpCommonSettings(attributes) {\n this.hideOriginals = attributes.defaultHideSourceItems || false;\n },\n\n /** render the footer, completion controls, and cancel controls */\n _renderFooter: function _renderFooter(speed, callback) {\n var self = this;\n var $footer = this.$(\".footer\").empty().html(this.templates.footer());\n _.each(this.footerSettings, function (property, selector) {\n self.$(selector).prop(\"checked\", self[property]);\n });\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n return $footer;\n },\n\n _creatorTemplates: {\n main: _.template(['', '', ''].join(\"\"))\n }\n};\n\n//==============================================================================\nexports.default = {\n CollectionCreatorMixin: CollectionCreatorMixin\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 75 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n// Alphanumeric/natural sort fn\nfunction naturalSort(a, b) {\n // setup temp-scope variables for comparison evauluation\n var re = /(-?[0-9\\.]+)/g;\n\n var x = a.toString().toLowerCase() || \"\";\n var y = b.toString().toLowerCase() || \"\";\n var nC = String.fromCharCode(0);\n var xN = x.replace(re, nC + \"$1\" + nC).split(nC);\n var yN = y.replace(re, nC + \"$1\" + nC).split(nC);\n var xD = new Date(x).getTime();\n var yD = xD ? new Date(y).getTime() : null;\n // natural sorting of dates\n if (yD) {\n if (xD < yD) {\n return -1;\n } else if (xD > yD) {\n return 1;\n }\n }\n\n // natural sorting through split numeric strings and default strings\n var oFxNcL;\n\n var oFyNcL;\n for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {\n oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];\n oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];\n if (oFxNcL < oFyNcL) {\n return -1;\n } else if (oFxNcL > oFyNcL) {\n return 1;\n }\n }\n return 0;\n}\n\nexports.default = naturalSort;\n\n/***/ }),\n/* 76 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n\"use_strict\";\n\nvar $ = _jquery2.default;\n//=============================================================================\n\n_jquery2.default.fn.extend({\n hoverhighlight: function $hoverhighlight(scope, color) {\n scope = scope || \"body\";\n if (!this.length) {\n return this;\n }\n\n $(this).each(function () {\n var $this = $(this);\n var targetSelector = $this.data(\"target\");\n\n if (targetSelector) {\n $this.mouseover(function (ev) {\n $(targetSelector, scope).css({\n background: color\n });\n }).mouseout(function (ev) {\n $(targetSelector).css({\n background: \"\"\n });\n });\n }\n });\n return this;\n }\n});\n\n/***/ }),\n/* 77 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _deferred = __webpack_require__(67);\n\nvar _deferred2 = _interopRequireDefault(_deferred);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _formData = __webpack_require__(70);\n\nvar _formData2 = _interopRequireDefault(_formData);\n\nvar _toolFormBase = __webpack_require__(66);\n\nvar _toolFormBase2 = _interopRequireDefault(_toolFormBase);\n\nvar _uiModal = __webpack_require__(7);\n\nvar _uiModal2 = _interopRequireDefault(_uiModal);\n\nvar _webhooks = __webpack_require__(17);\n\nvar _webhooks2 = _interopRequireDefault(_webhooks);\n\nvar _workflowIcons = __webpack_require__(148);\n\nvar _workflowIcons2 = _interopRequireDefault(_workflowIcons);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar View = Backbone.View.extend({\n initialize: function initialize(options) {\n var self = this;\n this.modal = parent.Galaxy.modal || new _uiModal2.default.View();\n this.model = options && options.model || new Backbone.Model(options);\n this.deferred = new _deferred2.default();\n this.setElement($(\"\").addClass(\"ui-form-composite\").append(this.$message = $(\"\")).append(this.$header = $(\"\")).append(this.$steps = $(\"\")));\n $(\"body\").append(this.$el);\n this._configure();\n this.render();\n $(window).resize(function () {\n self._refresh();\n });\n },\n\n /** Refresh height of scrollable div below header, handle scrolling by lazy loading steps */\n _refresh: function _refresh(step_index) {\n var margin = _.reduce(this.$el.children(), function (memo, child) {\n return memo + $(child).outerHeight();\n }, 0) - this.$steps.height() + 90;\n this.$steps.css(\"height\", $(window).height() - margin);\n },\n\n /** Configures form/step options for each workflow step */\n _configure: function _configure() {\n var self = this;\n this.forms = [];\n this.steps = [];\n this.links = [];\n this.parms = [];\n _.each(this.model.get(\"steps\"), function (step, i) {\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", i + \" : Preparing workflow step.\");\n var icon = _workflowIcons2.default[step.step_type];\n var title = parseInt(i + 1) + \": \" + (step.step_label || step.step_name);\n if (step.annotation) {\n title += \" - \" + step.annotation;\n }\n if (step.step_version) {\n title += \" (Galaxy Version \" + step.step_version + \")\";\n }\n step = _utils2.default.merge({\n index: i,\n fixed_title: _.escape(title),\n icon: icon || \"\",\n help: null,\n citations: null,\n collapsible: true,\n collapsed: i > 0 && !self._isDataStep(step),\n sustain_version: true,\n sustain_repeats: true,\n sustain_conditionals: true,\n narrow: true,\n text_enable: \"Edit\",\n text_disable: \"Undo\",\n cls_enable: \"fa fa-edit\",\n cls_disable: \"fa fa-undo\",\n errors: step.messages,\n initial_errors: true,\n cls: \"ui-portlet-narrow\",\n hide_operations: true,\n needs_refresh: false,\n always_refresh: step.step_type != \"tool\"\n }, step);\n self.steps[i] = step;\n self.links[i] = [];\n self.parms[i] = {};\n });\n\n // build linear index of step input pairs\n _.each(this.steps, function (step, i) {\n _formData2.default.visitInputs(step.inputs, function (input, name) {\n self.parms[i][name] = input;\n });\n });\n\n // iterate through data input modules and collect linked sub steps\n _.each(this.steps, function (step, i) {\n _.each(step.output_connections, function (output_connection) {\n _.each(self.steps, function (sub_step, j) {\n sub_step.step_index === output_connection.input_step_index && self.links[i].push(sub_step);\n });\n });\n });\n\n // convert all connected data inputs to hidden fields with proper labels,\n // and track the linked source step\n _.each(this.steps, function (step, i) {\n _.each(self.steps, function (sub_step, j) {\n var connections_by_name = {};\n _.each(step.output_connections, function (connection) {\n sub_step.step_index === connection.input_step_index && (connections_by_name[connection.input_name] = connection);\n });\n _.each(self.parms[j], function (input, name) {\n var connection = connections_by_name[name];\n if (connection) {\n input.type = \"hidden\";\n input.help = input.step_linked ? input.help + \", \" : \"\";\n input.help += \"Output dataset '\" + connection.output_name + \"' from step \" + (parseInt(i) + 1);\n input.step_linked = input.step_linked || [];\n input.step_linked.push(step);\n }\n });\n });\n });\n\n // identify and configure workflow parameters\n var wp_count = 0;\n this.wp_inputs = {};\n function _handleWorkflowParameter(value, callback) {\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while (match = re.exec(String(value))) {\n var wp_name = match[1];\n callback(self.wp_inputs[wp_name] = self.wp_inputs[wp_name] || {\n label: wp_name,\n name: wp_name,\n type: \"text\",\n color: \"hsl( \" + ++wp_count * 100 + \", 70%, 30% )\",\n style: \"ui-form-wp-source\",\n links: []\n });\n }\n }\n _.each(this.steps, function (step, i) {\n _.each(self.parms[i], function (input, name) {\n _handleWorkflowParameter(input.value, function (wp_input) {\n wp_input.links.push(step);\n input.wp_linked = true;\n input.type = \"text\";\n input.backdrop = true;\n input.style = \"ui-form-wp-target\";\n });\n });\n _.each(step.post_job_actions, function (pja) {\n _.each(pja.action_arguments, function (arg) {\n _handleWorkflowParameter(arg, function () {});\n });\n });\n });\n\n // select fields are shown for dynamic fields if all putative data inputs are available,\n // or if an explicit reference is specified as data_ref and available\n _.each(this.steps, function (step, i) {\n if (step.step_type == \"tool\") {\n var data_resolved = true;\n _formData2.default.visitInputs(step.inputs, function (input, name, context) {\n var is_runtime_value = input.value && input.value.__class__ == \"RuntimeValue\";\n var is_data_input = [\"data\", \"data_collection\"].indexOf(input.type) != -1;\n var data_ref = context[input.data_ref];\n input.step_linked && !self._isDataStep(input.step_linked) && (data_resolved = false);\n input.options && (input.options.length == 0 && !data_resolved || input.wp_linked) && (input.is_workflow = true);\n data_ref && (input.is_workflow = data_ref.step_linked && !self._isDataStep(data_ref.step_linked) || input.wp_linked);\n (is_data_input || input.value && input.value.__class__ == \"RuntimeValue\" && !input.step_linked) && (step.collapsed = false);\n is_runtime_value && (input.value = input.default_value);\n input.flavor = \"workflow\";\n if (!is_runtime_value && !is_data_input && input.type !== \"hidden\" && !input.wp_linked) {\n if (input.optional || !_utils2.default.isEmpty(input.value) && input.value !== \"\") {\n input.collapsible_value = input.value;\n input.collapsible_preview = true;\n }\n }\n });\n }\n });\n },\n\n render: function render() {\n var self = this;\n this.deferred.reset();\n this._renderHeader();\n this._renderMessage();\n this._renderParameters();\n this._renderHistory();\n _.each(this.steps, function (step) {\n self._renderStep(step);\n });\n },\n\n /** Render header */\n _renderHeader: function _renderHeader() {\n var self = this;\n this.execute_btn = new _uiMisc2.default.Button({\n icon: \"fa-check\",\n title: \"Run workflow\",\n cls: \"btn btn-primary\",\n onclick: function onclick() {\n self._execute();\n }\n });\n this.$header.addClass(\"ui-form-header\").empty().append(new _uiMisc2.default.Label({\n title: \"Workflow: \" + this.model.get(\"name\")\n }).$el).append(this.execute_btn.$el);\n },\n\n /** Render message */\n _renderMessage: function _renderMessage() {\n this.$message.empty();\n if (this.model.get(\"has_upgrade_messages\")) {\n this.$message.append(new _uiMisc2.default.Message({\n message: \"Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el);\n }\n var step_version_changes = this.model.get(\"step_version_changes\");\n if (step_version_changes && step_version_changes.length > 0) {\n this.$message.append(new _uiMisc2.default.Message({\n message: \"Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el);\n }\n },\n\n /** Render workflow parameters */\n _renderParameters: function _renderParameters() {\n var self = this;\n this.wp_form = null;\n if (!_.isEmpty(this.wp_inputs)) {\n this.wp_form = new _formView2.default({\n title: \"Workflow Parameters\",\n inputs: this.wp_inputs,\n cls: \"ui-portlet-narrow\",\n onchange: function onchange() {\n _.each(self.wp_form.input_list, function (input_def, i) {\n _.each(input_def.links, function (step) {\n self._refreshStep(step);\n });\n });\n }\n });\n this._append(this.$steps.empty(), this.wp_form.$el);\n }\n },\n\n /** Render workflow parameters */\n _renderHistory: function _renderHistory() {\n this.history_form = new _formView2.default({\n cls: \"ui-portlet-narrow\",\n title: \"History Options\",\n inputs: [{\n type: \"conditional\",\n name: \"new_history\",\n test_param: {\n name: \"check\",\n label: \"Send results to a new history\",\n type: \"boolean\",\n value: \"false\",\n help: \"\"\n },\n cases: [{\n value: \"true\",\n inputs: [{\n name: \"name\",\n label: \"History name\",\n type: \"text\",\n value: this.model.get(\"name\")\n }]\n }]\n }]\n });\n this._append(this.$steps, this.history_form.$el);\n },\n\n /** Render step */\n _renderStep: function _renderStep(step) {\n var self = this;\n var form = null;\n this.deferred.execute(function (promise) {\n self.$steps.addClass(\"ui-steps\");\n if (step.step_type == \"tool\") {\n step.postchange = function (process, form) {\n var self = this;\n var current_state = {\n tool_id: step.id,\n tool_version: step.version,\n inputs: $.extend(true, {}, form.data.create())\n };\n form.wait(true);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Sending current state.\", current_state);\n _utils2.default.request({\n type: \"POST\",\n url: Galaxy.root + \"api/tools/\" + step.id + \"/build\",\n data: current_state,\n success: function success(data) {\n form.update(data);\n form.wait(false);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Received new model.\", data);\n process.resolve();\n },\n error: function error(response) {\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Refresh request failed.\", response);\n process.reject();\n }\n });\n };\n form = new _toolFormBase2.default(step);\n if (step.post_job_actions && step.post_job_actions.length) {\n form.portlet.append($(\"\").addClass(\"ui-form-element-disabled\").append($(\"\").addClass(\"ui-form-title\").html(\"Job Post Actions\")).append($(\"\").addClass(\"ui-form-preview\").html(_.reduce(step.post_job_actions, function (memo, value) {\n return memo + \" \" + value.short_str;\n }, \"\"))));\n }\n } else {\n var is_simple_input = [\"data_input\", \"data_collection_input\"].indexOf(step.step_type) != -1;\n _.each(step.inputs, function (input) {\n input.flavor = \"module\";\n input.hide_label = is_simple_input;\n });\n form = new _formView2.default(_utils2.default.merge({\n title: step.fixed_title,\n onchange: function onchange() {\n _.each(self.links[step.index], function (link) {\n self._refreshStep(link);\n });\n },\n inputs: step.inputs && step.inputs.length > 0 ? step.inputs : [{\n type: \"hidden\",\n name: \"No options available.\",\n ignore: null\n }]\n }, step));\n }\n self.forms[step.index] = form;\n self._append(self.$steps, form.$el);\n self._refresh();\n step.needs_refresh && self._refreshStep(step);\n form.portlet[!self.show_progress ? \"enable\" : \"disable\"]();\n self.show_progress && self.execute_btn.model.set({\n wait: true,\n wait_text: \"Preparing...\",\n percentage: (step.index + 1) * 100.0 / self.steps.length\n });\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", step.index + \" : Workflow step state ready.\", step);\n setTimeout(function () {\n promise.resolve();\n }, 0);\n });\n },\n\n /** Refreshes step values from source step values */\n _refreshStep: function _refreshStep(step) {\n var self = this;\n var form = this.forms[step.index];\n if (form) {\n _.each(self.parms[step.index], function (input, name) {\n if (input.step_linked || input.wp_linked) {\n var field = form.field_list[form.data.match(name)];\n if (field) {\n var new_value = undefined;\n if (input.step_linked) {\n new_value = { values: [] };\n _.each(input.step_linked, function (source_step) {\n if (self._isDataStep(source_step)) {\n var value = self.forms[source_step.index].data.create().input;\n value && _.each(value.values, function (v) {\n new_value.values.push(v);\n });\n }\n });\n if (!input.multiple && new_value.values.length > 0) {\n new_value = {\n values: [new_value.values[0]]\n };\n }\n } else if (input.wp_linked) {\n new_value = input.value;\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while (match = re.exec(input.value)) {\n var wp_field = self.wp_form.field_list[self.wp_form.data.match(match[1])];\n var wp_value = wp_field && wp_field.value();\n if (wp_value) {\n new_value = new_value.split(match[0]).join(wp_value);\n }\n }\n }\n if (new_value !== undefined) {\n field.value(new_value);\n }\n }\n }\n });\n form.trigger(\"change\");\n } else {\n step.needs_refresh = true;\n }\n },\n\n /** Refresh the history after job submission while form is shown */\n _refreshHistory: function _refreshHistory() {\n var self = this;\n var history = parent.Galaxy && parent.Galaxy.currHistoryPanel && parent.Galaxy.currHistoryPanel.model;\n this._refresh_history && clearTimeout(this._refresh_history);\n if (history) {\n history.refresh().success(function () {\n if (history.numOfUnfinishedShownContents() === 0) {\n self._refresh_history = setTimeout(function () {\n self._refreshHistory();\n }, history.UPDATE_DELAY);\n }\n });\n }\n },\n\n /** Build remaining steps */\n _execute: function _execute() {\n var self = this;\n this.show_progress = true;\n this._enabled(false);\n this.deferred.execute(function (promise) {\n setTimeout(function () {\n promise.resolve();\n self._submit();\n }, 0);\n });\n },\n\n /** Validate and submit workflow */\n _submit: function _submit() {\n var self = this;\n var history_form_data = this.history_form.data.create();\n var job_def = {\n new_history_name: history_form_data[\"new_history|name\"] ? history_form_data[\"new_history|name\"] : null,\n history_id: !history_form_data[\"new_history|name\"] ? this.model.get(\"history_id\") : null,\n replacement_params: this.wp_form ? this.wp_form.data.create() : {},\n parameters: {},\n // Tool form will submit flat maps for each parameter\n // (e.g. \"repeat_0|cond|param\": \"foo\" instead of nested\n // data structures).\n parameters_normalized: true,\n // Tool form always wants a list of invocations back\n // so that inputs can be batched.\n batch: true\n };\n var validated = true;\n for (var i in this.forms) {\n var form = this.forms[i];\n var job_inputs = form.data.create();\n var step = self.steps[i];\n var step_index = step.step_index;\n form.trigger(\"reset\");\n for (var job_input_id in job_inputs) {\n var input_value = job_inputs[job_input_id];\n var input_id = form.data.match(job_input_id);\n var input_field = form.field_list[input_id];\n var input_def = form.input_list[input_id];\n if (!input_def.step_linked) {\n if (this._isDataStep(step)) {\n validated = input_value && input_value.values && input_value.values.length > 0;\n } else {\n validated = input_def.optional || input_def.is_workflow && input_value !== \"\" || !input_def.is_workflow && input_value !== null;\n }\n if (!validated) {\n form.highlight(input_id);\n break;\n }\n job_def.parameters[step_index] = job_def.parameters[step_index] || {};\n job_def.parameters[step_index][job_input_id] = job_inputs[job_input_id];\n }\n }\n if (!validated) {\n break;\n }\n }\n if (!validated) {\n self._enabled(true);\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation failed.\", job_def);\n } else {\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation complete.\", job_def);\n _utils2.default.request({\n type: \"POST\",\n url: Galaxy.root + \"api/workflows/\" + this.model.id + \"/invocations\",\n data: job_def,\n success: function success(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission successful.\", response);\n self.$el.children().hide();\n self.$el.append(self._templateSuccess(response));\n\n // Show Webhook if job is running\n if ($.isArray(response) && response.length > 0) {\n self.$el.append($(\"\", { id: \"webhook-view\" }));\n var WebhookApp = new _webhooks2.default.WebhookView({\n urlRoot: Galaxy.root + \"api/webhooks/workflow\",\n toolId: job_def.tool_id,\n toolVersion: job_def.tool_version\n });\n }\n\n self._refreshHistory();\n },\n error: function error(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission failed.\", response);\n var input_found = false;\n if (response && response.err_data) {\n for (var i in self.forms) {\n var form = self.forms[i];\n var step_related_errors = response.err_data[form.model.get(\"step_index\")];\n if (step_related_errors) {\n var error_messages = form.data.matchResponse(step_related_errors);\n for (var input_id in error_messages) {\n form.highlight(input_id, error_messages[input_id]);\n input_found = true;\n break;\n }\n }\n }\n }\n if (!input_found) {\n self.modal.show({\n title: \"Workflow submission failed\",\n body: self._templateError(job_def, response && response.err_msg),\n buttons: {\n Close: function Close() {\n self.modal.hide();\n }\n }\n });\n }\n },\n complete: function complete() {\n self._enabled(true);\n }\n });\n }\n },\n\n /** Append new dom to body */\n _append: function _append($container, $el) {\n $container.append(\"\").append($el);\n },\n\n /** Set enabled/disabled state */\n _enabled: function _enabled(enabled) {\n this.execute_btn.model.set({\n wait: !enabled,\n wait_text: \"Sending...\",\n percentage: -1\n });\n this.wp_form && this.wp_form.portlet[enabled ? \"enable\" : \"disable\"]();\n this.history_form && this.history_form.portlet[enabled ? \"enable\" : \"disable\"]();\n _.each(this.forms, function (form) {\n form && form.portlet[enabled ? \"enable\" : \"disable\"]();\n });\n },\n\n /** Is data input module/step */\n _isDataStep: function _isDataStep(steps) {\n var lst = $.isArray(steps) ? steps : [steps];\n for (var i = 0; i < lst.length; i++) {\n var step = lst[i];\n if (!step || !step.step_type || !step.step_type.startsWith(\"data\")) {\n return false;\n }\n }\n return true;\n },\n\n /** Templates */\n _templateSuccess: function _templateSuccess(response) {\n if ($.isArray(response) && response.length > 0) {\n return $(\"\").addClass(\"donemessagelarge\").append($(\"\").html(\"Successfully invoked workflow \" + _utils2.default.sanitize(this.model.get(\"name\")) + \"\" + (response.length > 1 ? \" \" + response.length + \" times\" : \"\") + \".\")).append($(\"\").append(\"\").text(\"You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.\"));\n } else {\n return this._templateError(response, \"Invalid success response. No invocations found.\");\n }\n },\n\n _templateError: function _templateError(response, err_msg) {\n return $(\"\").addClass(\"errormessagelarge\").append($(\"\").text(\"The server could not complete the request. Please contact the Galaxy Team if this error persists. \" + (JSON.stringify(err_msg) || \"\"))).append($(\"\").text(JSON.stringify(response, null, 4)));\n }\n}); /** This is the run workflow tool form view. */\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 78 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, jQuery, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _uiModal = __webpack_require__(7);\n\nvar _uiModal2 = _interopRequireDefault(_uiModal);\n\nvar _errorModal = __webpack_require__(79);\n\nvar _errorModal2 = _interopRequireDefault(_errorModal);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/**\n * A dialog/modal that allows copying a user history or 'importing' from user\n * another. Generally called via historyCopyDialog below.\n * @type {Object}\n */\nvar CopyDialog = {\n // language related strings/fns\n defaultName: _.template(\"Copy of '<%- name %>'\"),\n title: _.template((0, _localization2.default)(\"Copying history\") + \" \\\"<%- name %>\\\"\"),\n submitLabel: (0, _localization2.default)(\"Copy\"),\n errorMessage: (0, _localization2.default)(\"History could not be copied.\"),\n progressive: (0, _localization2.default)(\"Copying history\"),\n activeLabel: (0, _localization2.default)(\"Copy only the active, non-deleted datasets\"),\n allLabel: (0, _localization2.default)(\"Copy all datasets including deleted ones\"),\n anonWarning: (0, _localization2.default)(\"As an anonymous user, unless you login or register, you will lose your current history \") + (0, _localization2.default)(\"after copying this history. \"),\n\n // template for modal body\n _template: _.template([\n //TODO: remove inline styles\n // show a warning message for losing current to anon users\n \"<% if( isAnon ){ %>\", '
\", \"<% } %>\", \"\"].join(\"\")),\n\n // empty modal body and let the user know the copy is happening\n _showAjaxIndicator: function _showAjaxIndicator() {\n var indicator = \"
\" + this.progressive + \"...
\";\n this.modal.$(\".modal-body\").empty().append(indicator).css({ \"margin-top\": \"8px\" });\n },\n\n // (sorta) public interface - display the modal, render the form, and potentially copy the history\n // returns a jQuery.Deferred done->history copied, fail->user cancelled\n dialog: function _dialog(modal, history, options) {\n options = options || {};\n\n var dialog = this;\n var deferred = jQuery.Deferred();\n\n var // TODO: getting a little byzantine here\n defaultCopyNameFn = options.nameFn || this.defaultName;\n\n var defaultCopyName = defaultCopyNameFn({\n name: history.get(\"name\")\n });\n\n var // TODO: these two might be simpler as one 3 state option (all,active,no-choice)\n defaultCopyWhat = options.allDatasets ? \"copy-all\" : \"copy-non-deleted\";\n\n var allowAll = !_.isUndefined(options.allowAll) ? options.allowAll : true;\n\n var autoClose = !_.isUndefined(options.autoClose) ? options.autoClose : true;\n\n this.modal = modal;\n\n // validate the name and copy if good\n function checkNameAndCopy() {\n var name = modal.$(\"#copy-modal-title\").val();\n if (!name) {\n modal.$(\".invalid-title\").show();\n return;\n }\n // get further settings, shut down and indicate the ajax call, then hide and resolve/reject\n var copyAllDatasets = modal.$('input[name=\"copy-what\"]:checked').val() === \"copy-all\";\n modal.$(\"button\").prop(\"disabled\", true);\n dialog._showAjaxIndicator();\n history.copy(true, name, copyAllDatasets).done(function (response) {\n deferred.resolve(response);\n }).fail(function (xhr, status, message) {\n var options = {\n name: name,\n copyAllDatasets: copyAllDatasets\n };\n _errorModal2.default.ajaxErrorModal(history, xhr, options, dialog.errorMessage);\n deferred.rejectWith(deferred, arguments);\n }).done(function () {\n if (autoClose) {\n modal.hide();\n }\n });\n }\n\n var originalClosingCallback = options.closing_callback;\n modal.show(_.extend(options, {\n title: this.title({ name: history.get(\"name\") }),\n body: $(dialog._template({\n name: defaultCopyName,\n isAnon: Galaxy.user.isAnonymous(),\n allowAll: allowAll,\n copyWhat: defaultCopyWhat,\n activeLabel: this.activeLabel,\n allLabel: this.allLabel,\n anonWarning: this.anonWarning\n })),\n buttons: _.object([[(0, _localization2.default)(\"Cancel\"), function () {\n modal.hide();\n }], [this.submitLabel, checkNameAndCopy]]),\n height: \"auto\",\n closing_events: true,\n closing_callback: function _historyCopyClose(cancelled) {\n if (cancelled) {\n deferred.reject({ cancelled: true });\n }\n if (originalClosingCallback) {\n originalClosingCallback(cancelled);\n }\n }\n }));\n\n // set the default dataset copy, autofocus the title, and set up for a simple return\n modal.$(\"#copy-modal-title\").focus().select();\n modal.$(\"#copy-modal-title\").on(\"keydown\", function (ev) {\n if (ev.keyCode === 13) {\n ev.preventDefault();\n checkNameAndCopy();\n }\n });\n\n return deferred;\n }\n};\n\n//==============================================================================\n// maintain the (slight) distinction between copy and import\n/**\n * Subclass CopyDialog to use the import language.\n */\nvar ImportDialog = _.extend({}, CopyDialog, {\n defaultName: _.template(\"imported: <%- name %>\"),\n title: _.template((0, _localization2.default)(\"Importing history\") + \" \\\"<%- name %>\\\"\"),\n submitLabel: (0, _localization2.default)(\"Import\"),\n errorMessage: (0, _localization2.default)(\"History could not be imported.\"),\n progressive: (0, _localization2.default)(\"Importing history\"),\n activeLabel: (0, _localization2.default)(\"Import only the active, non-deleted datasets\"),\n allLabel: (0, _localization2.default)(\"Import all datasets including deleted ones\"),\n anonWarning: (0, _localization2.default)(\"As an anonymous user, unless you login or register, you will lose your current history \") + (0, _localization2.default)(\"after importing this history. \")\n});\n\n//==============================================================================\n/**\n * Main interface for both history import and history copy dialogs.\n * @param {Backbone.Model} history the history to copy\n * @param {Object} options a hash\n * @return {jQuery.Deferred} promise that fails on close and succeeds on copy\n *\n * options:\n * (this object is also passed to the modal used to display the dialog and accepts modal options)\n * {Function} nameFn if defined, use this to build the default name shown to the user\n * (the fn is passed: {name: })\n * {bool} useImport if true, use the 'import' language (instead of Copy)\n * {bool} allowAll if true, allow the user to choose between copying all datasets and\n * only non-deleted datasets\n * {String} allDatasets default initial checked radio button: 'copy-all' or 'copy-non-deleted',\n */\nvar historyCopyDialog = function historyCopyDialog(history, options) {\n options = options || {};\n // create our own modal if Galaxy doesn't have one (mako tab without use_panels)\n var modal = window.parent.Galaxy.modal || new _uiModal2.default.View({});\n return options.useImport ? ImportDialog.dialog(modal, history, options) : CopyDialog.dialog(modal, history, options);\n};\n\n//==============================================================================\nexports.default = historyCopyDialog;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 79 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function($, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//TODO: toastr is another possibility - I didn't see where I might add details, tho\n\n/* ============================================================================\nError modals meant to replace the o-so-easy alerts.\n\nThese are currently styled as errormessages but use the Galaxy.modal\ninfrastructure to be shown/closed. They're capable of showing details in a\ntogglable dropdown and the details are formatted in a pre.\n\nExample:\n errorModal( 'Heres a message', 'A Title', { some_details: 'here' });\n errorModal( 'Heres a message' ); // no details, title is 'Error'\n\nThere are three specialized forms:\n offlineErrorModal a canned response for when there's no connection\n badGatewayErrorModal canned response for when Galaxy is restarting\n ajaxErrorModal plugable into any Backbone class as an\n error event handler by accepting the error args: model, xhr, options\n\nExamples:\n if( navigator.offLine ){ offlineErrorModal(); }\n if( xhr.status === 502 ){ badGatewayErrorModal(); }\n this.listenTo( this.model, 'error', ajaxErrorModal );\n\n============================================================================ */\n\nvar CONTACT_MSG = (0, _localization2.default)(\"Please contact a Galaxy administrator if the problem persists.\");\nvar DEFAULT_AJAX_ERR_MSG = (0, _localization2.default)(\"An error occurred while updating information with the server.\");\nvar DETAILS_MSG = (0, _localization2.default)(\"The following information can assist the developers in finding the source of the error:\");\n\n/** private helper that builds the modal and handles adding details */\nfunction _errorModal(message, title, details) {\n // create and return the modal, adding details button only if needed\n Galaxy.modal.show({\n title: title,\n body: message,\n closing_events: true,\n buttons: {\n Ok: function Ok() {\n Galaxy.modal.hide();\n }\n }\n });\n Galaxy.modal.$el.addClass(\"error-modal\");\n\n if (details) {\n Galaxy.modal.$(\".error-details\").add(Galaxy.modal.$('button:contains(\"Details\")')).remove();\n $(\"\").addClass(\"error-details\").hide().appendTo(Galaxy.modal.$(\".modal-content\")).append([$(\"\").text(DETAILS_MSG), $(\"\").text(JSON.stringify(details, null, \" \"))]);\n\n $(\"\").appendTo(Galaxy.modal.$(\".buttons\")).click(function () {\n Galaxy.modal.$(\".error-details\").toggle();\n });\n }\n return Galaxy.modal;\n}\n\n/** Display a modal showing an error message but fallback to alert if there's no modal */\nfunction errorModal(message, title, details) {\n if (!message) {\n return;\n }\n\n message = (0, _localization2.default)(message);\n title = (0, _localization2.default)(title) || (0, _localization2.default)(\"Error:\");\n if (window.Galaxy && Galaxy.modal) {\n return _errorModal(message, title, details);\n }\n\n alert(title + \"\\n\\n\" + message);\n console.log(\"error details:\", JSON.stringify(details));\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal when the user may be offline */\nfunction offlineErrorModal() {\n return errorModal((0, _localization2.default)(\"You appear to be offline. Please check your connection and try again.\"), (0, _localization2.default)(\"Offline?\"));\n}\n\n// ----------------------------------------------------------------------------\n/** 502 messages that should be displayed when galaxy is restarting */\nfunction badGatewayErrorModal() {\n return errorModal((0, _localization2.default)(\"Galaxy is currently unreachable. Please try again in a few minutes.\") + \" \" + CONTACT_MSG, (0, _localization2.default)(\"Cannot connect to Galaxy\"));\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal (with details) about a failed Backbone ajax operation */\nfunction ajaxErrorModal(model, xhr, options, message, title) {\n message = message || DEFAULT_AJAX_ERR_MSG;\n message += \" \" + CONTACT_MSG;\n title = title || (0, _localization2.default)(\"An error occurred\");\n var details = _ajaxDetails(model, xhr, options);\n return errorModal(message, title, details);\n}\n\n/** build details which may help debugging the ajax call */\nfunction _ajaxDetails(model, xhr, options) {\n return {\n //TODO: still can't manage Raven id\n raven: _.result(window.Raven, \"lastEventId\"),\n userAgent: navigator.userAgent,\n onLine: navigator.onLine,\n version: _.result(Galaxy.config, \"version_major\"),\n xhr: _.omit(xhr, _.functions(xhr)),\n options: _.omit(options, \"xhr\"),\n // add ajax data from Galaxy object cache\n url: _.result(Galaxy.lastAjax, \"url\"),\n data: _.result(Galaxy.lastAjax, \"data\"),\n // backbone stuff (auto-redacting email for user)\n model: _.result(model, \"toJSON\", \"\" + model),\n user: _.omit(_.result(Galaxy.user, \"toJSON\"), \"email\")\n };\n}\n\n//=============================================================================\nexports.default = {\n errorModal: errorModal,\n offlineErrorModal: offlineErrorModal,\n badGatewayErrorModal: badGatewayErrorModal,\n ajaxErrorModal: ajaxErrorModal\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 80 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _underscore = __webpack_require__(1);\n\nvar _ = _interopRequireWildcard(_underscore);\n\nvar _backbone = __webpack_require__(2);\n\nvar Backbone = _interopRequireWildcard(_backbone);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }\n\n//=============================================================================\n/**\n * A Collection that can be limited/offset/re-ordered/filtered.\n * @type {Backbone.Collection}\n */\nvar ControlledFetchCollection = Backbone.Collection.extend({\n /** call setOrder on initialization to build the comparator based on options */\n initialize: function initialize(models, options) {\n Backbone.Collection.prototype.initialize.call(this, models, options);\n this.setOrder(options.order || this.order, { silent: true });\n },\n\n /** set up to track order changes and re-sort when changed */\n _setUpListeners: function _setUpListeners() {\n return this.on({\n \"changed-order\": this.sort\n });\n },\n\n /** override to provide order and offsets based on instance vars, set limit if passed,\n * and set allFetched/fire 'all-fetched' when xhr returns\n */\n fetch: function fetch(options) {\n options = this._buildFetchOptions(options);\n Galaxy.debug(\"fetch options:\", options);\n return Backbone.Collection.prototype.fetch.call(this, options);\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function _buildFetchOptions(options) {\n // note: we normally want options passed in to override the defaults built here\n // so most of these fns will generate defaults\n options = _.clone(options) || {};\n var self = this;\n\n // jquery ajax option; allows multiple q/qv for filters (instead of 'q[]')\n options.traditional = true;\n\n // options.data\n // we keep limit, offset, etc. in options *as well as move it into data* because:\n // - it makes fetch calling convenient to add it to a single options map (instead of as mult. args)\n // - it allows the std. event handlers (for fetch, etc.) to have access\n // to the pagination options too\n // (i.e. this.on( 'sync', function( options ){ if( options.limit ){ ... } }))\n // however, when we send to xhr/jquery we copy them to data also so that they become API query params\n options.data = options.data || self._buildFetchData(options);\n Galaxy.debug(\"data:\", options.data);\n\n // options.data.filters --> options.data.q, options.data.qv\n var filters = this._buildFetchFilters(options);\n Galaxy.debug(\"filters:\", filters);\n if (!_.isEmpty(filters)) {\n _.extend(options.data, this._fetchFiltersToAjaxData(filters));\n }\n Galaxy.debug(\"data:\", options.data);\n return options;\n },\n\n /** Build the dictionary to send to fetch's XHR as data */\n _buildFetchData: function _buildFetchData(options) {\n var defaults = {};\n if (this.order) {\n defaults.order = this.order;\n }\n return _.defaults(_.pick(options, this._fetchParams), defaults);\n },\n\n /** These attribute keys are valid params to fetch/API-index */\n _fetchParams: [\n /** model dependent string to control the order of models returned */\n \"order\",\n /** limit the number of models returned from a fetch */\n \"limit\",\n /** skip this number of models when fetching */\n \"offset\",\n /** what series of attributes to return (model dependent) */\n \"view\",\n /** individual keys to return for the models (see api/histories.index) */\n \"keys\"],\n\n /** add any needed filters here based on collection state */\n _buildFetchFilters: function _buildFetchFilters(options) {\n // override\n return _.clone(options.filters || {});\n },\n\n /** Convert dictionary filters to qqv style arrays */\n _fetchFiltersToAjaxData: function _fetchFiltersToAjaxData(filters) {\n // return as a map so ajax.data can extend from it\n var filterMap = {\n q: [],\n qv: []\n };\n _.each(filters, function (v, k) {\n // don't send if filter value is empty\n if (v === undefined || v === \"\") {\n return;\n }\n // json to python\n if (v === true) {\n v = \"True\";\n }\n if (v === false) {\n v = \"False\";\n }\n if (v === null) {\n v = \"None\";\n }\n // map to k/v arrays (q/qv)\n filterMap.q.push(k);\n filterMap.qv.push(v);\n });\n return filterMap;\n },\n\n /** override to reset allFetched flag to false */\n reset: function reset(models, options) {\n this.allFetched = false;\n return Backbone.Collection.prototype.reset.call(this, models, options);\n },\n\n // ........................................................................ order\n order: null,\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: {\n update_time: _baseMvc2.default.buildComparator(\"update_time\", {\n ascending: false\n }),\n \"update_time-asc\": _baseMvc2.default.buildComparator(\"update_time\", {\n ascending: true\n }),\n create_time: _baseMvc2.default.buildComparator(\"create_time\", {\n ascending: false\n }),\n \"create_time-asc\": _baseMvc2.default.buildComparator(\"create_time\", {\n ascending: true\n })\n },\n\n /** set the order and comparator for this collection then sort with the new order\n * @event 'changed-order' passed the new order and the collection\n */\n setOrder: function setOrder(order, options) {\n options = options || {};\n var collection = this;\n var comparator = collection.comparators[order];\n if (_.isUndefined(comparator)) {\n throw new Error(\"unknown order: \" + order);\n }\n // if( _.isUndefined( comparator ) ){ return; }\n if (comparator === collection.comparator) {\n return;\n }\n\n collection.order = order;\n collection.comparator = comparator;\n\n if (!options.silent) {\n collection.trigger(\"changed-order\", options);\n }\n return collection;\n }\n});\n\n//=============================================================================\n/**\n *\n */\nvar PaginatedCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for each page's fetch */\n limitPerPage: 500,\n\n initialize: function initialize(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n this.currentPage = options.currentPage || 0;\n },\n\n getTotalItemCount: function getTotalItemCount() {\n return this.length;\n },\n\n shouldPaginate: function shouldPaginate() {\n return this.getTotalItemCount() >= this.limitPerPage;\n },\n\n getLastPage: function getLastPage() {\n return Math.floor(this.getTotalItemCount() / this.limitPerPage);\n },\n\n getPageCount: function getPageCount() {\n return this.getLastPage() + 1;\n },\n\n getPageLimitOffset: function getPageLimitOffset(pageNum) {\n pageNum = this.constrainPageNum(pageNum);\n return {\n limit: this.limitPerPage,\n offset: pageNum * this.limitPerPage\n };\n },\n\n constrainPageNum: function constrainPageNum(pageNum) {\n return Math.max(0, Math.min(pageNum, this.getLastPage()));\n },\n\n /** fetch the next page of data */\n fetchPage: function fetchPage(pageNum, options) {\n var self = this;\n pageNum = self.constrainPageNum(pageNum);\n self.currentPage = pageNum;\n options = _.defaults(options || {}, self.getPageLimitOffset(pageNum));\n\n self.trigger(\"fetching-more\");\n return self.fetch(options).always(function () {\n self.trigger(\"fetching-more-done\");\n });\n },\n\n fetchCurrentPage: function fetchCurrentPage(options) {\n return this.fetchPage(this.currentPage, options);\n },\n\n fetchPrevPage: function fetchPrevPage(options) {\n return this.fetchPage(this.currentPage - 1, options);\n },\n\n fetchNextPage: function fetchNextPage(options) {\n return this.fetchPage(this.currentPage + 1, options);\n }\n});\n\n//=============================================================================\n/**\n * A Collection that will load more elements without reseting.\n */\nvar InfinitelyScrollingCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: null,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 100,\n\n initialize: function initialize(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n /** @type {Integer} number of contents to return from the first fetch */\n this.limitOnFirstFetch = options.limitOnFirstFetch || this.limitOnFirstFetch;\n /** @type {Integer} limit for every fetch after the first */\n this.limitPerFetch = options.limitPerFetch || this.limitPerFetch;\n /** @type {Boolean} are all contents fetched? */\n this.allFetched = false;\n /** @type {Integer} what was the offset of the last content returned */\n this.lastFetched = options.lastFetched || 0;\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function _buildFetchOptions(options) {\n // options (options for backbone.fetch and jquery.ajax generally)\n // backbone option; false here to make fetching an addititive process\n options.remove = options.remove || false;\n return ControlledFetchCollection.prototype._buildFetchOptions.call(this, options);\n },\n\n /** fetch the first 'page' of data */\n fetchFirst: function fetchFirst(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchFirst:\", options);\n options = options ? _.clone(options) : {};\n this.allFetched = false;\n this.lastFetched = 0;\n return this.fetchMore(_.defaults(options, {\n reset: true,\n limit: this.limitOnFirstFetch\n }));\n },\n\n /** fetch the next page of data */\n fetchMore: function fetchMore(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchMore:\", options);\n options = _.clone(options || {});\n var collection = this;\n\n Galaxy.debug(\"fetchMore, options.reset:\", options.reset);\n if (!options.reset && collection.allFetched) {\n return jQuery.when();\n }\n\n // TODO: this fails in the edge case where\n // the first fetch offset === limit (limit 4, offset 4, collection.length 4)\n if (options.reset) {\n options.offset = 0;\n } else if (options.offset === undefined) {\n options.offset = collection.lastFetched;\n }\n var limit = options.limit = options.limit || collection.limitPerFetch || null;\n Galaxy.debug(\"fetchMore, limit:\", limit, \"offset:\", options.offset);\n\n collection.trigger(\"fetching-more\");\n return collection.fetch(options).always(function () {\n collection.trigger(\"fetching-more-done\");\n })\n // maintain allFetched flag and trigger if all were fetched this time\n .done(function _postFetchMore(fetchedData) {\n var numFetched = _.isArray(fetchedData) ? fetchedData.length : 0;\n collection.lastFetched += numFetched;\n Galaxy.debug(\"fetchMore, lastFetched:\", collection.lastFetched);\n // anything less than a full page means we got all there is to get\n if (!limit || numFetched < limit) {\n collection.allFetched = true;\n collection.trigger(\"all-fetched\", this);\n }\n });\n },\n\n /** fetch all the collection */\n fetchAll: function fetchAll(options) {\n // whitelist options to prevent allowing limit/offset/filters\n // (use vanilla fetch instead)\n options = options || {};\n var self = this;\n options = _.pick(options, \"silent\");\n options.filters = {};\n return self.fetch(options).done(function () {\n self.allFetched = true;\n self.trigger(\"all-fetched\", self);\n });\n }\n});\n\n//==============================================================================\nexports.default = {\n ControlledFetchCollection: ControlledFetchCollection,\n PaginatedCollection: PaginatedCollection,\n InfinitelyScrollingCollection: InfinitelyScrollingCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n\n/***/ }),\n/* 81 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _datasetModel = __webpack_require__(72);\n\nvar _datasetModel2 = _interopRequireDefault(_datasetModel);\n\nvar _historyContentModel = __webpack_require__(73);\n\nvar _historyContentModel2 = _interopRequireDefault(_historyContentModel);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _datasetModel2.default.DatasetAssociation;\n\nvar hcontentMixin = _historyContentModel2.default.HistoryContentMixin;\n/** @class (HDA) model for a Galaxy dataset contained in and related to a history.\n */\nvar HistoryDatasetAssociation = _super.extend(_baseMvc2.default.mixin(hcontentMixin,\n/** @lends HistoryDatasetAssociation.prototype */{\n /** default attributes for a model */\n defaults: _.extend({}, _super.prototype.defaults, hcontentMixin.defaults, {\n history_content_type: \"dataset\",\n model_class: \"HistoryDatasetAssociation\"\n })\n}));\n\n//==============================================================================\nexports.default = {\n HistoryDatasetAssociation: HistoryDatasetAssociation\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 82 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listItem = __webpack_require__(41);\n\nvar _listItem2 = _interopRequireDefault(_listItem);\n\nvar _loadingIndicator = __webpack_require__(155);\n\nvar _loadingIndicator2 = _interopRequireDefault(_loadingIndicator);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(83);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"list\";\n/* ============================================================================\nTODO:\n\n============================================================================ */\n/** @class View for a list/collection of models and the sub-views of those models.\n * Sub-views must (at least have the interface if not) inherit from ListItemView.\n * (For a list panel that also includes some 'container' model (History->HistoryContents)\n * use ModelWithListPanel)\n *\n * Allows for:\n * searching collection/sub-views\n * selecting/multi-selecting sub-views\n *\n * Currently used:\n * for dataset/dataset-choice\n * as superclass of ModelListPanel\n */\nvar ListPanel = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(\n/** @lends ListPanel.prototype */{\n _logNamespace: logNamespace,\n\n /** class to use for constructing the sub-views */\n viewClass: _listItem2.default.ListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: Backbone.Collection,\n\n tagName: \"div\",\n className: \"list-panel\",\n\n /** (in ms) that jquery effects will use */\n fxSpeed: \"fast\",\n\n /** string to display when the collection has no contents */\n emptyMsg: (0, _localization2.default)(\"This list is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: (0, _localization2.default)(\"No matching items found\"),\n /** string used for search placeholder */\n searchPlaceholder: (0, _localization2.default)(\"search\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the list\n */\n initialize: function initialize(attributes, options) {\n attributes = attributes || {};\n // set the logger if requested\n if (attributes.logger) {\n this.logger = attributes.logger;\n }\n this.log(this + \".initialize:\", attributes);\n\n // ---- instance vars\n /** how quickly should jquery fx run? */\n this.fxSpeed = _.has(attributes, \"fxSpeed\") ? attributes.fxSpeed : this.fxSpeed;\n\n /** filters for displaying subviews */\n this.filters = [];\n /** current search terms */\n this.searchFor = attributes.searchFor || \"\";\n\n /** loading indicator */\n // this.indicator = new LoadingIndicator( this.$el );\n\n /** currently showing selectors on items? */\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : true;\n //this.selecting = false;\n\n /** cached selected item.model.ids to persist btwn renders */\n this.selected = attributes.selected || [];\n /** the last selected item.model.id */\n this.lastSelected = null;\n\n /** are sub-views draggable */\n this.dragItems = attributes.dragItems || false;\n\n /** list item view class (when passed models) */\n this.viewClass = attributes.viewClass || this.viewClass;\n\n /** list item views */\n this.views = [];\n /** list item models */\n this.collection = attributes.collection || this._createDefaultCollection();\n\n /** filter fns run over collection items to see if they should show in the list */\n this.filters = attributes.filters || [];\n\n /** override $scrollContainer fn via attributes - fn should return jq for elem to call scrollTo on */\n this.$scrollContainer = attributes.$scrollContainer || this.$scrollContainer;\n\n /** @type {String} generic title */\n this.title = attributes.title || \"\";\n /** @type {String} generic subtitle */\n this.subtitle = attributes.subtitle || \"\";\n\n this._setUpListeners();\n },\n\n // ------------------------------------------------------------------------ listeners\n /** create any event listeners for the list */\n _setUpListeners: function _setUpListeners() {\n this.off();\n\n //TODO: move errorHandler down into list-view from history-view or\n // pass to global error handler (Galaxy)\n this.on({\n error: function error(model, xhr, options, msg, details) {\n //this.errorHandler( model, xhr, options, msg, details );\n console.error(model, xhr, options, msg, details);\n },\n // show hide the loading indicator\n loading: function loading() {\n this._showLoadingIndicator(\"loading...\", 40);\n },\n \"loading-done\": function loadingDone() {\n this._hideLoadingIndicator(40);\n }\n });\n\n // throw the first render up as a diff namespace using once (for outside consumption)\n this.once(\"rendered\", function () {\n this.trigger(\"rendered:initial\", this);\n });\n\n this._setUpCollectionListeners();\n this._setUpViewListeners();\n return this;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function _createDefaultCollection() {\n // override\n return new this.collectionClass([]);\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n this.log(this + \"._setUpCollectionListeners\", this.collection);\n this.stopListening(this.collection);\n\n // bubble up error events\n this.listenTo(this.collection, {\n error: function error(model, xhr, options, msg, details) {\n this.trigger(\"error\", model, xhr, options, msg, details);\n },\n update: function update(collection, options) {\n var changes = options.changes;\n // console.info( collection + ', update:', changes, '\\noptions:', options );\n // more than one: render everything\n if (options.renderAll || changes.added.length + changes.removed.length > 1) {\n return this.renderItems();\n }\n // otherwise, let the single add/remove handlers do it\n if (changes.added.length === 1) {\n return this.addItemView(_.first(changes.added), collection, options);\n }\n if (changes.removed.length === 1) {\n return this.removeItemView(_.first(changes.removed), collection, options);\n }\n }\n });\n return this;\n },\n\n /** listening for sub-view events that bubble up with the 'view:' prefix */\n _setUpViewListeners: function _setUpViewListeners() {\n this.log(this + \"._setUpViewListeners\");\n\n // shift to select a range\n this.on({\n \"view:selected\": function viewSelected(view, ev) {\n if (ev && ev.shiftKey && this.lastSelected) {\n var lastSelectedView = this.viewFromModelId(this.lastSelected);\n if (lastSelectedView) {\n this.selectRange(view, lastSelectedView);\n }\n } else if (ev && ev.altKey && !this.selecting) {\n this.showSelectors();\n }\n this.selected.push(view.model.id);\n this.lastSelected = view.model.id;\n },\n\n \"view:de-selected\": function viewDeSelected(view, ev) {\n this.selected = _.without(this.selected, view.model.id);\n }\n });\n },\n\n // ------------------------------------------------------------------------ rendering\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function render(speed) {\n this.log(this + \".render\", speed);\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _buildNewRender: function _buildNewRender() {\n this.debug(this + \"(ListPanel)._buildNewRender\");\n var $newRender = $(this.templates.el({}, this));\n this._renderControls($newRender);\n this._renderTitle($newRender);\n this._renderSubtitle($newRender);\n this._renderSearch($newRender);\n this.renderItems($newRender);\n return $newRender;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _renderControls: function _renderControls($newRender) {\n this.debug(this + \"(ListPanel)._renderControls\");\n var $controls = $(this.templates.controls({}, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n /** return a jQuery object containing the title DOM */\n _renderTitle: function _renderTitle($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** return a jQuery object containing the subtitle DOM (if any) */\n _renderSubtitle: function _renderSubtitle($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function _queueNewRender($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n $(panel).queue(\"fx\", [function (next) {\n panel.$el.fadeOut(speed, next);\n }, function (next) {\n panel._swapNewRender($newRender);\n next();\n }, function (next) {\n panel.$el.fadeIn(speed, next);\n }, function (next) {\n panel.trigger(\"rendered\", panel);\n next();\n }]);\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function _swapNewRender($newRender) {\n this.$el.empty().attr(\"class\", this.className).append($newRender.children());\n if (this.selecting) {\n this.showSelectors(0);\n }\n return this;\n },\n\n /** Set up any behaviors, handlers (ep. plugins) that need to be called when the entire view has been built but\n * not attached to the page yet.\n */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n this.$controls($where).find(\"[title]\").tooltip();\n // set up the pupup for actions available when multi selecting\n this._renderMultiselectActionMenu($where);\n return this;\n },\n\n /** render a menu containing the actions available to sets of selected items */\n _renderMultiselectActionMenu: function _renderMultiselectActionMenu($where) {\n $where = $where || this.$el;\n var $menu = $where.find(\".list-action-menu\");\n var actions = this.multiselectActions();\n if (!actions.length) {\n return $menu.empty();\n }\n\n var $newMenu = $(['
', '\", '
', \"
\", \"
\"].join(\"\"));\n var $actions = actions.map(function (action) {\n var html = ['
\"].join(\"\");\n return $(html).click(function (ev) {\n ev.preventDefault();\n return action.func(ev);\n });\n });\n $newMenu.find(\"ul\").append($actions);\n $menu.replaceWith($newMenu);\n return $newMenu;\n },\n\n /** return a list of plain objects used to render multiselect actions menu. Each object should have:\n * html: an html string used as the anchor contents\n * func: a function called when the anchor is clicked (passed the click event)\n */\n multiselectActions: function multiselectActions() {\n return [];\n },\n\n // ------------------------------------------------------------------------ sub-$element shortcuts\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function $scrollContainer($where) {\n // override or set via attributes.$scrollContainer\n return ($where || this.$el).parent().parent();\n },\n /** convenience selector for the section that displays the list controls */\n $controls: function $controls($where) {\n return ($where || this.$el).find(\"> .controls\");\n },\n /** list-items: where the subviews are contained in the view's dom */\n $list: function $list($where) {\n return ($where || this.$el).find(\"> .list-items\");\n },\n /** container where list messages are attached */\n $messages: function $messages($where) {\n //TODO: controls isn't really correct here (only for ModelListPanel)\n return ($where || this.$el).find(\"> .controls .messages\");\n },\n /** the message displayed when no views can be shown (no views, none matching search) */\n $emptyMessage: function $emptyMessage($where) {\n return ($where || this.$el).find(\"> .empty-message\");\n },\n\n // ------------------------------------------------------------------------ hda sub-views\n /** render the subviews for the list's collection */\n renderItems: function renderItems($whereTo) {\n $whereTo = $whereTo || this.$el;\n var panel = this;\n panel.log(this + \".renderItems\", $whereTo);\n\n var $list = panel.$list($whereTo);\n panel.freeViews();\n // console.log( 'views freed' );\n //TODO:? cache and re-use views?\n var shownModels = panel._filterCollection();\n // console.log( 'models filtered:', shownModels );\n\n panel.views = shownModels.map(function (itemModel) {\n var view = panel._createItemView(itemModel);\n return view;\n });\n\n $list.empty();\n // console.log( 'list emptied' );\n if (panel.views.length) {\n panel._attachItems($whereTo);\n // console.log( 'items attached' );\n }\n panel._renderEmptyMessage($whereTo).toggle(!panel.views.length);\n panel.trigger(\"views:ready\", panel.views);\n\n // console.log( '------------------------------------------- rendering items' );\n return panel.views;\n },\n\n /** Filter the collection to only those models that should be currently viewed */\n _filterCollection: function _filterCollection() {\n // override this\n var panel = this;\n return panel.collection.filter(_.bind(panel._filterItem, panel));\n },\n\n /** Should the model be viewable in the current state?\n * Checks against this.filters and this.searchFor\n */\n _filterItem: function _filterItem(model) {\n // override this\n var panel = this;\n return _.every(panel.filters.map(function (fn) {\n return fn.call(model);\n })) && (!panel.searchFor || model.matchesAll(panel.searchFor));\n },\n\n /** Create a view for a model and set up it's listeners */\n _createItemView: function _createItemView(model) {\n var ViewClass = this._getItemViewClass(model);\n var options = _.extend(this._getItemViewOptions(model), {\n model: model\n });\n var view = new ViewClass(options);\n this._setUpItemViewListeners(view);\n return view;\n },\n\n /** Free a view for a model. Note: does not remove it from the DOM */\n _destroyItemView: function _destroyItemView(view) {\n this.stopListening(view);\n this.views = _.without(this.views, view);\n },\n\n _destroyItemViews: function _destroyItemViews(view) {\n var self = this;\n self.views.forEach(function (v) {\n self.stopListening(v);\n });\n self.views = [];\n return self;\n },\n\n /** free any sub-views the list has */\n freeViews: function freeViews() {\n return this._destroyItemViews();\n },\n\n /** Get the bbone view class based on the model */\n _getItemViewClass: function _getItemViewClass(model) {\n // override this\n return this.viewClass;\n },\n\n /** Get the options passed to the new view based on the model */\n _getItemViewOptions: function _getItemViewOptions(model) {\n // override this\n return {\n //logger : this.logger,\n fxSpeed: this.fxSpeed,\n expanded: false,\n selectable: this.selecting,\n selected: _.contains(this.selected, model.id),\n draggable: this.dragItems\n };\n },\n\n /** Set up listeners for new models */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n // send all events to the panel, re-namspaceing them with the view prefix\n this.listenTo(view, \"all\", function () {\n var args = Array.prototype.slice.call(arguments, 0);\n args[0] = \"view:\" + args[0];\n panel.trigger.apply(panel, args);\n });\n\n // drag multiple - hijack ev.setData to add all selected items\n this.listenTo(view, \"draggable:dragstart\", function (ev, v) {\n //TODO: set multiple drag data here\n var json = {};\n\n var selected = this.getSelectedModels();\n if (selected.length) {\n json = selected.toJSON();\n } else {\n json = [v.model.toJSON()];\n }\n ev.dataTransfer.setData(\"text\", JSON.stringify(json));\n //ev.dataTransfer.setDragImage( v.el, 60, 60 );\n }, this);\n\n return panel;\n },\n\n /** Attach views in this.views to the model based on $whereTo */\n _attachItems: function _attachItems($whereTo) {\n var self = this;\n // console.log( '_attachItems:', $whereTo, this.$list( $whereTo ) );\n //ASSUMES: $list has been emptied\n this.$list($whereTo).append(this.views.map(function (view) {\n return self._renderItemView$el(view);\n }));\n return this;\n },\n\n /** get a given subview's $el (or whatever may wrap it) and return it */\n _renderItemView$el: function _renderItemView$el(view) {\n // useful to wrap and override\n return view.render(0).$el;\n },\n\n /** render the empty/none-found message */\n _renderEmptyMessage: function _renderEmptyMessage($whereTo) {\n this.debug(\"_renderEmptyMessage\", $whereTo, this.searchFor);\n var text = this.searchFor ? this.noneFoundMsg : this.emptyMsg;\n return this.$emptyMessage($whereTo).text(text);\n },\n\n /** expand all item views */\n expandAll: function expandAll() {\n _.each(this.views, function (view) {\n view.expand();\n });\n },\n\n /** collapse all item views */\n collapseAll: function collapseAll() {\n _.each(this.views, function (view) {\n view.collapse();\n });\n },\n\n // ------------------------------------------------------------------------ collection/views syncing\n /** Add a view (if the model should be viewable) to the panel */\n addItemView: function addItemView(model, collection, options) {\n // console.log( this + '.addItemView:', model );\n var panel = this;\n // get the index of the model in the list of filtered models shown by this list\n // in order to insert the view in the proper place\n //TODO:? potentially expensive\n var modelIndex = panel._filterCollection().indexOf(model);\n if (modelIndex === -1) {\n return undefined;\n }\n var view = panel._createItemView(model);\n // console.log( 'adding and rendering:', modelIndex, view.toString() );\n\n $(view).queue(\"fx\", [function (next) {\n // hide the empty message first if only view\n if (panel.$emptyMessage().is(\":visible\")) {\n panel.$emptyMessage().fadeOut(panel.fxSpeed, next);\n } else {\n next();\n }\n }, function (next) {\n panel._attachView(view, modelIndex);\n next();\n }]);\n return view;\n },\n\n /** internal fn to add view (to both panel.views and panel.$list) */\n _attachView: function _attachView(view, modelIndex, useFx) {\n // console.log( this + '._attachView:', view, modelIndex, useFx );\n useFx = _.isUndefined(useFx) ? true : useFx;\n modelIndex = modelIndex || 0;\n var panel = this;\n\n // use the modelIndex to splice into views and insert at the proper index in the DOM\n panel.views.splice(modelIndex, 0, view);\n panel._insertIntoListAt(modelIndex, panel._renderItemView$el(view).hide());\n\n panel.trigger(\"view:attached\", view);\n if (useFx) {\n view.$el.slideDown(panel.fxSpeed, function () {\n panel.trigger(\"view:attached:rendered\");\n });\n } else {\n view.$el.show();\n panel.trigger(\"view:attached:rendered\");\n }\n return view;\n },\n\n /** insert a jq object as a child of list-items at the specified *DOM index* */\n _insertIntoListAt: function _insertIntoListAt(index, $what) {\n // console.log( this + '._insertIntoListAt:', index, $what );\n var $list = this.$list();\n if (index === 0) {\n $list.prepend($what);\n } else {\n $list.children().eq(index - 1).after($what);\n }\n return $what;\n },\n\n /** Remove a view from the panel (if found) */\n removeItemView: function removeItemView(model, collection, options) {\n var panel = this;\n var view = _.find(panel.views, function (v) {\n return v.model === model;\n });\n if (!view) {\n return undefined;\n }\n panel.views = _.without(panel.views, view);\n panel.trigger(\"view:removed\", view);\n\n // potentially show the empty message if no views left\n // use anonymous queue here - since remove can happen multiple times\n $({}).queue(\"fx\", [function (next) {\n view.$el.fadeOut(panel.fxSpeed, next);\n }, function (next) {\n view.remove();\n panel.trigger(\"view:removed:rendered\");\n if (!panel.views.length) {\n panel._renderEmptyMessage().fadeIn(panel.fxSpeed, next);\n } else {\n next();\n }\n }]);\n return view;\n },\n\n /** get views based on model.id */\n viewFromModelId: function viewFromModelId(id) {\n return _.find(this.views, function (v) {\n return v.model.id === id;\n });\n },\n\n /** get views based on model */\n viewFromModel: function viewFromModel(model) {\n return model ? this.viewFromModelId(model.id) : undefined;\n },\n\n /** get views based on model properties */\n viewsWhereModel: function viewsWhereModel(properties) {\n return this.views.filter(function (view) {\n return _.isMatch(view.model.attributes, properties);\n });\n },\n\n /** A range of views between (and including) viewA and viewB */\n viewRange: function viewRange(viewA, viewB) {\n if (viewA === viewB) {\n return viewA ? [viewA] : [];\n }\n\n var indexA = this.views.indexOf(viewA);\n var indexB = this.views.indexOf(viewB);\n\n // handle not found\n if (indexA === -1 || indexB === -1) {\n if (indexA === indexB) {\n return [];\n }\n return indexA === -1 ? [viewB] : [viewA];\n }\n // reverse if indeces are\n //note: end inclusive\n return indexA < indexB ? this.views.slice(indexA, indexB + 1) : this.views.slice(indexB, indexA + 1);\n },\n\n // ------------------------------------------------------------------------ searching\n /** render a search input for filtering datasets shown\n * (see SearchableMixin in base-mvc for implementation of the actual searching)\n * return will start the search\n * esc will clear the search\n * clicking the clear button will clear the search\n * uses searchInput in ui.js\n */\n _renderSearch: function _renderSearch($where) {\n $where.find(\".controls .search-input\").searchInput({\n placeholder: this.searchPlaceholder,\n initialVal: this.searchFor,\n onfirstsearch: _.bind(this._firstSearch, this),\n onsearch: _.bind(this.searchItems, this),\n onclear: _.bind(this.clearSearch, this)\n });\n return $where;\n },\n\n /** What to do on the first search entered */\n _firstSearch: function _firstSearch(searchFor) {\n // override to load model details if necc.\n this.log(\"onFirstSearch\", searchFor);\n return this.searchItems(searchFor);\n },\n\n /** filter view list to those that contain the searchFor terms */\n searchItems: function searchItems(searchFor, force) {\n this.log(\"searchItems\", searchFor, this.searchFor, force);\n if (!force && this.searchFor === searchFor) {\n return this;\n }\n this.searchFor = searchFor;\n this.renderItems();\n this.trigger(\"search:searching\", searchFor, this);\n var $search = this.$(\"> .controls .search-query\");\n if ($search.val() !== searchFor) {\n $search.val(searchFor);\n }\n return this;\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function clearSearch(searchFor) {\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n this.renderItems();\n return this;\n },\n\n // ------------------------------------------------------------------------ selection\n /** @type Integer when the number of list item views is >= to this, don't animate selectors */\n THROTTLE_SELECTOR_FX_AT: 20,\n\n /** show selectors on all visible itemViews and associated controls */\n showSelectors: function showSelectors(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = true;\n this.$(\".list-actions\").slideDown(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, function (view) {\n view.showSelector(speed);\n });\n //this.selected = [];\n //this.lastSelected = null;\n },\n\n /** hide selectors on all visible itemViews and associated controls */\n hideSelectors: function hideSelectors(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = false;\n this.$(\".list-actions\").slideUp(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, function (view) {\n view.hideSelector(speed);\n });\n this.selected = [];\n this.lastSelected = null;\n },\n\n /** show or hide selectors on all visible itemViews and associated controls */\n toggleSelectors: function toggleSelectors() {\n if (!this.selecting) {\n this.showSelectors();\n } else {\n this.hideSelectors();\n }\n },\n\n /** select all visible items */\n selectAll: function selectAll(event) {\n _.each(this.views, function (view) {\n view.select(event);\n });\n },\n\n /** deselect all visible items */\n deselectAll: function deselectAll(event) {\n this.lastSelected = null;\n _.each(this.views, function (view) {\n view.deselect(event);\n });\n },\n\n /** select a range of datasets between A and B */\n selectRange: function selectRange(viewA, viewB) {\n var range = this.viewRange(viewA, viewB);\n _.each(range, function (view) {\n view.select();\n });\n return range;\n },\n\n /** return an array of all currently selected itemViews */\n getSelectedViews: function getSelectedViews() {\n return _.filter(this.views, function (v) {\n return v.selected;\n });\n },\n\n /** return a collection of the models of all currenly selected items */\n getSelectedModels: function getSelectedModels() {\n // console.log( '(getSelectedModels)' );\n return new this.collection.constructor(_.map(this.getSelectedViews(), function (view) {\n return view.model;\n }));\n },\n\n // ------------------------------------------------------------------------ loading indicator\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function _showLoadingIndicator(msg, speed, callback) {\n this.debug(\"_showLoadingIndicator\", this.indicator, msg, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (!this.indicator) {\n this.indicator = new _loadingIndicator2.default(this.$el);\n this.debug(\"\\t created\", this.indicator);\n }\n if (!this.$el.is(\":visible\")) {\n this.indicator.show(0, callback);\n } else {\n this.$el.fadeOut(speed);\n this.indicator.show(msg, speed, callback);\n }\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function _hideLoadingIndicator(speed, callback) {\n this.debug(\"_hideLoadingIndicator\", this.indicator, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (this.indicator) {\n this.indicator.hide(speed, callback);\n }\n },\n\n // ------------------------------------------------------------------------ scrolling\n /** get the current scroll position of the panel in its parent */\n scrollPosition: function scrollPosition() {\n return this.$scrollContainer().scrollTop();\n },\n\n /** set the current scroll position of the panel in its parent */\n scrollTo: function scrollTo(pos, speed) {\n speed = speed || 0;\n this.$scrollContainer().animate({ scrollTop: pos }, speed);\n return this;\n },\n\n /** Scrolls the panel to the top. */\n scrollToTop: function scrollToTop(speed) {\n return this.scrollTo(0, speed);\n },\n\n /** scroll to the given view in list-items */\n scrollToItem: function scrollToItem(view, speed) {\n if (!view) {\n return this;\n }\n return this;\n },\n\n /** Scrolls the panel to show the content with the given id. */\n scrollToId: function scrollToId(id, speed) {\n return this.scrollToItem(this.viewFromModelId(id), speed);\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .select-all\": \"selectAll\",\n \"click .deselect-all\": \"deselectAll\"\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function toString() {\n return \"ListPanel(\" + this.collection + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListPanel.prototype.templates = function () {\n var elTemplate = _baseMvc2.default.wrapTemplate([\n // temp container\n \"
\", '', '', '', \"
\"]);\n\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
\"]);\n\n return {\n el: elTemplate,\n controls: controlsTemplate\n };\n}();\n\n//=============================================================================\n/** View for a model that has a sub-collection (e.g. History, DatasetCollection)\n * Allows:\n * the model to be reset\n * auto assign panel.collection to panel.model[ panel.modelCollectionKey ]\n *\n */\nvar ModelListPanel = ListPanel.extend({\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n initialize: function initialize(attributes) {\n ListPanel.prototype.initialize.call(this, attributes);\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : false;\n\n this.setModel(this.model, attributes);\n },\n\n /** release/free/shutdown old models and set up panel for new models\n * @fires new-model with the panel as parameter\n */\n setModel: function setModel(model, attributes) {\n attributes = attributes || {};\n this.debug(this + \".setModel:\", model, attributes);\n\n this.freeModel();\n this.freeViews();\n\n if (model) {\n var oldModelId = this.model ? this.model.get(\"id\") : null;\n\n // set up the new model with user, logger, storage, events\n this.model = model;\n if (this.logger) {\n this.model.logger = this.logger;\n }\n this._setUpModelListeners();\n\n //TODO: relation btwn model, collection becoming tangled here\n // free the collection, and assign the new collection to either\n // the model[ modelCollectionKey ], attributes.collection, or an empty vanilla collection\n this.stopListening(this.collection);\n this.collection = this.model[this.modelCollectionKey] || attributes.collection || this._createDefaultCollection();\n this._setUpCollectionListeners();\n\n if (oldModelId && model.get(\"id\") !== oldModelId) {\n this.trigger(\"new-model\", this);\n }\n }\n return this;\n },\n\n /** free the current model and all listeners for it, free any views for the model */\n freeModel: function freeModel() {\n // stop/release the previous model, and clear cache to sub-views\n if (this.model) {\n this.stopListening(this.model);\n //TODO: see base-mvc\n //this.model.free();\n //this.model = null;\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ listening\n /** listening for model events */\n _setUpModelListeners: function _setUpModelListeners() {\n // override\n this.log(this + \"._setUpModelListeners\", this.model);\n // bounce model errors up to the panel\n this.listenTo(this.model, \"error\", function () {\n var args = Array.prototype.slice.call(arguments, 0);\n //args.unshift( 'model:error' );\n args.unshift(\"error\");\n this.trigger.apply(this, args);\n }, this);\n\n // debugging\n if (this.logger) {\n this.listenTo(this.model, \"all\", function (event) {\n this.info(this + \"(model)\", event, arguments);\n });\n }\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n */\n _renderControls: function _renderControls($newRender) {\n this.debug(this + \"(ModelListPanel)._renderControls\");\n var json = this.model ? this.model.toJSON() : {};\n var $controls = $(this.templates.controls(json, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function toString() {\n return \"ModelListPanel(\" + this.model + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nModelListPanel.prototype.templates = function () {\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
', '
',\n //TODO: this is really the only difference - consider factoring titlebar out\n '
<%- model.name %>
', \"
\", '
<%- view.subtitle %>
', '', '', '
', '', \"
\", '
', '
', '\", '\", \"
\", '
', \"
\", \"
\", \"
\"]);\n\n return _.extend(_.clone(ListPanel.prototype.templates), {\n controls: controlsTemplate\n });\n}();\n\n//=============================================================================\nexports.default = {\n ListPanel: ListPanel,\n ModelListPanel: ModelListPanel\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 83 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n\"use_strict\";\n\nvar $ = _jquery2.default;\nvar _l = window._l || function (s) {\n return s;\n};\n\n//TODO: consolidate with tool menu functionality, use there\n\n/** searchInput: (jQuery plugin)\n * Creates a search input, a clear button, and loading indicator\n * within the selected node.\n *\n * When the user either presses return or enters some minimal number\n * of characters, a callback is called. Pressing ESC when the input\n * is focused will clear the input and call a separate callback.\n */\nfunction searchInput(parentNode, options) {\n var KEYCODE_ESC = 27;\n var KEYCODE_RETURN = 13;\n var $parentNode = $(parentNode);\n var firstSearch = true;\n\n var defaults = {\n initialVal: \"\",\n name: \"search\",\n placeholder: \"search\",\n classes: \"\",\n onclear: function onclear() {},\n onfirstsearch: null,\n onsearch: function onsearch(inputVal) {},\n minSearchLen: 0,\n escWillClear: true,\n oninit: function oninit() {}\n };\n\n // .................................................................... input rendering and events\n // visually clear the search, trigger an event, and call the callback\n function clearSearchInput(event) {\n var $input = $(this).parent().children(\"input\");\n $input.val(\"\").trigger(\"searchInput.clear\").blur();\n options.onclear();\n }\n\n // search for searchTerms, trigger an event, call the appropo callback (based on whether this is the first)\n function search(event, searchTerms) {\n if (!searchTerms) {\n return clearSearchInput();\n }\n $(this).trigger(\"search.search\", searchTerms);\n if (typeof options.onfirstsearch === \"function\" && firstSearch) {\n firstSearch = false;\n options.onfirstsearch(searchTerms);\n } else {\n options.onsearch(searchTerms);\n }\n }\n\n // .................................................................... input rendering and events\n function inputTemplate() {\n // class search-query is bootstrap 2.3 style that now lives in base.less\n return ['\"].join(\"\");\n }\n\n // the search input that responds to keyboard events and displays the search value\n function $input() {\n return $(inputTemplate())\n // select all text on a focus\n .focus(function (event) {\n $(this).select();\n })\n // attach behaviors to esc, return if desired, search on some min len string\n .keyup(function (event) {\n event.preventDefault();\n event.stopPropagation();\n\n // esc key will clear if desired\n if (event.which === KEYCODE_ESC && options.escWillClear) {\n clearSearchInput.call(this, event);\n } else {\n var searchTerms = $(this).val();\n // return key or the search string len > minSearchLen (if not 0) triggers search\n if (event.which === KEYCODE_RETURN || options.minSearchLen && searchTerms.length >= options.minSearchLen) {\n search.call(this, event, searchTerms);\n }\n }\n }).val(options.initialVal);\n }\n\n // .................................................................... clear button rendering and events\n // a button for clearing the search bar, placed on the right hand side\n function $clearBtn() {\n return $([''].join(\"\")).tooltip({ placement: \"bottom\" }).click(function (event) {\n clearSearchInput.call(this, event);\n });\n }\n\n // .................................................................... loadingIndicator rendering\n // a button for clearing the search bar, placed on the right hand side\n function $loadingIndicator() {\n return $([''].join(\"\")).hide().tooltip({ placement: \"bottom\" });\n }\n\n // .................................................................... commands\n // visually swap the load, clear buttons\n function toggleLoadingIndicator() {\n $parentNode.find(\".search-loading\").toggle();\n $parentNode.find(\".search-clear\").toggle();\n }\n\n // .................................................................... init\n // string command (not constructor)\n if (_jquery2.default.type(options) === \"string\") {\n if (options === \"toggle-loading\") {\n toggleLoadingIndicator();\n }\n return $parentNode;\n }\n\n // initial render\n if (_jquery2.default.type(options) === \"object\") {\n options = _jquery2.default.extend(true, {}, defaults, options);\n }\n //NOTE: prepended\n return $parentNode.addClass(\"search-input\").prepend([$input(), $clearBtn(), $loadingIndicator()]);\n}\n\n// as jq plugin\n_jquery2.default.fn.extend({\n searchInput: function $searchInput(options) {\n return this.each(function () {\n return searchInput(this, options);\n });\n }\n});\n\n/***/ }),\n/* 84 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _datasetLi = __webpack_require__(42);\n\nvar _datasetLi2 = _interopRequireDefault(_datasetLi);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _datasetLi2.default.DatasetListItemView;\n/** @class Read only view for HistoryDatasetAssociation.\n * Since there are no controls on the HDAView to hide the dataset,\n * the primary thing this class does (currently) is override templates\n * to render the HID.\n */\nvar HDAListItemView = _super.extend(\n/** @lends HDAListItemView.prototype */{\n className: _super.prototype.className + \" history-content\",\n\n initialize: function initialize(attributes, options) {\n _super.prototype.initialize.call(this, attributes, options);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"HDAListItemView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nHDAListItemView.prototype.templates = function () {\n var titleBarTemplate = _baseMvc2.default.wrapTemplate([\n // adding the hid display to the title\n '
', '', '
',\n //TODO: remove whitespace and use margin-right\n '<%- dataset.hid %> ', '<%- dataset.name %>', \"
\"], \"dataset\");\n\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: _baseMvc2.default.wrapTemplate([\n // add a warning when hidden\n \"<% if( !dataset.visible ){ %>\", '
', (0, _localization2.default)(\"This dataset has been hidden\"), \"
\", \"<% } %>\"], \"dataset\")\n });\n\n return _.extend({}, _super.prototype.templates, {\n titleBar: titleBarTemplate,\n warnings: warnings\n });\n}();\n\n//==============================================================================\nexports.default = {\n HDAListItemView: HDAListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 85 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _collectionLi = __webpack_require__(43);\n\nvar _collectionLi2 = _interopRequireDefault(_collectionLi);\n\nvar _collectionView = __webpack_require__(86);\n\nvar _collectionView2 = _interopRequireDefault(_collectionView);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _collectionLi2.default.DCListItemView;\n/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).\n */\nvar HDCAListItemView = _super.extend(\n/** @lends HDCAListItemView.prototype */{\n className: _super.prototype.className + \" history-content\",\n\n /** event listeners */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n this.listenTo(this.model, {\n \"change:tags change:populated change:visible\": function changeTagsChangePopulatedChangeVisible(model, options) {\n this.render();\n }\n });\n },\n\n /** Override to provide the proper collections panels as the foldout */\n _getFoldoutPanelClass: function _getFoldoutPanelClass() {\n switch (this.model.get(\"collection_type\")) {\n case \"list\":\n return _collectionView2.default.ListCollectionView;\n case \"paired\":\n return _collectionView2.default.PairCollectionView;\n case \"list:paired\":\n return _collectionView2.default.ListOfPairsCollectionView;\n case \"list:list\":\n return _collectionView2.default.ListOfListsCollectionView;\n }\n throw new TypeError(\"Uknown collection_type: \" + this.model.get(\"collection_type\"));\n },\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function _swapNewRender($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n //TODO: model currently has no state\n var state = !this.model.get(\"populated\") ? _states2.default.RUNNING : _states2.default.OK;\n //if( this.model.has( 'state' ) ){\n this.$el.addClass(\"state-\" + state);\n //}\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"HDCAListItemView(\" + modelString + \")\";\n }\n});\n\n/** underscore templates */\nHDCAListItemView.prototype.templates = function () {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: _baseMvc2.default.wrapTemplate([\n // add a warning when hidden\n \"<% if( !collection.visible ){ %>\", '
', (0, _localization2.default)(\"This collection has been hidden\"), \"
\", \"<% } %>\"], \"collection\")\n });\n\n // could steal this from hda-base (or use mixed content)\n var titleBarTemplate = _baseMvc2.default.wrapTemplate([\n // adding the hid display to the title\n '
', '', '
',\n //TODO: remove whitespace and use margin-right\n '<%- collection.hid %> ', '<%- collection.name %>', \"
\"], \"collection\");\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n HDCAListItemView: HDCAListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 86 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listView = __webpack_require__(82);\n\nvar _listView2 = _interopRequireDefault(_listView);\n\nvar _collectionModel = __webpack_require__(37);\n\nvar _collectionModel2 = _interopRequireDefault(_collectionModel);\n\nvar _collectionLi = __webpack_require__(43);\n\nvar _collectionLi2 = _interopRequireDefault(_collectionLi);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"collections\";\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a dataset collection.\n */\nvar _super = _listView2.default.ModelListPanel;\nvar CollectionView = _super.extend(\n/** @lends CollectionView.prototype */{\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n _logNamespace: logNamespace,\n\n className: _super.prototype.className + \" dataset-collection-panel\",\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: _collectionLi2.default.DatasetDCEListItemView,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: _collectionLi2.default.NestedDCDCEListItemView,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"elements\",\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function initialize(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n this.hasUser = attributes.hasUser;\n /** A stack of panels that currently cover or hide this panel */\n this.panelStack = [];\n /** The text of the link to go back to the panel containing this one */\n this.parentName = attributes.parentName;\n /** foldout or drilldown */\n this.foldoutStyle = attributes.foldoutStyle || \"foldout\";\n this.downloadUrl = Galaxy.root + \"api/dataset_collections/\" + this.model.attributes.id + \"/download\";\n console.log(this);\n },\n\n _queueNewRender: function _queueNewRender($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n // TODO: jquery@1.12 doesn't change display when the elem has display: flex\n // this causes display: block for those elems after the use of show/hide animations\n // animations are removed from this view for now until fixed\n panel._swapNewRender($newRender);\n panel.trigger(\"rendered\", panel);\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, use model.getVisibleContents */\n _filterCollection: function _filterCollection() {\n //TODO: should *not* be model.getVisibleContents - visibility is not model related\n return this.model.getVisibleContents();\n },\n\n /** override to return proper view class based on element_type */\n _getItemViewClass: function _getItemViewClass(model) {\n //this.debug( this + '._getItemViewClass:', model );\n //TODO: subclasses use DCEViewClass - but are currently unused - decide\n switch (model.get(\"element_type\")) {\n case \"hda\":\n return this.DatasetDCEViewClass;\n case \"dataset_collection\":\n return this.NestedDCDCEViewClass;\n }\n throw new TypeError(\"Unknown element type:\", model.get(\"element_type\"));\n },\n\n /** override to add link target and anon */\n _getItemViewOptions: function _getItemViewOptions(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n hasUser: this.hasUser,\n //TODO: could move to only nested: list:paired\n foldoutStyle: this.foldoutStyle\n });\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n\n // use pub-sub to: handle drilldown expansion and collapse\n panel.listenTo(view, {\n \"expanded:drilldown\": function expandedDrilldown(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function collapsedDrilldown(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n return this;\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function _expandDrilldownPanel(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$(\"> .controls\").add(this.$list()).hide();\n drilldown.parentName = this.model.get(\"name\");\n this.$el.append(drilldown.render().$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function _collapseDrilldownPanel(drilldown) {\n this.panelStack.pop();\n this.render();\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .navigation .back\": \"close\"\n },\n\n /** close/remove this collection panel */\n close: function close(event) {\n this.remove();\n this.trigger(\"close\");\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"CollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nCollectionView.prototype.templates = function () {\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
\"], \"collection\");\n\n return _.extend(_.clone(_super.prototype.templates), {\n controls: controlsTemplate\n });\n}();\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionView = CollectionView.extend(\n/** @lends ListCollectionView.prototype */{\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: _collectionLi2.default.DatasetDCEListItemView,\n\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"ListCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionView = ListCollectionView.extend(\n/** @lends PairCollectionView.prototype */{\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"PairCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListOfPairsCollectionView = CollectionView.extend(\n/** @lends ListOfPairsCollectionView.prototype */{\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: _collectionLi2.default.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"ListOfPairsCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionView = CollectionView.extend({\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: _collectionLi2.default.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n /** string rep */\n toString: function toString() {\n return \"ListOfListsCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n CollectionView: CollectionView,\n ListCollectionView: ListCollectionView,\n PairCollectionView: PairCollectionView,\n ListOfPairsCollectionView: ListOfPairsCollectionView,\n ListOfListsCollectionView: ListOfListsCollectionView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 87 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _datasetLi = __webpack_require__(42);\n\nvar _datasetLi2 = _interopRequireDefault(_datasetLi);\n\nvar _tag = __webpack_require__(22);\n\nvar _tag2 = _interopRequireDefault(_tag);\n\nvar _annotation = __webpack_require__(88);\n\nvar _annotation2 = _interopRequireDefault(_annotation);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _datasetLi2.default.DatasetListItemView;\n/** @class Editing view for DatasetAssociation.\n */\nvar DatasetListItemEdit = _super.extend(\n/** @lends DatasetListItemEdit.prototype */{\n /** set up: options */\n initialize: function initialize(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.hasUser = attributes.hasUser;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n //TODO: move to HiddenUntilActivatedViewMixin\n /** should the tags editor be shown or hidden initially? */\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n /** should the tags editor be shown or hidden initially? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n },\n\n // ......................................................................... titlebar actions\n /** In this override, add the other two primary actions: edit and delete */\n _renderPrimaryActions: function _renderPrimaryActions() {\n var actions = _super.prototype._renderPrimaryActions.call(this);\n if (this.model.get(\"state\") === _states2.default.NOT_VIEWABLE) {\n return actions;\n }\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions.call(this).concat([this._renderEditButton(), this._renderDeleteButton()]);\n },\n\n //TODO: move titleButtons into state renderers, remove state checks in the buttons\n\n /** Render icon-button to edit the attributes (format, permissions, etc.) this dataset. */\n _renderEditButton: function _renderEditButton() {\n var self = this;\n // don't show edit while uploading, in-accessible\n // DO show if in error (ala previous history panel)\n if (this.model.get(\"state\") === _states2.default.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n var purged = this.model.get(\"purged\");\n var deleted = this.model.get(\"deleted\");\n\n var editBtnData = {\n title: (0, _localization2.default)(\"Edit attributes\"),\n href: Galaxy.root + \"datasets/edit?dataset_id=\" + this.model.attributes.id,\n faIcon: \"fa-pencil\",\n classes: \"edit-btn\",\n onclick: function onclick(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/edit\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n };\n\n // disable if purged or deleted and explain why in the tooltip\n if (deleted || purged) {\n editBtnData.disabled = true;\n if (purged) {\n editBtnData.title = (0, _localization2.default)(\"Cannot edit attributes of datasets removed from disk\");\n } else if (deleted) {\n editBtnData.title = (0, _localization2.default)(\"Undelete dataset to edit attributes\");\n }\n\n // disable if still uploading or new\n } else if (_.contains([_states2.default.UPLOAD, _states2.default.NEW], this.model.get(\"state\"))) {\n editBtnData.disabled = true;\n editBtnData.title = (0, _localization2.default)(\"This dataset is not yet editable\");\n }\n return (0, _faIconButton2.default)(editBtnData);\n },\n\n /** Render icon-button to delete this hda. */\n _renderDeleteButton: function _renderDeleteButton() {\n // don't show delete if...\n if (!this.model.get(\"accessible\")) {\n return null;\n }\n\n var self = this;\n var deletedAlready = this.model.isDeletedOrPurged();\n return (0, _faIconButton2.default)({\n title: !deletedAlready ? (0, _localization2.default)(\"Delete\") : (0, _localization2.default)(\"Dataset is already deleted\"),\n disabled: deletedAlready,\n faIcon: \"fa-times\",\n classes: \"delete-btn\",\n onclick: function onclick() {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n self.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n self.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... details\n /** In this override, add tags and annotations controls, make the ? dbkey a link to editing page */\n _renderDetails: function _renderDetails() {\n //TODO: generalize to be allow different details for each state\n var $details = _super.prototype._renderDetails.call(this);\n\n var state = this.model.get(\"state\");\n\n if (!this.model.isDeletedOrPurged() && _.contains([_states2.default.OK, _states2.default.FAILED_METADATA], state)) {\n this._renderTags($details);\n this._renderAnnotation($details);\n this._makeDbkeyEditLink($details);\n }\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /**************************************************************************\n * Render help button to show tool help text without rerunning the tool.\n * Issue #2100\n */\n _renderToolHelpButton: function _renderToolHelpButton() {\n var datasetID = this.model.attributes.dataset_id;\n var jobID = this.model.attributes.creating_job;\n var self = this;\n\n var parseToolBuild = function parseToolBuild(data) {\n var helpString = \"
\";\n if (data.name && data.help) {\n helpString += \"Tool help for \" + data.name + \"\";\n helpString += data.help;\n } else {\n helpString += \"Tool help is unavailable for this dataset.\";\n }\n helpString += \"
\";\n self.$el.find(\".details\").append($.parseHTML(helpString));\n };\n var parseToolID = function parseToolID(data) {\n $.ajax({\n url: Galaxy.root + \"api/tools/\" + data.tool_id + \"/build\"\n }).done(function (data) {\n parseToolBuild(data);\n }).fail(function () {\n parseToolBuild({});\n });\n };\n if (Galaxy.user.id === null) {\n return null;\n }\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Tool Help\"),\n classes: \"icon-btn\",\n href: \"#\",\n faIcon: \"fa-question\",\n onclick: function onclick() {\n var divString = \"thdiv-\" + datasetID;\n if (self.$el.find(\".toolhelp\").length > 0) {\n self.$el.find(\".toolhelp\").toggle();\n } else {\n $.ajax({\n url: Galaxy.root + \"api/jobs/\" + jobID\n }).done(function (data) {\n parseToolID(data);\n }).fail(function () {\n console.log(\"Failed at recovering job information from the Galaxy API for job id \\\"\" + jobID + \"\\\".\");\n });\n }\n }\n });\n },\n //*************************************************************************\n\n /** Add less commonly used actions in the details section based on state */\n _renderSecondaryActions: function _renderSecondaryActions() {\n var actions = _super.prototype._renderSecondaryActions.call(this);\n switch (this.model.get(\"state\")) {\n case _states2.default.UPLOAD:\n case _states2.default.NOT_VIEWABLE:\n return actions;\n case _states2.default.ERROR:\n // error button comes first\n actions.unshift(this._renderErrButton());\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n case _states2.default.OK:\n case _states2.default.FAILED_METADATA:\n return actions.concat([this._renderRerunButton(), this._renderVisualizationsButton(), this._renderToolHelpButton()]);\n }\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n },\n\n /** Render icon-button to report an error on this dataset to the galaxy admin. */\n _renderErrButton: function _renderErrButton() {\n var self = this;\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"View or report this error\"),\n href: Galaxy.root + \"datasets/error?dataset_id=\" + this.model.attributes.id,\n classes: \"report-error-btn\",\n faIcon: \"fa-bug\",\n onclick: function onclick(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/error\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n });\n },\n\n /** Render icon-button to re-run the job that created this dataset. */\n _renderRerunButton: function _renderRerunButton() {\n var creating_job = this.model.get(\"creating_job\");\n if (this.model.get(\"rerunnable\")) {\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Run this job again\"),\n href: this.model.urls.rerun,\n classes: \"rerun-btn\",\n target: this.linkTarget,\n faIcon: \"fa-refresh\",\n onclick: function onclick(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"/\", {\n job_id: creating_job\n });\n }\n }\n });\n }\n },\n\n /** Render an icon-button or popupmenu of links based on the applicable visualizations */\n _renderVisualizationsButton: function _renderVisualizationsButton() {\n //TODO: someday - lazyload visualizations\n var visualizations = this.model.get(\"visualizations\");\n if (this.model.isDeletedOrPurged() || !this.hasUser || !this.model.hasData() || _.isEmpty(visualizations)) {\n return null;\n }\n if (!_.isObject(visualizations[0])) {\n this.warn(\"Visualizations have been switched off\");\n return null;\n }\n\n var $visualizations = $(this.templates.visualizations(visualizations, this));\n //HACK: need to re-write those directed at galaxy_main with linkTarget\n $visualizations.find('[target=\"galaxy_main\"]').attr(\"target\", this.linkTarget);\n // use addBack here to include the root $visualizations elem (for the case of 1 visualization)\n this._addScratchBookFn($visualizations.find(\".visualization-link\").addBack(\".visualization-link\"));\n return $visualizations;\n },\n\n /** add scratchbook functionality to visualization links */\n _addScratchBookFn: function _addScratchBookFn($links) {\n var li = this;\n $links.click(function (ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Visualization\",\n url: $(this).attr(\"href\")\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n });\n },\n\n //TODO: if possible move these to readonly view - but display the owner's tags/annotation (no edit)\n /** Render the tags list/control */\n _renderTags: function _renderTags($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.tagsEditor = new _tag2.default.TagsEditor({\n model: this.model,\n el: $where.find(\".tags-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function onshow() {\n view.tagsEditorShown = true;\n },\n onhide: function onhide() {\n view.tagsEditorShown = false;\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit dataset tags\"),\n classes: \"tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.tagsEditorShown) {\n this.tagsEditor.toggle(true);\n }\n },\n\n /** Render the annotation display/control */\n _renderAnnotation: function _renderAnnotation($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.annotationEditor = new _annotation2.default.AnnotationEditor({\n model: this.model,\n el: $where.find(\".annotation-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function onshow() {\n view.annotationEditorShown = true;\n },\n onhide: function onhide() {\n view.annotationEditorShown = false;\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit dataset annotation\"),\n classes: \"annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.annotationEditorShown) {\n this.annotationEditor.toggle(true);\n }\n },\n\n /** If the format/dbkey/genome_build isn't set, make the display a link to the edit page */\n _makeDbkeyEditLink: function _makeDbkeyEditLink($details) {\n // make the dbkey a link to editing\n if (this.model.get(\"metadata_dbkey\") === \"?\" && !this.model.isDeletedOrPurged()) {\n var editableDbkey = $('?').attr(\"href\", this.model.urls.edit).attr(\"target\", \"_top\");\n $details.find(\".dbkey .value\").replaceWith(editableDbkey);\n }\n },\n\n // ......................................................................... events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .undelete-link\": \"_clickUndeleteLink\",\n \"click .purge-link\": \"_clickPurgeLink\",\n\n \"click .edit-btn\": function clickEditBtn(ev) {\n this.trigger(\"edit\", this, ev);\n },\n \"click .delete-btn\": function clickDeleteBtn(ev) {\n this.trigger(\"delete\", this, ev);\n },\n \"click .rerun-btn\": function clickRerunBtn(ev) {\n this.trigger(\"rerun\", this, ev);\n },\n \"click .report-err-btn\": function clickReportErrBtn(ev) {\n this.trigger(\"report-err\", this, ev);\n },\n \"click .visualization-btn\": function clickVisualizationBtn(ev) {\n this.trigger(\"visualize\", this, ev);\n },\n \"click .dbkey a\": function clickDbkeyA(ev) {\n this.trigger(\"edit\", this, ev);\n }\n }),\n\n /** listener for item undelete (in the messages section) */\n _clickUndeleteLink: function _clickUndeleteLink(ev) {\n this.model.undelete();\n return false;\n },\n\n /** listener for item purge (in the messages section) */\n _clickPurgeLink: function _clickPurgeLink(ev) {\n if (confirm((0, _localization2.default)(\"This will permanently remove the data in your dataset. Are you sure?\"))) {\n this.model.purge();\n }\n return false;\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"HDAEditView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetListItemEdit.prototype.templates = function () {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n failed_metadata: _baseMvc2.default.wrapTemplate([\n // in this override, provide a link to the edit page\n '<% if( dataset.state === \"failed_metadata\" ){ %>', '
\", \"<% } %>\"], \"dataset\"),\n\n deleted: _baseMvc2.default.wrapTemplate([\n // in this override, provide links to undelete or purge the dataset\n \"<% if( dataset.deleted && !dataset.purged ){ %>\",\n // deleted not purged\n '
\", \"<% } %>\"], \"visualizations\");\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n visualizations: visualizationsTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n DatasetListItemEdit: DatasetListItemEdit\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 88 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(15);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// =============================================================================\n/** A view on any model that has a 'annotation' attribute\n */\nvar AnnotationEditor = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.HiddenUntilActivatedViewMixin).extend({\n tagName: \"div\",\n className: \"annotation-display\",\n\n /** Set up listeners, parse options */\n initialize: function initialize(options) {\n options = options || {};\n this.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n //console.debug( this, options );\n // only listen to the model only for changes to annotations\n this.listenTo(this.model, \"change:annotation\", function () {\n this.render();\n });\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function render() {\n var view = this;\n this.$el.html(this._template());\n\n //TODO: handle empties better\n this.$annotation().make_text_editable({\n use_textarea: true,\n on_finish: function on_finish(newAnnotation) {\n view.$annotation().text(newAnnotation);\n view.model.save({ annotation: newAnnotation }, { silent: true }).fail(function () {\n view.$annotation().text(view.model.previous(\"annotation\"));\n });\n }\n });\n return this;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _template: function _template() {\n var annotation = this.model.get(\"annotation\");\n return [\n //TODO: make prompt optional\n '\",\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n '
', _.escape(annotation), \"
\"].join(\"\");\n },\n\n /** @returns {jQuery} the main element for this view */\n $annotation: function $annotation() {\n return this.$el.find(\".annotation\");\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function remove() {\n this.$annotation.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function toString() {\n return [\"AnnotationEditor(\", \"\" + this.model, \")\"].join(\"\");\n }\n});\n// =============================================================================\nexports.default = {\n AnnotationEditor: AnnotationEditor\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 89 */,\n/* 90 */,\n/* 91 */,\n/* 92 */,\n/* 93 */,\n/* 94 */,\n/* 95 */,\n/* 96 */,\n/* 97 */,\n/* 98 */,\n/* 99 */,\n/* 100 */,\n/* 101 */,\n/* 102 */,\n/* 103 */,\n/* 104 */,\n/* 105 */,\n/* 106 */,\n/* 107 */,\n/* 108 */,\n/* 109 */,\n/* 110 */,\n/* 111 */,\n/* 112 */,\n/* 113 */,\n/* 114 */,\n/* 115 */,\n/* 116 */,\n/* 117 */,\n/* 118 */,\n/* 119 */,\n/* 120 */,\n/* 121 */,\n/* 122 */,\n/* 123 */,\n/* 124 */,\n/* 125 */,\n/* 126 */,\n/* 127 */,\n/* 128 */,\n/* 129 */,\n/* 130 */,\n/* 131 */,\n/* 132 */,\n/* 133 */,\n/* 134 */,\n/* 135 */,\n/* 136 */,\n/* 137 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nvar _galaxy = __webpack_require__(24);\n\nvar _galaxy2 = _interopRequireDefault(_galaxy);\n\nvar _router = __webpack_require__(30);\n\nvar _router2 = _interopRequireDefault(_router);\n\nvar _toolPanel = __webpack_require__(138);\n\nvar _toolPanel2 = _interopRequireDefault(_toolPanel);\n\nvar _historyPanel = __webpack_require__(149);\n\nvar _historyPanel2 = _interopRequireDefault(_historyPanel);\n\nvar _page = __webpack_require__(25);\n\nvar _page2 = _interopRequireDefault(_page);\n\nvar _toolForm = __webpack_require__(65);\n\nvar _toolForm2 = _interopRequireDefault(_toolForm);\n\nvar _formWrapper = __webpack_require__(44);\n\nvar _formWrapper2 = _interopRequireDefault(_formWrapper);\n\nvar _userPreferences = __webpack_require__(163);\n\nvar _userPreferences2 = _interopRequireDefault(_userPreferences);\n\nvar _userCustomBuilds = __webpack_require__(164);\n\nvar _userCustomBuilds2 = _interopRequireDefault(_userCustomBuilds);\n\nvar _tours = __webpack_require__(57);\n\nvar _tours2 = _interopRequireDefault(_tours);\n\nvar _gridView = __webpack_require__(12);\n\nvar _gridView2 = _interopRequireDefault(_gridView);\n\nvar _gridShared = __webpack_require__(165);\n\nvar _gridShared2 = _interopRequireDefault(_gridShared);\n\nvar _workflow = __webpack_require__(166);\n\nvar _workflow2 = _interopRequireDefault(_workflow);\n\nvar _historyList = __webpack_require__(168);\n\nvar _historyList2 = _interopRequireDefault(_historyList);\n\nvar _toolFormComposite = __webpack_require__(77);\n\nvar _toolFormComposite2 = _interopRequireDefault(_toolFormComposite);\n\nvar _queryStringParsing = __webpack_require__(8);\n\nvar _queryStringParsing2 = _interopRequireDefault(_queryStringParsing);\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _datasetError = __webpack_require__(169);\n\nvar _datasetError2 = _interopRequireDefault(_datasetError);\n\nvar _datasetEditAttributes = __webpack_require__(170);\n\nvar _datasetEditAttributes2 = _interopRequireDefault(_datasetEditAttributes);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar $ = _jquery2.default;\n\n\n/** define the 'Analyze Data'/analysis/main/home page for Galaxy\n * * has a masthead\n * * a left tool menu to allow the user to load tools in the center panel\n * * a right history menu that shows the user's current data\n * * a center panel\n * Both panels (generally) persist while the center panel shows any\n * UI needed for the current step of an analysis, like:\n * * tool forms to set tool parameters,\n * * tables showing the contents of datasets\n * * etc.\n */\nwindow.app = function app(options, bootstrapped) {\n window.Galaxy = new _galaxy2.default.GalaxyApp(options, bootstrapped);\n Galaxy.debug(\"analysis app\");\n\n /** Routes */\n var AnalysisRouter = _router2.default.extend({\n routes: {\n \"(/)\": \"home\",\n \"(/)root*\": \"home\",\n \"(/)tours(/)(:tour_id)\": \"show_tours\",\n \"(/)user(/)\": \"show_user\",\n \"(/)user(/)(:form_id)\": \"show_user_form\",\n \"(/)workflow(/)\": \"show_workflows\",\n \"(/)workflow/run(/)\": \"show_run\",\n \"(/)pages(/)create(/)\": \"show_pages_create\",\n \"(/)pages(/)edit(/)\": \"show_pages_edit\",\n \"(/)pages(/)(:action_id)\": \"show_pages\",\n \"(/)visualizations(/)edit(/)\": \"show_visualizations_edit\",\n \"(/)visualizations/(:action_id)\": \"show_visualizations\",\n \"(/)workflows/list_published(/)\": \"show_workflows_published\",\n \"(/)histories(/)rename(/)\": \"show_histories_rename\",\n \"(/)histories(/)permissions(/)\": \"show_histories_permissions\",\n \"(/)histories(/)(:action_id)\": \"show_histories\",\n \"(/)datasets(/)list(/)\": \"show_datasets\",\n \"(/)workflow/import_workflow\": \"show_import_workflow\",\n \"(/)custom_builds\": \"show_custom_builds\",\n \"(/)datasets/edit\": \"show_dataset_edit_attributes\",\n \"(/)datasets/error\": \"show_dataset_error\"\n },\n\n require_login: [\"show_user\", \"show_user_form\", \"show_workflows\"],\n\n authenticate: function authenticate(args, name) {\n return Galaxy.user && Galaxy.user.id || this.require_login.indexOf(name) == -1;\n },\n\n show_tours: function show_tours(tour_id) {\n if (tour_id) {\n _tours2.default.giveTour(tour_id);\n } else {\n this.page.display(new _tours2.default.ToursView());\n }\n },\n\n show_user: function show_user() {\n this.page.display(new _userPreferences2.default.View());\n },\n\n show_user_form: function show_user_form(form_id) {\n var model = new _userPreferences2.default.Model({\n user_id: Galaxy.params.id\n });\n this.page.display(new _formWrapper2.default.View(model.get(form_id)));\n },\n\n show_visualizations: function show_visualizations(action_id) {\n this.page.display(new _gridShared2.default.View({\n action_id: action_id,\n plural: \"Visualizations\",\n item: \"visualization\"\n }));\n },\n\n show_visualizations_edit: function show_visualizations_edit() {\n this.page.display(new _formWrapper2.default.View({\n url: \"visualization/edit?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"visualizations/list\"\n }));\n },\n\n show_workflows_published: function show_workflows_published() {\n this.page.display(new _gridView2.default({\n url_base: Galaxy.root + \"workflow/list_published\",\n dict_format: true\n }));\n },\n\n show_histories: function show_histories(action_id) {\n this.page.display(new _historyList2.default.View({ action_id: action_id }));\n },\n\n show_histories_rename: function show_histories_rename() {\n this.page.display(new _formWrapper2.default.View({\n url: \"history/rename?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"histories/list\"\n }));\n },\n\n show_histories_permissions: function show_histories_permissions() {\n this.page.display(new _formWrapper2.default.View({\n url: \"history/permissions?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"histories/list\"\n }));\n },\n\n show_datasets: function show_datasets() {\n this.page.display(new _gridView2.default({\n url_base: Galaxy.root + \"dataset/list\",\n dict_format: true\n }));\n },\n\n show_pages: function show_pages(action_id) {\n this.page.display(new _gridShared2.default.View({\n action_id: action_id,\n plural: \"Pages\",\n item: \"page\"\n }));\n },\n\n show_pages_create: function show_pages_create() {\n this.page.display(new _formWrapper2.default.View({\n url: \"page/create\",\n redirect: \"pages/list\"\n }));\n },\n\n show_pages_edit: function show_pages_edit() {\n this.page.display(new _formWrapper2.default.View({\n url: \"page/edit?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"pages/list\"\n }));\n },\n\n show_workflows: function show_workflows() {\n this.page.display(new _workflow2.default.View());\n },\n\n show_run: function show_run() {\n this._loadWorkflow();\n },\n\n show_import_workflow: function show_import_workflow() {\n this.page.display(new _workflow2.default.ImportWorkflowView());\n },\n\n show_custom_builds: function show_custom_builds() {\n var self = this;\n var historyPanel = this.page.historyPanel.historyView;\n if (!historyPanel || !historyPanel.model || !historyPanel.model.id) {\n window.setTimeout(function () {\n self.show_custom_builds();\n }, 500);\n return;\n }\n this.page.display(new _userCustomBuilds2.default.View());\n },\n\n show_dataset_edit_attributes: function show_dataset_edit_attributes() {\n this.page.display(new _datasetEditAttributes2.default.View());\n },\n\n show_dataset_error: function show_dataset_error() {\n this.page.display(new _datasetError2.default.View());\n },\n\n /** */\n home: function home(params) {\n // TODO: to router, remove Globals\n // load a tool by id (tool_id) or rerun a previous tool execution (job_id)\n if (params.tool_id || params.job_id) {\n if (params.tool_id === \"upload1\") {\n this.page.toolPanel.upload.show();\n this._loadCenterIframe(\"welcome\");\n } else {\n this._loadToolForm(params);\n }\n } else {\n // show the workflow run form\n if (params.workflow_id) {\n this._loadWorkflow();\n // load the center iframe with controller.action: galaxy.org/?m_c=history&m_a=list -> history/list\n } else if (params.m_c) {\n this._loadCenterIframe(params.m_c + \"/\" + params.m_a);\n // show the workflow run form\n } else {\n this._loadCenterIframe(\"welcome\");\n }\n }\n },\n\n /** load the center panel with a tool form described by the given params obj */\n _loadToolForm: function _loadToolForm(params) {\n //TODO: load tool form code async\n params.id = decodeURIComponent(params.tool_id);\n this.page.display(new _toolForm2.default.View(params));\n },\n\n /** load the center panel iframe using the given url */\n _loadCenterIframe: function _loadCenterIframe(url, root) {\n root = root || Galaxy.root;\n url = root + url;\n this.page.$(\"#galaxy_main\").prop(\"src\", url);\n },\n\n /** load workflow by its url in run mode */\n _loadWorkflow: function _loadWorkflow() {\n var self = this;\n _utils2.default.get({\n url: Galaxy.root + \"api/workflows/\" + _utils2.default.getQueryString(\"id\") + \"/download?style=run\",\n success: function success(response) {\n self.page.display(new _toolFormComposite2.default.View(response));\n },\n error: function error(response) {\n var error_msg = response.err_msg || \"Error occurred while loading the resource.\";\n var options = {\n message: error_msg,\n status: \"danger\",\n persistent: true\n };\n self.page.display(new _uiMisc2.default.Message(options));\n }\n });\n }\n });\n\n // render and start the router\n $(function () {\n Galaxy.page = new _page2.default.View(_.extend(options, {\n Left: _toolPanel2.default,\n Right: _historyPanel2.default,\n Router: AnalysisRouter\n }));\n });\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 138 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _tools = __webpack_require__(64);\n\nvar _tools2 = _interopRequireDefault(_tools);\n\nvar _uploadView = __webpack_require__(139);\n\nvar _uploadView2 = _interopRequireDefault(_uploadView);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nvar _toolFormComposite = __webpack_require__(77);\n\nvar _toolFormComposite2 = _interopRequireDefault(_toolFormComposite);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar ToolPanel = Backbone.View.extend({\n initialize: function initialize(page, options) {\n // access configuration options\n var config = options.config;\n this.root = options.root;\n\n /** @type {Object[]} descriptions of user's workflows to be shown in the tool menu */\n this.stored_workflow_menu_entries = config.stored_workflow_menu_entries || [];\n\n // create tool search, tool panel, and tool panel view.\n var tool_search = new _tools2.default.ToolSearch({\n hidden: false\n });\n var tools = new _tools2.default.ToolCollection(config.toolbox);\n this.tool_panel = new _tools2.default.ToolPanel({\n tool_search: tool_search,\n tools: tools,\n layout: config.toolbox_in_panel\n });\n this.tool_panel_view = new _tools2.default.ToolPanelView({\n model: this.tool_panel\n });\n\n // add upload modal\n this.upload_button = new _uploadView2.default({\n nginx_upload_path: config.nginx_upload_path,\n ftp_upload_site: config.ftp_upload_site,\n default_genome: config.default_genome,\n default_extension: config.default_extension\n });\n\n // add uploader button to Galaxy object\n Galaxy.upload = this.upload_button;\n\n // components for panel definition\n this.model = new Backbone.Model({\n title: (0, _localization2.default)(\"Tools\"),\n buttons: [this.upload_button]\n });\n\n // build body template\n this.setElement(this._template());\n },\n\n render: function render() {\n // if there are tools, render panel and display everything\n var self = this;\n if (this.tool_panel.get(\"layout\").size() > 0) {\n this.$el.prepend(this.tool_panel_view.$el);\n this.tool_panel_view.render();\n }\n // build the dom for the workflow portion of the tool menu\n // add internal workflow list\n self.$(\"#internal-workflows\").append(self._templateAllWorkflow({\n title: (0, _localization2.default)(\"All workflows\"),\n href: \"workflow\"\n }));\n _.each(this.stored_workflow_menu_entries, function (menu_entry) {\n self.$(\"#internal-workflows\").append(self._templateWorkflowLink({\n title: menu_entry.stored_workflow.name,\n href: \"workflow/run?id=\" + menu_entry.encoded_stored_workflow_id\n }));\n });\n },\n\n /** build a link to one tool */\n _templateTool: function _templateTool(tool) {\n return ['
\";\n }\n});\nexports.default = { View: View };\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 141 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _defaultRow = __webpack_require__(142);\n\nvar _defaultRow2 = _interopRequireDefault(_defaultRow);\n\nvar _uploadFtp2 = __webpack_require__(32);\n\nvar _uploadFtp3 = _interopRequireDefault(_uploadFtp2);\n\nvar _uploadExtension = __webpack_require__(33);\n\nvar _uploadExtension2 = _interopRequireDefault(_uploadExtension);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _lazyLimited = __webpack_require__(143);\n\nvar _lazyLimited2 = _interopRequireDefault(_lazyLimited);\n\n__webpack_require__(34);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Renders contents of the default uploader */\nexports.default = Backbone.View.extend({\n // current upload size in bytes\n upload_size: 0,\n\n // contains upload row models\n collection: new _uploadModel2.default.Collection(),\n\n // keeps track of the current uploader state\n counter: {\n announce: 0,\n success: 0,\n error: 0,\n running: 0,\n reset: function reset() {\n this.announce = this.success = this.error = this.running = 0;\n }\n },\n\n initialize: function initialize(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ui_button = app.ui_button;\n this.ftp_upload_site = app.currentFtp();\n\n // build template\n this.setElement(this._template());\n this.$uploadbox = this.$(\".upload-box\");\n this.$uploadtable = this.$(\".upload-table\");\n\n // append buttons to dom\n this.btnLocal = new _uiMisc2.default.Button({\n id: \"btn-local\",\n title: \"Choose local file\",\n onclick: function onclick() {\n self.uploadbox.select();\n },\n icon: \"fa fa-laptop\"\n });\n this.btnFtp = new _uiMisc2.default.Button({\n id: \"btn-ftp\",\n title: \"Choose FTP file\",\n onclick: function onclick() {\n self._eventFtp();\n },\n icon: \"fa fa-folder-open-o\"\n });\n this.btnCreate = new _uiMisc2.default.Button({\n id: \"btn-new\",\n title: \"Paste/Fetch data\",\n onclick: function onclick() {\n self._eventCreate();\n },\n icon: \"fa fa-edit\"\n });\n this.btnStart = new _uiMisc2.default.Button({\n id: \"btn-start\",\n title: \"Start\",\n onclick: function onclick() {\n self._eventStart();\n }\n });\n this.btnStop = new _uiMisc2.default.Button({\n id: \"btn-stop\",\n title: \"Pause\",\n onclick: function onclick() {\n self._eventStop();\n }\n });\n this.btnReset = new _uiMisc2.default.Button({\n id: \"btn-reset\",\n title: \"Reset\",\n onclick: function onclick() {\n self._eventReset();\n }\n });\n this.btnClose = new _uiMisc2.default.Button({\n id: \"btn-close\",\n title: \"Close\",\n onclick: function onclick() {\n self.app.modal.hide();\n }\n });\n _.each([this.btnLocal, this.btnFtp, this.btnCreate, this.btnStop, this.btnReset, this.btnStart, this.btnClose], function (button) {\n self.$(\".upload-buttons\").prepend(button.$el);\n });\n\n // file upload\n this.uploadbox = this.$uploadbox.uploadbox({\n url: this.app.options.nginx_upload_path,\n announce: function announce(index, file) {\n self._eventAnnounce(index, file);\n },\n initialize: function initialize(index) {\n return self.app.toData([self.collection.get(index)], self.history_id);\n },\n progress: function progress(index, percentage) {\n self._eventProgress(index, percentage);\n },\n success: function success(index, message) {\n self._eventSuccess(index, message);\n },\n error: function error(index, message) {\n self._eventError(index, message);\n },\n complete: function complete() {\n self._eventComplete();\n },\n ondragover: function ondragover() {\n self.$uploadbox.addClass(\"highlight\");\n },\n ondragleave: function ondragleave() {\n self.$uploadbox.removeClass(\"highlight\");\n }\n });\n\n // add ftp file viewer\n this.ftp = new _uiPopover2.default.View({\n title: \"FTP files\",\n container: this.btnFtp.$el\n });\n\n // select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, function (ext) {\n return !ext.composite_files;\n }),\n value: this.options.default_extension,\n onchange: function onchange(extension) {\n self._changeExtension(extension);\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\").on(\"click\", function (e) {\n new _uploadExtension2.default({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome,\n onchange: function onchange(genome) {\n self._changeGenome(genome);\n }\n });\n\n // Lazy load helper\n this.loader = new _lazyLimited2.default({\n $container: this.$uploadbox,\n collection: this.collection,\n new_content: function new_content(model) {\n var upload_row = new _defaultRow2.default(self, { model: model });\n self.$uploadtable.find(\"> tbody:first\").append(upload_row.$el);\n upload_row.render();\n return upload_row;\n }\n });\n\n // events\n this.collection.on(\"remove\", function (model) {\n self._eventRemove(model);\n });\n this.render();\n },\n\n render: function render() {\n var message = \"\";\n if (this.counter.announce == 0) {\n if (this.uploadbox.compatible()) {\n message = \" \";\n } else {\n message = \"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.\";\n }\n } else {\n if (this.counter.running == 0) {\n message = \"You added \" + this.counter.announce + \" file(s) to the queue. Add more files or click 'Start' to proceed.\";\n } else {\n message = \"Please wait...\" + this.counter.announce + \" out of \" + this.counter.running + \" remaining.\";\n }\n }\n this.$(\".upload-top-info\").html(message);\n var enable_reset = this.counter.running == 0 && this.counter.announce + this.counter.success + this.counter.error > 0;\n var enable_start = this.counter.running == 0 && this.counter.announce > 0;\n var enable_sources = this.counter.running == 0;\n var show_table = this.counter.announce + this.counter.success + this.counter.error > 0;\n this.btnReset[enable_reset ? \"enable\" : \"disable\"]();\n this.btnStart[enable_start ? \"enable\" : \"disable\"]();\n this.btnStart.$el[enable_start ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnStop[this.counter.running > 0 ? \"enable\" : \"disable\"]();\n this.btnLocal[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp[enable_sources ? \"enable\" : \"disable\"]();\n this.btnCreate[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp.$el[this.ftp_upload_site ? \"show\" : \"hide\"]();\n this.$(\".upload-table\")[show_table ? \"show\" : \"hide\"]();\n this.$(\".upload-helper\")[show_table ? \"hide\" : \"show\"]();\n },\n\n /** A new file has been dropped/selected through the uploadbox plugin */\n _eventAnnounce: function _eventAnnounce(index, file) {\n this.counter.announce++;\n var new_model = new _uploadModel2.default.Model({\n id: index,\n file_name: file.name,\n file_size: file.size,\n file_mode: file.mode || \"local\",\n file_path: file.path,\n file_data: file\n });\n this.render();\n this.collection.add(new_model);\n },\n\n /** Progress */\n _eventProgress: function _eventProgress(index, percentage) {\n var it = this.collection.get(index);\n it.set(\"percentage\", percentage);\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(percentage, it.get(\"file_size\")));\n },\n\n /** Success */\n _eventSuccess: function _eventSuccess(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"success\" });\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(100, it.get(\"file_size\")));\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.success++;\n this.render();\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Error */\n _eventError: function _eventError(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"error\", info: message });\n this.ui_button.model.set({\n percentage: this._uploadPercentage(100, it.get(\"file_size\")),\n status: \"danger\"\n });\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.error++;\n this.render();\n },\n\n /** Queue is done */\n _eventComplete: function _eventComplete() {\n this.collection.each(function (model) {\n model.get(\"status\") == \"queued\" && model.set(\"status\", \"init\");\n });\n this.counter.running = 0;\n this.render();\n },\n\n /** Remove model from upload list */\n _eventRemove: function _eventRemove(model) {\n var status = model.get(\"status\");\n if (status == \"success\") {\n this.counter.success--;\n } else if (status == \"error\") {\n this.counter.error--;\n } else {\n this.counter.announce--;\n }\n this.uploadbox.remove(model.id);\n this.render();\n },\n\n //\n // events triggered by this view\n //\n\n /** Show/hide ftp popup */\n _eventFtp: function _eventFtp() {\n if (!this.ftp.visible) {\n this.ftp.empty();\n var self = this;\n this.ftp.append(new _uploadFtp3.default({\n collection: this.collection,\n ftp_upload_site: this.ftp_upload_site,\n onadd: function onadd(ftp_file) {\n return self.uploadbox.add([{\n mode: \"ftp\",\n name: ftp_file.path,\n size: ftp_file.size,\n path: ftp_file.path\n }]);\n },\n onremove: function onremove(model_index) {\n self.collection.remove(model_index);\n }\n }).$el);\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Create a new file */\n _eventCreate: function _eventCreate() {\n this.uploadbox.add([{ name: \"New File\", size: 0, mode: \"new\" }]);\n },\n\n /** Start upload process */\n _eventStart: function _eventStart() {\n if (this.counter.announce != 0 && this.counter.running == 0) {\n // prepare upload process\n var self = this;\n this.upload_size = 0;\n this.upload_completed = 0;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\") {\n model.set(\"status\", \"queued\");\n self.upload_size += model.get(\"file_size\");\n }\n });\n this.ui_button.model.set({\n percentage: 0,\n status: \"success\"\n });\n this.counter.running = this.counter.announce;\n this.history_id = this.app.currentHistory();\n\n // package ftp files separately, and remove them from queue\n this._uploadFtp();\n\n // queue remaining files\n this.uploadbox.start();\n this.render();\n }\n },\n\n /** Pause upload process */\n _eventStop: function _eventStop() {\n if (this.counter.running > 0) {\n this.ui_button.model.set(\"status\", \"info\");\n $(\".upload-top-info\").html(\"Queue will pause after completing the current file...\");\n this.uploadbox.stop();\n }\n },\n\n /** Remove all */\n _eventReset: function _eventReset() {\n if (this.counter.running == 0) {\n var self = this;\n this.collection.reset();\n this.counter.reset();\n this.uploadbox.reset();\n this.select_extension.value(this.options.default_extension);\n this.select_genome.value(this.options.default_genome);\n this.ui_button.model.set(\"percentage\", 0);\n this.render();\n }\n },\n\n /** Update extension for all models */\n _changeExtension: function _changeExtension(extension, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"extension\") == self.options.default_extension || !defaults_only)) {\n model.set(\"extension\", extension);\n }\n });\n },\n\n /** Update genome for all models */\n _changeGenome: function _changeGenome(genome, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"genome\") == self.options.default_genome || !defaults_only)) {\n model.set(\"genome\", genome);\n }\n });\n },\n\n /** Package and upload ftp files in a single request */\n _uploadFtp: function _uploadFtp() {\n var self = this;\n var list = [];\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"queued\" && model.get(\"file_mode\") == \"ftp\") {\n self.uploadbox.remove(model.id);\n list.push(model);\n }\n });\n if (list.length > 0) {\n $.uploadpost({\n data: this.app.toData(list),\n url: this.app.options.nginx_upload_path,\n success: function success(message) {\n _.each(list, function (model) {\n self._eventSuccess(model.id);\n });\n },\n error: function error(message) {\n _.each(list, function (model) {\n self._eventError(model.id, message);\n });\n }\n });\n }\n },\n\n /** Calculate percentage of all queued uploads */\n _uploadPercentage: function _uploadPercentage(percentage, size) {\n return (this.upload_completed + percentage * size) / this.upload_size;\n },\n\n /** Template */\n _template: function _template() {\n return '
' + '
' + '
' + \"
\" + '
' + '
Drop files here
' + '
' + \"\" + \"
\" + \"
Name
\" + \"
Size
\" + \"
Type
\" + \"
Genome
\" + \"
Settings
\" + \"
Status
\" + \"
\" + \"
\" + \"\" + \"\" + \"
\" + \"
\" + '\" + '
' + \"
\";\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 142 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _uploadSettings = __webpack_require__(31);\n\nvar _uploadSettings2 = _interopRequireDefault(_uploadSettings);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-icon-button fa fa-trash-o\",\n queued: \"upload-icon fa fa-spinner fa-spin\",\n running: \"upload-icon fa fa-spinner fa-spin\",\n success: \"upload-icon-button fa fa-check\",\n error: \"upload-icon-button fa fa-exclamation-triangle\"\n },\n\n initialize: function initialize(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template(options.model));\n this.$mode = this.$(\".upload-mode\");\n this.$title = this.$(\".upload-title\");\n this.$text = this.$(\".upload-text\");\n this.$size = this.$(\".upload-size\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$settings = this.$(\".upload-settings\");\n this.$symbol = this.$(\".upload-symbol\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // append popup to settings icon\n this.settings = new _uiPopover2.default.View({\n title: \"Upload configuration\",\n container: this.$(\".upload-settings\"),\n placement: \"bottom\"\n });\n\n // identify default genome and extension values\n var default_genome = this.app.select_genome.value();\n var default_extension = this.app.select_extension.value();\n\n // create select genomes\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-genome\",\n data: self.app.list_genomes,\n container: this.$(\".upload-genome\"),\n value: default_genome,\n onchange: function onchange(genome) {\n self.model.set(\"genome\", genome);\n }\n });\n\n // create select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-extension\",\n data: self.app.list_extensions,\n container: this.$(\".upload-extension\"),\n value: default_extension,\n onchange: function onchange(extension) {\n self.model.set(\"extension\", extension);\n }\n });\n\n // initialize genome and extension values\n this.model.set({\n genome: default_genome,\n extension: default_extension\n });\n\n // handle click event\n this.$symbol.on(\"click\", function () {\n self._removeRow();\n });\n\n // handle extension info popover\n this.$(\".upload-extension-info\").on(\"click\", function (e) {\n self.app.showExtensionInfo({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value()\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // handle settings popover\n this.$settings.on(\"click\", function (e) {\n self._showSettings();\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", function (e) {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", function () {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", function () {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", function () {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:genome\", function () {\n self._refreshGenome();\n });\n this.listenTo(this.model, \"change:extension\", function () {\n self._refreshExtension();\n });\n this.listenTo(this.model, \"change:file_size\", function () {\n self._refreshFileSize();\n });\n },\n\n render: function render() {\n this._refreshType();\n this._refreshPercentage();\n this._refreshStatus();\n this._refreshInfo();\n this._refreshGenome();\n this._refreshExtension();\n this._refreshFileSize();\n },\n\n /** Remove view */\n remove: function remove() {\n this.select_genome.remove();\n this.select_extension.remove();\n Backbone.View.prototype.remove.apply(this);\n },\n\n /** Render type */\n _refreshType: function _refreshType() {\n var options = this.model.attributes;\n this.$title.html(_.escape(options.file_name));\n this.$size.html(_utils2.default.bytesToString(options.file_size));\n this.$mode.removeClass().addClass(\"upload-mode\").addClass(\"text-primary\");\n if (options.file_mode == \"new\") {\n this.$text.css({\n width: this.$el.width() - 16 + \"px\",\n top: this.$el.height() - 8 + \"px\"\n }).show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$mode.addClass(\"fa fa-edit\");\n } else if (options.file_mode == \"local\") {\n this.$mode.addClass(\"fa fa-laptop\");\n } else if (options.file_mode == \"ftp\") {\n this.$mode.addClass(\"fa fa-folder-open-o\");\n }\n },\n\n /** Update extension */\n _refreshExtension: function _refreshExtension() {\n this.select_extension.value(this.model.get(\"extension\"));\n },\n\n /** Update genome */\n _refreshGenome: function _refreshGenome() {\n this.select_genome.value(this.model.get(\"genome\"));\n },\n\n /** Refresh info text */\n _refreshInfo: function _refreshInfo() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(\"Failed: \" + info).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage status */\n _refreshPercentage: function _refreshPercentage() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n this.$progress_bar.css({ width: percentage + \"%\" });\n this.$percentage.html(percentage != 100 ? percentage + \"%\" : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function _refreshStatus() {\n var status = this.model.get(\"status\");\n this.$symbol.removeClass().addClass(\"upload-symbol\").addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status == \"init\");\n var enabled = this.model.get(\"enabled\");\n this.$text_content.attr(\"disabled\", !enabled);\n if (enabled) {\n this.select_genome.enable();\n this.select_extension.enable();\n } else {\n this.select_genome.disable();\n this.select_extension.disable();\n }\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.$info_progress.hide();\n }\n },\n\n /** Refresh file size */\n _refreshFileSize: function _refreshFileSize() {\n this.$size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Remove row */\n _removeRow: function _removeRow() {\n if ([\"init\", \"success\", \"error\"].indexOf(this.model.get(\"status\")) !== -1) {\n this.app.collection.remove(this.model);\n }\n },\n\n /** Attach file info popup */\n _showSettings: function _showSettings() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new _uploadSettings2.default(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** View template */\n _template: function _template(options) {\n return \"
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
 
0%
\";\n }\n}); /** Renders the default uploader rows */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 143 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/** Contains helpers to limit/lazy load views for backbone views */\n\nexports.default = Backbone.View.extend({\n initialize: function initialize(options) {\n var self = this;\n this.$container = options.$container;\n this.collection = options.collection;\n this.new_content = options.new_content;\n this.max = options.max || 50;\n this.content_list = {};\n this.$message = $(\"\").addClass(\"ui-limitloader\").append(\"...only the first \" + this.max + \" entries are visible.\");\n this.$container.append(this.$message);\n this.listenTo(this.collection, \"reset\", this._reset, this);\n this.listenTo(this.collection, \"add\", this._refresh, this);\n this.listenTo(this.collection, \"remove\", this._remove, this);\n },\n\n /** Checks if the limit has been reached */\n _done: function _done() {\n var done = _.size(this.content_list) > this.max;\n this.$message[done ? \"show\" : \"hide\"]();\n return done;\n },\n\n /** Remove all content */\n _reset: function _reset() {\n _.each(this.content_list, function (content) {\n content.remove();\n });\n this.content_list = {};\n this.$message.hide();\n },\n\n /** Remove content */\n _remove: function _remove(model) {\n var model_id = model.id;\n var content = this.content_list[model_id];\n if (content) {\n content.remove();\n delete this.content_list[model_id];\n }\n this._refresh();\n },\n\n /** Refreshes container content by adding new views if visible */\n _refresh: function _refresh() {\n if (!this._done()) {\n for (var i in this.collection.models) {\n var model = this.collection.models[i];\n var view = this.content_list[model.id];\n if (!this.content_list[model.id]) {\n var content = this.new_content(model);\n this.content_list[model.id] = content;\n if (this._done()) {\n break;\n }\n }\n }\n }\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 144 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _compositeRow = __webpack_require__(145);\n\nvar _compositeRow2 = _interopRequireDefault(_compositeRow);\n\nvar _uploadExtension = __webpack_require__(33);\n\nvar _uploadExtension2 = _interopRequireDefault(_uploadExtension);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n collection: new _uploadModel2.default.Collection(),\n initialize: function initialize(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ftp_upload_site = app.currentFtp();\n this.setElement(this._template());\n\n // create button section\n this.btnStart = new _uiMisc2.default.Button({\n title: \"Start\",\n onclick: function onclick() {\n self._eventStart();\n }\n });\n this.btnClose = new _uiMisc2.default.Button({\n title: \"Close\",\n onclick: function onclick() {\n self.app.modal.hide();\n }\n });\n\n // append buttons to dom\n _.each([this.btnStart, this.btnClose], function (button) {\n self.$(\".upload-buttons\").prepend(button.$el);\n });\n\n // select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, function (ext) {\n return ext.composite_files;\n }),\n onchange: function onchange(extension) {\n self.collection.reset();\n var details = _.findWhere(self.list_extensions, {\n id: extension\n });\n if (details && details.composite_files) {\n _.each(details.composite_files, function (item) {\n self.collection.add({\n id: self.collection.size(),\n file_desc: item.description || item.name\n });\n });\n }\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\").on(\"click\", function (e) {\n new _uploadExtension2.default({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome\n });\n\n // listener for collection triggers on change in composite datatype and extension selection\n this.listenTo(this.collection, \"add\", function (model) {\n self._eventAnnounce(model);\n });\n this.listenTo(this.collection, \"change add\", function () {\n self.render();\n });\n this.select_extension.options.onchange(this.select_extension.value());\n this.render();\n },\n\n render: function render() {\n var model = this.collection.first();\n if (model && model.get(\"status\") == \"running\") {\n this.select_genome.disable();\n this.select_extension.disable();\n } else {\n this.select_genome.enable();\n this.select_extension.enable();\n }\n if (this.collection.where({ status: \"ready\" }).length == this.collection.length && this.collection.length > 0) {\n this.btnStart.enable();\n this.btnStart.$el.addClass(\"btn-primary\");\n } else {\n this.btnStart.disable();\n this.btnStart.$el.removeClass(\"btn-primary\");\n }\n this.$(\".upload-table\")[this.collection.length > 0 ? \"show\" : \"hide\"]();\n },\n\n //\n // upload events / process pipeline\n //\n\n /** Builds the basic ui with placeholder rows for each composite data type file */\n _eventAnnounce: function _eventAnnounce(model) {\n var upload_row = new _compositeRow2.default(this, { model: model });\n this.$(\".upload-table > tbody:first\").append(upload_row.$el);\n this.$(\".upload-table\")[this.collection.length > 0 ? \"show\" : \"hide\"]();\n upload_row.render();\n },\n\n /** Start upload process */\n _eventStart: function _eventStart() {\n var self = this;\n this.collection.each(function (model) {\n model.set({\n genome: self.select_genome.value(),\n extension: self.select_extension.value()\n });\n });\n $.uploadpost({\n url: this.app.options.nginx_upload_path,\n data: this.app.toData(this.collection.filter()),\n success: function success(message) {\n self._eventSuccess(message);\n },\n error: function error(message) {\n self._eventError(message);\n },\n progress: function progress(percentage) {\n self._eventProgress(percentage);\n }\n });\n },\n\n /** Refresh progress state */\n _eventProgress: function _eventProgress(percentage) {\n this.collection.each(function (it) {\n it.set(\"percentage\", percentage);\n });\n },\n\n /** Refresh success state */\n _eventSuccess: function _eventSuccess(message) {\n this.collection.each(function (it) {\n it.set(\"status\", \"success\");\n });\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Refresh error state */\n _eventError: function _eventError(message) {\n this.collection.each(function (it) {\n it.set({ status: \"error\", info: message });\n });\n },\n\n /** Load html template */\n _template: function _template() {\n return '
' + '
' + '
' + \"
\" + '
' + '
' + \"\" + \"
\" + \"
\" + \"
\" + \"
Description
\" + \"
Name
\" + \"
Size
\" + \"
Settings
\" + \"
Status
\" + \"
\" + \"\" + \"\" + \"
\" + \"
\" + '\" + '
' + \"
\";\n }\n}); /** Renders contents of the composite uploader */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 145 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadSettings = __webpack_require__(31);\n\nvar _uploadSettings2 = _interopRequireDefault(_uploadSettings);\n\nvar _uploadFtp = __webpack_require__(32);\n\nvar _uploadFtp2 = _interopRequireDefault(_uploadFtp);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\n__webpack_require__(34);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-mode fa fa-exclamation text-primary\",\n ready: \"upload-mode fa fa-check text-success\",\n running: \"upload-mode fa fa-spinner fa-spin\",\n success: \"upload-mode fa fa-check\",\n error: \"upload-mode fa fa-exclamation-triangle\"\n },\n\n initialize: function initialize(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template());\n this.$source = this.$(\".upload-source\");\n this.$settings = this.$(\".upload-settings\");\n this.$status = this.$(\".upload-status\");\n this.$text = this.$(\".upload-text\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$file_name = this.$(\".upload-file-name\");\n this.$file_desc = this.$(\".upload-file-desc\");\n this.$file_size = this.$(\".upload-file-size\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // build upload functions\n this.uploadinput = this.$el.uploadinput({\n ondragover: function ondragover() {\n self.model.get(\"enabled\") && self.$el.addClass(\"warning\");\n },\n ondragleave: function ondragleave() {\n self.$el.removeClass(\"warning\");\n },\n onchange: function onchange(files) {\n if (self.model.get(\"status\") != \"running\" && files && files.length > 0) {\n self.model.reset({\n file_data: files[0],\n file_name: files[0].name,\n file_size: files[0].size,\n file_mode: files[0].mode || \"local\"\n });\n self._refreshReady();\n }\n }\n });\n\n // source selection popup\n this.button_menu = new _uiMisc2.default.ButtonMenu({\n icon: \"fa-caret-down\",\n title: \"Select\",\n pull: \"left\"\n });\n this.$source.append(this.button_menu.$el);\n this.button_menu.addMenu({\n icon: \"fa-laptop\",\n title: \"Choose local file\",\n onclick: function onclick() {\n self.uploadinput.dialog();\n }\n });\n if (this.app.ftp_upload_site) {\n this.button_menu.addMenu({\n icon: \"fa-folder-open-o\",\n title: \"Choose FTP file\",\n onclick: function onclick() {\n self._showFtp();\n }\n });\n }\n this.button_menu.addMenu({\n icon: \"fa-edit\",\n title: \"Paste/Fetch data\",\n onclick: function onclick() {\n self.model.reset({\n file_mode: \"new\",\n file_name: \"New File\"\n });\n }\n });\n\n // add ftp file viewer\n this.ftp = new _uiPopover2.default.View({\n title: \"Choose FTP file:\",\n container: this.$source.find(\".ui-button-menu\"),\n placement: \"right\"\n });\n\n // append popup to settings icon\n this.settings = new _uiPopover2.default.View({\n title: \"Upload configuration\",\n container: this.$settings,\n placement: \"bottom\"\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", function (e) {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n self._refreshReady();\n });\n\n // handle settings popover\n this.$settings.on(\"click\", function (e) {\n self._showSettings();\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", function () {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", function () {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", function () {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:file_name\", function () {\n self._refreshFileName();\n });\n this.listenTo(this.model, \"change:file_mode\", function () {\n self._refreshMode();\n });\n this.listenTo(this.model, \"change:file_size\", function () {\n self._refreshFileSize();\n });\n this.listenTo(this.model, \"remove\", function () {\n self.remove();\n });\n this.app.collection.on(\"reset\", function () {\n self.remove();\n });\n },\n\n render: function render() {\n this.$el.attr(\"id\", \"upload-row-\" + this.model.id);\n this.$file_name.html(_.escape(this.model.get(\"file_name\") || \"-\"));\n this.$file_desc.html(this.model.get(\"file_desc\") || \"Unavailable\");\n this.$file_size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n this.$status.removeClass().addClass(this.status_classes.init);\n },\n\n /** Remove view */\n remove: function remove() {\n // call the base class remove method\n Backbone.View.prototype.remove.apply(this);\n },\n\n //\n // handle model events\n //\n\n /** Refresh ready or not states */\n _refreshReady: function _refreshReady() {\n this.app.collection.each(function (model) {\n model.set(\"status\", model.get(\"file_size\") > 0 && \"ready\" || \"init\");\n });\n },\n\n /** Refresh mode and e.g. show/hide textarea field */\n _refreshMode: function _refreshMode() {\n var file_mode = this.model.get(\"file_mode\");\n if (file_mode == \"new\") {\n this.height = this.$el.height();\n this.$text.css({\n width: this.$el.width() - 16 + \"px\",\n top: this.$el.height() - 8 + \"px\"\n }).show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$text_content.val(\"\").trigger(\"keyup\");\n } else {\n this.$el.height(this.height);\n this.$text.hide();\n }\n },\n\n /** Refresh information */\n _refreshInfo: function _refreshInfo() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(\"Failed: \" + info).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage */\n _refreshPercentage: function _refreshPercentage() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n if (percentage != 0) {\n this.$progress_bar.css({ width: percentage + \"%\" });\n } else {\n this.$progress_bar.addClass(\"no-transition\");\n this.$progress_bar.css({ width: \"0%\" });\n this.$progress_bar[0].offsetHeight;\n this.$progress_bar.removeClass(\"no-transition\");\n }\n this.$percentage.html(percentage != 100 ? percentage + \"%\" : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function _refreshStatus() {\n var status = this.model.get(\"status\");\n this.$status.removeClass().addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status != \"running\");\n this.$text_content.attr(\"disabled\", !this.model.get(\"enabled\"));\n this.$el.removeClass(\"success danger warning\");\n if (status == \"running\" || status == \"ready\") {\n this.model.set(\"percentage\", 0);\n }\n this.$source.find(\".button\")[status == \"running\" ? \"addClass\" : \"removeClass\"](\"disabled\");\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.model.set(\"percentage\", 100);\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.model.set(\"percentage\", 0);\n this.$info_progress.hide();\n this.$info_text.show();\n } else {\n this.$info_progress.show();\n this.$info_text.hide();\n }\n },\n\n /** File name */\n _refreshFileName: function _refreshFileName() {\n this.$file_name.html(this.model.get(\"file_name\") || \"-\");\n },\n\n /** File size */\n _refreshFileSize: function _refreshFileSize() {\n this.$file_size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Show/hide ftp popup */\n _showFtp: function _showFtp() {\n if (!this.ftp.visible) {\n var self = this;\n this.ftp.empty();\n this.ftp.append(new _uploadFtp2.default({\n ftp_upload_site: this.app.ftp_upload_site,\n onchange: function onchange(ftp_file) {\n self.ftp.hide();\n if (self.model.get(\"status\") != \"running\" && ftp_file) {\n self.model.reset({\n file_mode: \"ftp\",\n file_name: ftp_file.path,\n file_size: ftp_file.size,\n file_path: ftp_file.path\n });\n self._refreshReady();\n }\n }\n }).$el);\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Show/hide settings popup */\n _showSettings: function _showSettings() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new _uploadSettings2.default(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** Template */\n _template: function _template() {\n return '
' + \"
\" + '
' + '
' + '
' + '
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
' + '' + \"
\" + \"
\" + \"
\" + \"
\" + '
' + \"
\" + \"
\" + '' + \"
\" + \"
\" + '' + \"
\" + \"
\" + '' + \"
\" + '
' + \"
\" + '
' + '
' + '
' + '' + '
0%
' + \"
\" + \"
\" + \"
\" + \"
\";\n }\n}); /** Renders the composite upload row view */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 146 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _collectionRow = __webpack_require__(147);\n\nvar _collectionRow2 = _interopRequireDefault(_collectionRow);\n\nvar _uploadFtp = __webpack_require__(32);\n\nvar _uploadFtp2 = _interopRequireDefault(_uploadFtp);\n\nvar _uploadExtension = __webpack_require__(33);\n\nvar _uploadExtension2 = _interopRequireDefault(_uploadExtension);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _listCollectionCreator = __webpack_require__(35);\n\nvar _listCollectionCreator2 = _interopRequireDefault(_listCollectionCreator);\n\n__webpack_require__(34);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Renders contents of the collection uploader */\nexports.default = Backbone.View.extend({\n // current upload size in bytes\n upload_size: 0,\n\n // contains upload row models\n collection: new _uploadModel2.default.Collection(),\n\n // keeps track of the current uploader state\n counter: {\n announce: 0,\n success: 0,\n error: 0,\n running: 0,\n reset: function reset() {\n this.announce = this.success = this.error = this.running = 0;\n }\n },\n\n initialize: function initialize(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ui_button = app.ui_button;\n this.ftp_upload_site = app.currentFtp();\n this.setElement(this._template());\n\n // append buttons to dom\n this.btnLocal = new _uiMisc2.default.Button({\n id: \"btn-local\",\n title: \"Choose local files\",\n onclick: function onclick() {\n self.uploadbox.select();\n },\n icon: \"fa fa-laptop\"\n });\n this.btnFtp = new _uiMisc2.default.Button({\n id: \"btn-ftp\",\n title: \"Choose FTP files\",\n onclick: function onclick() {\n self._eventFtp();\n },\n icon: \"fa fa-folder-open-o\"\n });\n this.btnCreate = new _uiMisc2.default.Button({\n id: \"btn-new\",\n title: \"Paste/Fetch data\",\n onclick: function onclick() {\n self._eventCreate();\n },\n icon: \"fa fa-edit\"\n });\n this.btnStart = new _uiMisc2.default.Button({\n id: \"btn-start\",\n title: \"Start\",\n onclick: function onclick() {\n self._eventStart();\n }\n });\n this.btnBuild = new _uiMisc2.default.Button({\n id: \"btn-build\",\n title: \"Build\",\n onclick: function onclick() {\n self._eventBuild();\n }\n });\n this.btnStop = new _uiMisc2.default.Button({\n id: \"btn-stop\",\n title: \"Pause\",\n onclick: function onclick() {\n self._eventStop();\n }\n });\n this.btnReset = new _uiMisc2.default.Button({\n id: \"btn-reset\",\n title: \"Reset\",\n onclick: function onclick() {\n self._eventReset();\n }\n });\n this.btnClose = new _uiMisc2.default.Button({\n id: \"btn-close\",\n title: \"Close\",\n onclick: function onclick() {\n self.app.modal.hide();\n }\n });\n _.each([this.btnLocal, this.btnFtp, this.btnCreate, this.btnStop, this.btnReset, this.btnStart, this.btnBuild, this.btnClose], function (button) {\n self.$(\".upload-buttons\").prepend(button.$el);\n });\n\n // file upload\n this.uploadbox = this.$(\".upload-box\").uploadbox({\n url: this.app.options.nginx_upload_path,\n announce: function announce(index, file) {\n self._eventAnnounce(index, file);\n },\n initialize: function initialize(index) {\n return self.app.toData([self.collection.get(index)], self.history_id);\n },\n progress: function progress(index, percentage) {\n self._eventProgress(index, percentage);\n },\n success: function success(index, message) {\n self._eventSuccess(index, message);\n },\n error: function error(index, message) {\n self._eventError(index, message);\n },\n complete: function complete() {\n self._eventComplete();\n },\n ondragover: function ondragover() {\n self.$(\".upload-box\").addClass(\"highlight\");\n },\n ondragleave: function ondragleave() {\n self.$(\".upload-box\").removeClass(\"highlight\");\n }\n });\n\n // add ftp file viewer\n this.ftp = new _uiPopover2.default.View({\n title: \"FTP files\",\n container: this.btnFtp.$el\n });\n\n // select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, function (ext) {\n return !ext.composite_files;\n }),\n value: this.options.default_extension,\n onchange: function onchange(extension) {\n self.updateExtension(extension);\n }\n });\n\n this.collectionType = \"list\";\n this.select_collection = new _uiSelect2.default.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-collection-type\"),\n data: [{ id: \"list\", text: \"List\" }, { id: \"paired\", text: \"Paired\" }, { id: \"list:paired\", text: \"List of Pairs\" }],\n value: \"list\",\n onchange: function onchange(collectionType) {\n self.updateCollectionType(collectionType);\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\").on(\"click\", function (e) {\n new _uploadExtension2.default({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome,\n onchange: function onchange(genome) {\n self.updateGenome(genome);\n }\n });\n\n // events\n this.collection.on(\"remove\", function (model) {\n self._eventRemove(model);\n });\n this._updateScreen();\n },\n\n /** A new file has been dropped/selected through the uploadbox plugin */\n _eventAnnounce: function _eventAnnounce(index, file) {\n this.counter.announce++;\n var new_model = new _uploadModel2.default.Model({\n id: index,\n file_name: file.name,\n file_size: file.size,\n file_mode: file.mode || \"local\",\n file_path: file.path,\n file_data: file,\n extension: this.select_extension.value(),\n genome: this.select_genome.value()\n });\n this.collection.add(new_model);\n var upload_row = new _collectionRow2.default(this, { model: new_model });\n this.$(\".upload-table > tbody:first\").append(upload_row.$el);\n this._updateScreen();\n upload_row.render();\n },\n\n /** Progress */\n _eventProgress: function _eventProgress(index, percentage) {\n var it = this.collection.get(index);\n it.set(\"percentage\", percentage);\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(percentage, it.get(\"file_size\")));\n },\n\n /** Success */\n _eventSuccess: function _eventSuccess(index, message) {\n // var hdaId = message[\"outputs\"][0][\"id\"];\n var hids = _.pluck(message[\"outputs\"], \"hid\");\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"success\", hids: hids });\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(100, it.get(\"file_size\")));\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.success++;\n this._updateScreen();\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Error */\n _eventError: function _eventError(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"error\", info: message });\n this.ui_button.model.set({\n percentage: this._uploadPercentage(100, it.get(\"file_size\")),\n status: \"danger\"\n });\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.error++;\n this._updateScreen();\n },\n\n /** Queue is done */\n _eventComplete: function _eventComplete() {\n this.collection.each(function (model) {\n model.get(\"status\") == \"queued\" && model.set(\"status\", \"init\");\n });\n this.counter.running = 0;\n this._updateScreen();\n },\n\n _eventBuild: function _eventBuild() {\n var allHids = [];\n _.forEach(this.collection.models, function (upload) {\n allHids.push.apply(allHids, upload.get(\"hids\"));\n });\n var models = _.map(allHids, function (hid) {\n return Galaxy.currHistoryPanel.collection.getByHid(hid);\n });\n var selection = new Galaxy.currHistoryPanel.collection.constructor(models);\n // I'm building the selection wrong because I need to set this historyId directly.\n selection.historyId = Galaxy.currHistoryPanel.collection.historyId;\n Galaxy.currHistoryPanel.buildCollection(this.collectionType, selection, true);\n this.counter.running = 0;\n this._updateScreen();\n this._eventReset();\n this.app.modal.hide();\n },\n\n /** Remove model from upload list */\n _eventRemove: function _eventRemove(model) {\n var status = model.get(\"status\");\n if (status == \"success\") {\n this.counter.success--;\n } else if (status == \"error\") {\n this.counter.error--;\n } else {\n this.counter.announce--;\n }\n this.uploadbox.remove(model.id);\n this._updateScreen();\n },\n\n //\n // events triggered by this view\n //\n\n /** Show/hide ftp popup */\n _eventFtp: function _eventFtp() {\n if (!this.ftp.visible) {\n this.ftp.empty();\n var self = this;\n this.ftp.append(new _uploadFtp2.default({\n collection: this.collection,\n ftp_upload_site: this.ftp_upload_site,\n onadd: function onadd(ftp_file) {\n return self.uploadbox.add([{\n mode: \"ftp\",\n name: ftp_file.path,\n size: ftp_file.size,\n path: ftp_file.path\n }]);\n },\n onremove: function onremove(model_index) {\n self.collection.remove(model_index);\n }\n }).$el);\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Create a new file */\n _eventCreate: function _eventCreate() {\n this.uploadbox.add([{ name: \"New File\", size: 0, mode: \"new\" }]);\n },\n\n /** Start upload process */\n _eventStart: function _eventStart() {\n if (this.counter.announce == 0 || this.counter.running > 0) {\n return;\n }\n var self = this;\n this.upload_size = 0;\n this.upload_completed = 0;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\") {\n model.set(\"status\", \"queued\");\n self.upload_size += model.get(\"file_size\");\n }\n });\n this.ui_button.model.set({ percentage: 0, status: \"success\" });\n this.counter.running = this.counter.announce;\n this.history_id = this.app.currentHistory();\n this.uploadbox.start();\n this._updateScreen();\n },\n\n /** Pause upload process */\n _eventStop: function _eventStop() {\n if (this.counter.running > 0) {\n this.ui_button.model.set(\"status\", \"info\");\n $(\".upload-top-info\").html(\"Queue will pause after completing the current file...\");\n this.uploadbox.stop();\n }\n },\n\n /** Remove all */\n _eventReset: function _eventReset() {\n if (this.counter.running == 0) {\n this.collection.reset();\n this.counter.reset();\n this.uploadbox.reset();\n this.select_extension.value(this.options.default_extension);\n this.select_genome.value(this.options.default_genome);\n this.ui_button.model.set(\"percentage\", 0);\n this._updateScreen();\n }\n },\n\n /** Update extension for all models */\n updateExtension: function updateExtension(extension, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"extension\") == self.options.default_extension || !defaults_only)) {\n model.set(\"extension\", extension);\n }\n });\n },\n\n /** Update collection type */\n updateCollectionType: function updateCollectionType(collectionType) {\n var self = this;\n this.collectionType = collectionType;\n },\n\n /** Update genome for all models */\n updateGenome: function updateGenome(genome, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"genome\") == self.options.default_genome || !defaults_only)) {\n model.set(\"genome\", genome);\n }\n });\n },\n\n /** Set screen */\n _updateScreen: function _updateScreen() {\n var message = \"\";\n if (this.counter.announce == 0) {\n if (this.uploadbox.compatible()) {\n message = \" \";\n } else {\n message = \"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.\";\n }\n } else {\n if (this.counter.running == 0) {\n message = \"You added \" + this.counter.announce + \" file(s) to the queue. Add more files or click 'Start' to proceed.\";\n } else {\n message = \"Please wait...\" + this.counter.announce + \" out of \" + this.counter.running + \" remaining.\";\n }\n }\n this.$(\".upload-top-info\").html(message);\n var enable_reset = this.counter.running == 0 && this.counter.announce + this.counter.success + this.counter.error > 0;\n var enable_start = this.counter.running == 0 && this.counter.announce > 0;\n var enable_build = this.counter.running == 0 && this.counter.announce == 0 && this.counter.success > 0 && this.counter.error == 0;\n var enable_sources = this.counter.running == 0;\n var show_table = this.counter.announce + this.counter.success + this.counter.error > 0;\n this.btnReset[enable_reset ? \"enable\" : \"disable\"]();\n this.btnStart[enable_start ? \"enable\" : \"disable\"]();\n this.btnStart.$el[enable_start ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnBuild[enable_build ? \"enable\" : \"disable\"]();\n this.btnBuild.$el[enable_build ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnStop[this.counter.running > 0 ? \"enable\" : \"disable\"]();\n this.btnLocal[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp[enable_sources ? \"enable\" : \"disable\"]();\n this.btnCreate[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp.$el[this.ftp_upload_site ? \"show\" : \"hide\"]();\n this.$(\".upload-table\")[show_table ? \"show\" : \"hide\"]();\n this.$(\".upload-helper\")[show_table ? \"hide\" : \"show\"]();\n },\n\n /** Calculate percentage of all queued uploads */\n _uploadPercentage: function _uploadPercentage(percentage, size) {\n return (this.upload_completed + percentage * size) / this.upload_size;\n },\n\n /** Template */\n _template: function _template() {\n return '
' + '
' + '
' + \"
\" + '
' + '
Drop files here
' + '
' + \"\" + \"
\" + \"
Name
\" + \"
Size
\" + \"
Status
\" + \"
\" + \"
\" + \"\" + \"\" + \"
\" + \"
\" + '\" + '
' + \"
\";\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 147 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _uploadSettings = __webpack_require__(31);\n\nvar _uploadSettings2 = _interopRequireDefault(_uploadSettings);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-icon-button fa fa-trash-o\",\n queued: \"upload-icon fa fa-spinner fa-spin\",\n running: \"upload-icon fa fa-spinner fa-spin\",\n success: \"upload-icon-button fa fa-check\",\n error: \"upload-icon-button fa fa-exclamation-triangle\"\n },\n\n initialize: function initialize(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template(options.model));\n this.$mode = this.$(\".upload-mode\");\n this.$title = this.$(\".upload-title-extended\");\n this.$text = this.$(\".upload-text\");\n this.$size = this.$(\".upload-size\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$symbol = this.$(\".upload-symbol\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // append popup to settings icon\n this.settings = new _uiPopover2.default.View({\n title: \"Upload configuration\",\n container: this.$(\".upload-settings\"),\n placement: \"bottom\"\n });\n\n // identify default genome and extension values\n var default_genome = this.app.select_genome.value();\n var default_extension = this.app.select_extension.value();\n\n // handle click event\n this.$symbol.on(\"click\", function () {\n self._removeRow();\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", function (e) {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", function () {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", function () {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", function () {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:file_size\", function () {\n self._refreshFileSize();\n });\n this.listenTo(this.model, \"remove\", function () {\n self.remove();\n });\n this.app.collection.on(\"reset\", function () {\n self.remove();\n });\n },\n\n render: function render() {\n var options = this.model.attributes;\n this.$title.html(_.escape(options.file_name));\n this.$size.html(_utils2.default.bytesToString(options.file_size));\n this.$mode.removeClass().addClass(\"upload-mode\").addClass(\"text-primary\");\n if (options.file_mode == \"new\") {\n this.$text.css({\n width: this.$el.width() - 16 + \"px\",\n top: this.$el.height() - 8 + \"px\"\n }).show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$mode.addClass(\"fa fa-edit\");\n } else if (options.file_mode == \"local\") {\n this.$mode.addClass(\"fa fa-laptop\");\n } else if (options.file_mode == \"ftp\") {\n this.$mode.addClass(\"fa fa-folder-open-o\");\n }\n },\n\n /** Refresh info text */\n _refreshInfo: function _refreshInfo() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(\"Failed: \" + info).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage status */\n _refreshPercentage: function _refreshPercentage() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n this.$progress_bar.css({ width: percentage + \"%\" });\n this.$percentage.html(percentage != 100 ? percentage + \"%\" : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function _refreshStatus() {\n var status = this.model.get(\"status\");\n this.$symbol.removeClass().addClass(\"upload-symbol\").addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status == \"init\");\n var enabled = this.model.get(\"enabled\");\n this.$text_content.attr(\"disabled\", !enabled);\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.$info_progress.hide();\n }\n },\n\n /** Refresh file size */\n _refreshFileSize: function _refreshFileSize() {\n this.$size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Remove row */\n _removeRow: function _removeRow() {\n if ([\"init\", \"success\", \"error\"].indexOf(this.model.get(\"status\")) !== -1) {\n this.app.collection.remove(this.model);\n }\n },\n\n /** Attach file info popup */\n _showSettings: function _showSettings() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new _uploadSettings2.default(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** View template */\n _template: function _template(options) {\n return \"
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
\";\n }\n}); /** Renders the collection uploader rows */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 148 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = {\n tool: \"fa-wrench\",\n data_input: \"fa-file-o\",\n data_collection_input: \"fa-folder-o\",\n subworkflow: \"fa-sitemap fa-rotate-270\",\n pause: \"fa-pause\"\n};\n\n/***/ }),\n/* 149 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _optionsMenu = __webpack_require__(150);\n\nvar _optionsMenu2 = _interopRequireDefault(_optionsMenu);\n\nvar _historyViewEditCurrent = __webpack_require__(151);\n\nvar _historyViewEditCurrent2 = _interopRequireDefault(_historyViewEditCurrent);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** the right hand panel in the analysis page that shows the current history */\nvar HistoryPanel = Backbone.View.extend({\n initialize: function initialize(page, options) {\n var self = this;\n this.userIsAnonymous = Galaxy.user.isAnonymous();\n this.allow_user_dataset_purge = options.config.allow_user_dataset_purge;\n this.root = options.root;\n\n // view of the current history\n this.historyView = new _historyViewEditCurrent2.default.CurrentHistoryView({\n className: _historyViewEditCurrent2.default.CurrentHistoryView.prototype.className + \" middle\",\n purgeAllowed: this.allow_user_dataset_purge,\n linkTarget: \"galaxy_main\"\n });\n\n // add history panel to Galaxy object\n Galaxy.currHistoryPanel = this.historyView;\n Galaxy.currHistoryPanel.listenToGalaxy(Galaxy);\n\n // build buttons\n this.buttonRefresh = new _uiMisc2.default.ButtonLink({\n id: \"history-refresh-button\",\n title: \"Refresh history\",\n cls: \"panel-header-button\",\n icon: \"fa fa-refresh\",\n onclick: function onclick() {\n self.historyView.loadCurrentHistory();\n }\n });\n this.buttonOptions = new _uiMisc2.default.ButtonLink({\n id: \"history-options-button\",\n title: \"History options\",\n cls: \"panel-header-button\",\n target: \"galaxy_main\",\n icon: \"fa fa-cog\",\n href: this.root + \"root/history_options\"\n });\n this.buttonViewMulti = new _uiMisc2.default.ButtonLink({\n id: \"history-view-multi-button\",\n title: \"View all histories\",\n cls: \"panel-header-button\",\n icon: \"fa fa-columns\",\n href: this.root + \"history/view_multiple\"\n });\n\n // define components\n this.model = new Backbone.Model({\n cls: \"history-right-panel\",\n title: (0, _localization2.default)(\"History\"),\n buttons: [this.buttonRefresh, this.buttonOptions, this.buttonViewMulti]\n });\n\n // build body template and connect history view\n this.setElement(this._template());\n this.historyView.setElement(this.$el);\n this.historyView.connectToQuotaMeter(Galaxy.quotaMeter);\n this.historyView.loadCurrentHistory();\n\n // fetch to update the quota meter adding 'current' for any anon-user's id\n Galaxy.listenTo(this.historyView, \"history-size-change\", function () {\n Galaxy.user.fetch({\n url: Galaxy.user.urlRoot() + \"/\" + (Galaxy.user.id || \"current\")\n });\n });\n },\n\n render: function render() {\n this.optionsMenu = (0, _optionsMenu2.default)(this.buttonOptions.$el, {\n anonymous: this.userIsAnonymous,\n purgeAllowed: this.allow_user_dataset_purge,\n root: this.root\n });\n this.buttonViewMulti.$el[!this.userIsAnonymous ? \"show\" : \"hide\"]();\n },\n\n /** add history view div */\n _template: function _template(data) {\n return [''].join(\"\");\n },\n\n toString: function toString() {\n return \"historyPanel\";\n }\n});\n\nexports.default = HistoryPanel;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 150 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function($, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _popupMenu = __webpack_require__(27);\n\nvar _popupMenu2 = _interopRequireDefault(_popupMenu);\n\nvar _copyDialog = __webpack_require__(78);\n\nvar _copyDialog2 = _interopRequireDefault(_copyDialog);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nvar _webhooks = __webpack_require__(17);\n\nvar _webhooks2 = _interopRequireDefault(_webhooks);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// ============================================================================\nvar menu = [{\n html: (0, _localization2.default)(\"History Lists\"),\n header: true\n}, {\n html: (0, _localization2.default)(\"Saved Histories\"),\n href: \"histories/list\",\n target: \"_top\"\n}, {\n html: (0, _localization2.default)(\"Histories Shared with Me\"),\n href: \"histories/list_shared\",\n target: \"_top\"\n}, {\n html: (0, _localization2.default)(\"Current History\"),\n header: true,\n anon: true\n}, {\n html: (0, _localization2.default)(\"Create New\"),\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.createNewHistory();\n }\n }\n}, {\n html: (0, _localization2.default)(\"Copy History\"),\n func: function func() {\n (0, _copyDialog2.default)(Galaxy.currHistoryPanel.model).done(function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n}, {\n html: (0, _localization2.default)(\"Share or Publish\"),\n href: \"history/sharing\"\n}, {\n html: (0, _localization2.default)(\"Show Structure\"),\n href: \"history/display_structured\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Extract Workflow\"),\n href: \"workflow/build_from_current_history\"\n}, {\n html: (0, _localization2.default)(\"Delete\"),\n anon: true,\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really delete the current history?\"))) {\n Galaxy.currHistoryPanel.model._delete().done(function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Delete Permanently\"),\n purge: true,\n anon: true,\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really delete the current history permanently? This cannot be undone.\"))) {\n Galaxy.currHistoryPanel.model.purge().done(function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Dataset Actions\"),\n header: true,\n anon: true\n}, {\n html: (0, _localization2.default)(\"Copy Datasets\"),\n href: \"dataset/copy_datasets\"\n}, {\n html: (0, _localization2.default)(\"Dataset Security\"),\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel && Galaxy.router) {\n Galaxy.router.push(\"/histories/permissions?id=\" + Galaxy.currHistoryPanel.model.id);\n }\n }\n}, {\n html: (0, _localization2.default)(\"Resume Paused Jobs\"),\n href: \"history/resume_paused_jobs?current=True\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Collapse Expanded Datasets\"),\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.collapseAll();\n }\n }\n}, {\n html: (0, _localization2.default)(\"Unhide Hidden Datasets\"),\n anon: true,\n func: function func() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really unhide all hidden datasets?\"))) {\n $.post(Galaxy.root + \"history/adjust_hidden\", { user_action: \"unhide\" }, function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Delete Hidden Datasets\"),\n anon: true,\n func: function func() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really delete all hidden datasets?\"))) {\n $.post(Galaxy.root + \"history/adjust_hidden\", { user_action: \"delete\" }, function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Purge Deleted Datasets\"),\n confirm: (0, _localization2.default)(\"Really delete all deleted datasets permanently? This cannot be undone.\"),\n href: \"history/purge_deleted_datasets\",\n purge: true,\n anon: true\n}, {\n html: (0, _localization2.default)(\"Downloads\"),\n header: true\n}, {\n html: (0, _localization2.default)(\"Export Tool Citations\"),\n href: \"history/citations\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Export History to File\"),\n href: \"history/export_archive?preview=True\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Other Actions\"),\n header: true\n}, {\n html: (0, _localization2.default)(\"Import from File\"),\n href: \"history/import_archive\"\n}];\n\n// Webhooks\n_webhooks2.default.add({\n url: \"api/webhooks/history-menu/all\",\n async: false, // (hypothetically) slows down the performance\n callback: function callback(webhooks) {\n var webhooks_menu = [];\n\n $.each(webhooks.models, function (index, model) {\n var webhook = model.toJSON();\n if (webhook.activate) {\n webhooks_menu.push({\n html: (0, _localization2.default)(webhook.config.title),\n // func: function() {},\n anon: true\n });\n }\n });\n\n if (webhooks_menu.length > 0) {\n webhooks_menu.unshift({\n html: (0, _localization2.default)(\"Webhooks\"),\n header: true\n });\n $.merge(menu, webhooks_menu);\n }\n }\n});\n\nfunction buildMenu(isAnon, purgeAllowed, urlRoot) {\n return _.clone(menu).filter(function (menuOption) {\n if (isAnon && !menuOption.anon) {\n return false;\n }\n if (!purgeAllowed && menuOption.purge) {\n return false;\n }\n\n //TODO:?? hard-coded galaxy_main\n if (menuOption.href) {\n menuOption.href = urlRoot + menuOption.href;\n menuOption.target = menuOption.target || \"galaxy_main\";\n }\n\n if (menuOption.confirm) {\n menuOption.func = function () {\n if (confirm(menuOption.confirm)) {\n galaxy_main.location = menuOption.href;\n }\n };\n }\n return true;\n });\n}\n\nvar create = function create($button, options) {\n options = options || {};\n var isAnon = options.anonymous === undefined ? true : options.anonymous;\n var purgeAllowed = options.purgeAllowed || false;\n var menu = buildMenu(isAnon, purgeAllowed, Galaxy.root);\n //console.debug( 'menu:', menu );\n return new _popupMenu2.default($button, menu);\n};\n\n// ============================================================================\nexports.default = create;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 151 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, $, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _historyModel = __webpack_require__(38);\n\nvar _historyModel2 = _interopRequireDefault(_historyModel);\n\nvar _historyViewEdit = __webpack_require__(153);\n\nvar _historyViewEdit2 = _interopRequireDefault(_historyViewEdit);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// ============================================================================\n/** session storage for history panel preferences (and to maintain state)\n */\nvar HistoryViewPrefs = _baseMvc2.default.SessionStorageModel.extend(\n/** @lends HistoryViewPrefs.prototype */{\n defaults: {\n /** should the tags editor be shown or hidden initially? */\n tagsEditorShown: false,\n /** should the annotation editor be shown or hidden initially? */\n annotationEditorShown: false,\n ///** what is the currently focused content (dataset or collection) in the current history?\n // * (the history panel will highlight and scroll to the focused content view)\n // */\n //focusedContentId : null\n /** Current scroll position */\n scrollPosition: 0\n },\n toString: function toString() {\n return \"HistoryViewPrefs(\" + JSON.stringify(this.toJSON()) + \")\";\n }\n});\n\n/** key string to store panel prefs (made accessible on class so you can access sessionStorage directly) */\nHistoryViewPrefs.storageKey = function storageKey() {\n return \"history-panel\";\n};\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = _historyViewEdit2.default.HistoryViewEdit;\n// used in root/index.mako\n/** @class View/Controller for the user's current history model as used in the history\n * panel (current right hand panel) of the analysis page.\n *\n * The only history panel that:\n * will poll for updates.\n * displays datasets in reverse hid order.\n */\nvar CurrentHistoryView = _super.extend(\n/** @lends CurrentHistoryView.prototype */{\n className: _super.prototype.className + \" current-history-panel\",\n\n /** override to use drilldown (and not foldout) for how collections are displayed */\n HDCAViewClass: _super.prototype.HDCAViewClass.extend({\n foldoutStyle: \"drilldown\"\n }),\n\n emptyMsg: [(0, _localization2.default)(\"This history is empty\"), \". \", (0, _localization2.default)(\"You can \"), '', (0, _localization2.default)(\"load your own data\"), \"\", (0, _localization2.default)(\" or \"), '', (0, _localization2.default)(\"get data from an external source\"), \"\"].join(\"\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events */\n initialize: function initialize(attributes) {\n attributes = attributes || {};\n\n // ---- persistent preferences\n /** maintain state / preferences over page loads */\n this.preferences = new HistoryViewPrefs(_.extend({\n id: HistoryViewPrefs.storageKey()\n }, _.pick(attributes, _.keys(HistoryViewPrefs.prototype.defaults))));\n\n _super.prototype.initialize.call(this, attributes);\n\n /** sub-views that will overlay this panel (collections) */\n this.panelStack = [];\n\n /** id of currently focused content */\n this.currentContentId = attributes.currentContentId || null;\n //NOTE: purposely not sent to localstorage since panel recreation roughly lines up with a reset of this value\n },\n\n /** Override to cache the current scroll position with a listener */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n\n var panel = this;\n // reset scroll position when there's a new history\n this.on(\"new-model\", function () {\n panel.preferences.set(\"scrollPosition\", 0);\n });\n },\n\n // ------------------------------------------------------------------------ loading history/item models\n // TODO: next three more appropriate moved to the app level\n /** (re-)loads the user's current history & contents w/ details */\n loadCurrentHistory: function loadCurrentHistory() {\n return this.loadHistory(null, {\n url: Galaxy.root + \"history/current_history_json\"\n });\n },\n\n /** loads a history & contents w/ details and makes them the current history */\n switchToHistory: function switchToHistory(historyId, attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", (0, _localization2.default)(\"You must be logged in to switch histories\"), (0, _localization2.default)(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(historyId, {\n url: Galaxy.root + \"history/set_as_current?id=\" + historyId\n });\n },\n\n /** creates a new history on the server and sets it as the user's current history */\n createNewHistory: function createNewHistory(attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", (0, _localization2.default)(\"You must be logged in to create histories\"), (0, _localization2.default)(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(null, {\n url: Galaxy.root + \"history/create_new_current\"\n });\n },\n\n /** release/free/shutdown old models and set up panel for new models */\n setModel: function setModel(model, attributes, render) {\n _super.prototype.setModel.call(this, model, attributes, render);\n if (this.model && this.model.id) {\n this.log(\"checking for updates\");\n this.model.checkForUpdates();\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ history/content event listening\n /** listening for history events */\n _setUpModelListeners: function _setUpModelListeners() {\n _super.prototype._setUpModelListeners.call(this);\n // re-broadcast any model change events so that listeners don't have to re-bind to each history\n return this.listenTo(this.model, {\n \"change:nice_size change:size\": function changeNice_sizeChangeSize() {\n this.trigger(\"history-size-change\", this, this.model, arguments);\n },\n \"change:id\": function changeId() {\n this.once(\"loading-done\", function () {\n this.model.checkForUpdates();\n });\n }\n });\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n _super.prototype._setUpCollectionListeners.call(this);\n // if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,\n // then: remove it from the collection if the panel is set to NOT show hidden datasets\n this.listenTo(this.collection, \"state:ready\", function (model, newState, oldState) {\n if (!model.get(\"visible\") && !this.collection.storage.includeHidden()) {\n this.removeItemView(model);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** override to add a handler to capture the scroll position when the parent scrolls */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n // console.log( '_setUpBehaviors', this.$scrollContainer( $where ).get(0), this.$list( $where ) );\n // we need to call this in _setUpBehaviors which is called after render since the $el\n // may not be attached to $el.parent and $scrollContainer() may not work\n var panel = this;\n _super.prototype._setUpBehaviors.call(panel, $where);\n\n // cache the handler to remove and re-add so we don't pile up the handlers\n if (!this._debouncedScrollCaptureHandler) {\n this._debouncedScrollCaptureHandler = _.debounce(function scrollCapture() {\n // cache the scroll position (only if visible)\n if (panel.$el.is(\":visible\")) {\n panel.preferences.set(\"scrollPosition\", $(this).scrollTop());\n }\n }, 40);\n }\n\n panel.$scrollContainer($where).off(\"scroll\", this._debouncedScrollCaptureHandler).on(\"scroll\", this._debouncedScrollCaptureHandler);\n return panel;\n },\n\n /** In this override, handle null models and move the search input to the top */\n _buildNewRender: function _buildNewRender() {\n if (!this.model) {\n return $();\n }\n var $newRender = _super.prototype._buildNewRender.call(this);\n $newRender.find(\".search\").prependTo($newRender.find(\"> .controls\"));\n this._renderQuotaMessage($newRender);\n return $newRender;\n },\n\n /** render the message displayed when a user is over quota and can't run jobs */\n _renderQuotaMessage: function _renderQuotaMessage($whereTo) {\n $whereTo = $whereTo || this.$el;\n return $(this.templates.quotaMsg({}, this)).prependTo($whereTo.find(\".messages\"));\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderTags: function _renderTags($where) {\n var panel = this;\n // render tags and show/hide based on preferences\n _super.prototype._renderTags.call(panel, $where);\n if (panel.preferences.get(\"tagsEditorShown\")) {\n panel.tagsEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(panel.tagsEditor, \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\", function (tagsEditor) {\n panel.preferences.set(\"tagsEditorShown\", tagsEditor.hidden);\n });\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderAnnotation: function _renderAnnotation($where) {\n var panel = this;\n // render annotation and show/hide based on preferences\n _super.prototype._renderAnnotation.call(panel, $where);\n if (panel.preferences.get(\"annotationEditorShown\")) {\n panel.annotationEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(panel.annotationEditor, \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\", function (annotationEditor) {\n panel.preferences.set(\"annotationEditorShown\", annotationEditor.hidden);\n });\n },\n\n /** Override to scroll to cached position (in prefs) after swapping */\n _swapNewRender: function _swapNewRender($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n var panel = this;\n _.delay(function () {\n var pos = panel.preferences.get(\"scrollPosition\");\n if (pos) {\n panel.scrollTo(pos, 0);\n }\n }, 10);\n //TODO: is this enough of a delay on larger histories?\n\n return this;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** Override to add the current-content highlight class to currentContentId's view */\n _attachItems: function _attachItems($whereTo) {\n _super.prototype._attachItems.call(this, $whereTo);\n var panel = this;\n if (panel.currentContentId) {\n panel._setCurrentContentById(panel.currentContentId);\n }\n return this;\n },\n\n /** Override to remove any drill down panels */\n addItemView: function addItemView(model, collection, options) {\n var view = _super.prototype.addItemView.call(this, model, collection, options);\n if (!view) {\n return view;\n }\n if (this.panelStack.length) {\n return this._collapseDrilldownPanel();\n }\n return view;\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n // use pub-sub to: handle drilldown expansion and collapse\n return panel.listenTo(view, {\n \"expanded:drilldown\": function expandedDrilldown(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function collapsedDrilldown(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n },\n\n /** display 'current content': add a visible highlight and store the id of a content item */\n setCurrentContent: function setCurrentContent(view) {\n this.$(\".history-content.current-content\").removeClass(\"current-content\");\n if (view) {\n view.$el.addClass(\"current-content\");\n this.currentContentId = view.model.id;\n } else {\n this.currentContentId = null;\n }\n },\n\n /** find the view with the id and then call setCurrentContent on it */\n _setCurrentContentById: function _setCurrentContentById(id) {\n var view = this.viewFromModelId(id) || null;\n this.setCurrentContent(view);\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function _expandDrilldownPanel(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$controls().add(this.$list()).hide();\n drilldown.parentName = this.model.get(\"name\");\n drilldown.delegateEvents().render().$el.appendTo(this.$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function _collapseDrilldownPanel(drilldown) {\n this.panelStack.pop();\n //TODO: MEM: free the panel\n this.$controls().add(this.$list()).show();\n },\n\n // ........................................................................ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n // the two links in the empty message\n \"click .uploader-link\": function clickUploaderLink(ev) {\n Galaxy.upload.show(ev);\n },\n \"click .get-data-link\": function clickGetDataLink(ev) {\n var $toolMenu = $(\".toolMenuContainer\");\n $toolMenu.parent().scrollTop(0);\n $toolMenu.find('span:contains(\"Get Data\")').click();\n }\n }),\n\n // ........................................................................ external objects/MVC\n listenToGalaxy: function listenToGalaxy(galaxy) {\n this.listenTo(galaxy, {\n // when the galaxy_main iframe is loaded with a new page,\n // compare the url to the following list and if there's a match\n // pull the id from url and indicate in the history view that\n // the dataset with that id is the 'current'ly active dataset\n \"center-frame:load\": function centerFrameLoad(data) {\n var pathToMatch = data.fullpath;\n var hdaId = null;\n var useToURLRegexMap = {\n display: /datasets\\/([a-f0-9]+)\\/display/,\n edit: /datasets\\/([a-f0-9]+)\\/edit/,\n report_error: /dataset\\/errors\\?id=([a-f0-9]+)/,\n rerun: /tool_runner\\/rerun\\?id=([a-f0-9]+)/,\n show_params: /datasets\\/([a-f0-9]+)\\/show_params/\n // no great way to do this here? (leave it in the dataset event handlers above?)\n // 'visualization' : 'visualization',\n };\n _.find(useToURLRegexMap, function (regex, use) {\n // grab the more specific match result (1), save, and use it as the find flag\n hdaId = _.result(pathToMatch.match(regex), 1);\n return hdaId;\n });\n // need to type mangle to go from web route to history contents\n this._setCurrentContentById(hdaId ? \"dataset-\" + hdaId : null);\n },\n // when the center panel is given a new view, clear the current indicator\n \"center-panel:load\": function centerPanelLoad(view) {\n this._setCurrentContentById();\n }\n });\n },\n\n //TODO: remove quota meter from panel and remove this\n /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */\n connectToQuotaMeter: function connectToQuotaMeter(quotaMeter) {\n if (!quotaMeter) {\n return this;\n }\n // show/hide the 'over quota message' in the history when the meter tells it to\n this.listenTo(quotaMeter, \"quota:over\", this.showQuotaMessage);\n this.listenTo(quotaMeter, \"quota:under\", this.hideQuotaMessage);\n\n // having to add this to handle re-render of hview while overquota (the above do not fire)\n this.on(\"rendered rendered:initial\", function () {\n if (quotaMeter && quotaMeter.isOverQuota()) {\n this.showQuotaMessage();\n }\n });\n return this;\n },\n\n /** Override to preserve the quota message */\n clearMessages: function clearMessages(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target = $target.not(\".quota-message\");\n $target.fadeOut(this.fxSpeed, function () {\n $(this).remove();\n });\n return this;\n },\n\n /** Show the over quota message (which happens to be in the history panel).\n */\n showQuotaMessage: function showQuotaMessage() {\n var $msg = this.$(\".quota-message\");\n if ($msg.is(\":hidden\")) {\n $msg.slideDown(this.fxSpeed);\n }\n },\n\n /** Hide the over quota message (which happens to be in the history panel).\n */\n hideQuotaMessage: function hideQuotaMessage() {\n var $msg = this.$(\".quota-message\");\n if (!$msg.is(\":hidden\")) {\n $msg.slideUp(this.fxSpeed);\n }\n },\n\n // ........................................................................ options menu\n //TODO: remove to batch\n /** unhide any hidden datasets */\n unhideHidden: function unhideHidden() {\n var self = this;\n if (confirm((0, _localization2.default)(\"Really unhide all hidden datasets?\"))) {\n // get all hidden, regardless of deleted/purged\n return self.model.contents._filterAndUpdate({ visible: false, deleted: \"\", purged: \"\" }, { visible: true }).done(function () {\n // TODO: would be better to render these as they're unhidden instead of all at once\n if (!self.model.contents.includeHidden) {\n self.renderItems();\n }\n });\n }\n return jQuery.when();\n },\n\n /** delete any hidden datasets */\n deleteHidden: function deleteHidden() {\n var self = this;\n if (confirm((0, _localization2.default)(\"Really delete all hidden datasets?\"))) {\n return self.model.contents._filterAndUpdate(\n // get all hidden, regardless of deleted/purged\n { visible: false, deleted: \"\", purged: \"\" },\n // both delete *and* unhide them\n { deleted: true, visible: true });\n }\n return jQuery.when();\n },\n\n /** Return a string rep of the history */\n toString: function toString() {\n return \"CurrentHistoryView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nCurrentHistoryView.prototype.templates = function () {\n var quotaMsgTemplate = _baseMvc2.default.wrapTemplate(['
', (0, _localization2.default)(\"You are over your disk quota\"), \". \", (0, _localization2.default)(\"Tool execution is on hold until your disk usage drops below your allocated quota\"), \".\", \"
\"], \"history\");\n return _.extend(_.clone(_super.prototype.templates), {\n quotaMsg: quotaMsgTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n CurrentHistoryView: CurrentHistoryView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 152 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if (\"value\" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n//ASSUMES: jquery\n//=============================================================================\n/** @class AjaxQueue\n * Class that allows queueing functions that return jQuery promises (such\n * as ajax calls). Each function waits for the previous to complete before\n * being called\n *\n * @constructor accepts a list of functions and automatically begins\n * processing them\n */\nvar AjaxQueue = function () {\n function AjaxQueue(initialFunctions) {\n _classCallCheck(this, AjaxQueue);\n\n /** the main deferred for the entire queue - note: also sends notifications of progress */\n this.deferred = jQuery.Deferred();\n /** the queue array of functions */\n this.queue = [];\n /** cache the response from each deferred call - error or success */\n this.responses = [];\n /** total number of fn's to process */\n this.numToProcess = 0;\n /** is the queue processing/waiting for any calls to return? */\n this.running = false;\n\n this.init(initialFunctions || []);\n this.start();\n }\n\n /** add all fns in initialFunctions (if any) to the queue */\n\n\n _createClass(AjaxQueue, [{\n key: \"init\",\n value: function init(initialFunctions) {\n var _this = this;\n\n initialFunctions.forEach(function (fn) {\n _this.add(fn);\n });\n }\n }, {\n key: \"add\",\n value: function add(fn) {\n var _this2 = this;\n\n var index = this.queue.length;\n this.numToProcess += 1;\n\n this.queue.push(function () {\n var fnIndex = index;\n var xhr = fn();\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(function (response) {\n _this2.deferred.notify({\n curr: fnIndex,\n total: _this2.numToProcess,\n response: response\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(function (response) {\n _this2.responses.push(response);\n if (_this2.queue.length) {\n _this2.queue.shift()();\n } else {\n _this2.stop();\n }\n });\n });\n return this;\n }\n }, {\n key: \"start\",\n value: function start() {\n if (this.queue.length) {\n this.running = true;\n this.queue.shift()();\n }\n return this;\n }\n\n /** stop the queue\n * @param {boolean} causeFail cause an error/fail on the main deferred\n * @param {String} msg message to send when rejecting the main deferred\n */\n\n }, {\n key: \"stop\",\n value: function stop(causeFail, msg) {\n //TODO: doesn't abort current call\n this.running = false;\n this.queue = [];\n if (causeFail) {\n //TODO: spliced args instead\n this.deferred.reject(msg);\n } else {\n this.deferred.resolve(this.responses);\n }\n this.numToProcess = 0;\n this.deferred = jQuery.Deferred();\n return this;\n }\n\n // only a handful of the deferred interface for now - possible YAGNI\n /** implement done from the jq deferred interface */\n\n }, {\n key: \"done\",\n value: function done(fn) {\n return this.deferred.done(fn);\n }\n\n /** implement fail from the jq deferred interface */\n\n }, {\n key: \"fail\",\n value: function fail(fn) {\n return this.deferred.fail(fn);\n }\n\n /** implement always from the jq deferred interface */\n\n }, {\n key: \"always\",\n value: function always(fn) {\n return this.deferred.always(fn);\n }\n\n /** implement progress from the jq deferred interface */\n\n }, {\n key: \"progress\",\n value: function progress(fn) {\n return this.deferred.progress(fn);\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n\n }], [{\n key: \"create\",\n value: function create(initialFunctions) {\n return new AjaxQueue(initialFunctions).deferred;\n }\n }]);\n\n return AjaxQueue;\n}();\n\n//=============================================================================\n/** @class NamedAjaxQueue\n * @augments AjaxQueue\n * Allows associating a name with a deferring fn and prevents adding deferring\n * fns if the name has already been used. Useful to prevent build up of duplicate\n * async calls.\n * Both the array initialFunctions sent to constructor and any added later with\n * add() should be objects (NOT functions) of the form:\n * { name: some unique id,\n * fn: the deferring fn or ajax call }\n */\n\n\nvar NamedAjaxQueue = function (_AjaxQueue) {\n _inherits(NamedAjaxQueue, _AjaxQueue);\n\n function NamedAjaxQueue(initialFunctions) {\n _classCallCheck(this, NamedAjaxQueue);\n\n var _this3 = _possibleConstructorReturn(this, (NamedAjaxQueue.__proto__ || Object.getPrototypeOf(NamedAjaxQueue)).call(this, initialFunctions));\n\n _this3.names = {};\n return _this3;\n }\n\n /** add the obj.fn to the queue if obj.name hasn't been used before */\n\n\n _createClass(NamedAjaxQueue, [{\n key: \"add\",\n value: function add(obj) {\n if (!(obj.hasOwnProperty(\"name\") && obj.hasOwnProperty(\"fn\"))) {\n throw new Error(\"NamedAjaxQueue.add requires an object with both \\\"name\\\" and \\\"fn\\\": \" + JSON.stringify(obj));\n }\n if (this.names.hasOwnProperty(obj.name)) {\n //console.warn( 'name has been used:', obj.name );\n return;\n }\n this.names[obj.name] = true;\n return _get(NamedAjaxQueue.prototype.__proto__ || Object.getPrototypeOf(NamedAjaxQueue.prototype), \"add\", this).call(this, obj.fn);\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this.names = {};\n return this;\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n\n }], [{\n key: \"create\",\n value: function create(initialFunctions) {\n return new NamedAjaxQueue(initialFunctions).deferred;\n }\n }]);\n\n return NamedAjaxQueue;\n}(AjaxQueue);\n\n//=============================================================================\n\n\nexports.default = {\n AjaxQueue: AjaxQueue,\n NamedAjaxQueue: NamedAjaxQueue\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n\n/***/ }),\n/* 153 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _historyView = __webpack_require__(154);\n\nvar _historyView2 = _interopRequireDefault(_historyView);\n\nvar _historyContents = __webpack_require__(39);\n\nvar _historyContents2 = _interopRequireDefault(_historyContents);\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _hdaModel = __webpack_require__(81);\n\nvar _hdaModel2 = _interopRequireDefault(_hdaModel);\n\nvar _hdaLiEdit = __webpack_require__(156);\n\nvar _hdaLiEdit2 = _interopRequireDefault(_hdaLiEdit);\n\nvar _hdcaLiEdit = __webpack_require__(157);\n\nvar _hdcaLiEdit2 = _interopRequireDefault(_hdcaLiEdit);\n\nvar _tag = __webpack_require__(22);\n\nvar _tag2 = _interopRequireDefault(_tag);\n\nvar _annotation = __webpack_require__(88);\n\nvar _annotation2 = _interopRequireDefault(_annotation);\n\nvar _listCollectionCreator = __webpack_require__(35);\n\nvar _listCollectionCreator2 = _interopRequireDefault(_listCollectionCreator);\n\nvar _pairCollectionCreator = __webpack_require__(160);\n\nvar _pairCollectionCreator2 = _interopRequireDefault(_pairCollectionCreator);\n\nvar _listOfPairsCollectionCreator = __webpack_require__(161);\n\nvar _listOfPairsCollectionCreator2 = _interopRequireDefault(_listOfPairsCollectionCreator);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _popupMenu = __webpack_require__(27);\n\nvar _popupMenu2 = _interopRequireDefault(_popupMenu);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(15);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = _historyView2.default.HistoryView;\n// base class for history-view-edit-current and used as-is in history/view.mako\n/** @class Editable View/Controller for the history model.\n *\n * Allows:\n * (everything HistoryView allows)\n * changing the name\n * displaying and editing tags and annotations\n * multi-selection and operations on mulitple content items\n */\nvar HistoryViewEdit = _super.extend(\n/** @lends HistoryViewEdit.prototype */{\n /** class to use for constructing the HistoryDatasetAssociation views */\n HDAViewClass: _hdaLiEdit2.default.HDAListItemEdit,\n /** class to use for constructing the HistoryDatasetCollectionAssociation views */\n HDCAViewClass: _hdcaLiEdit2.default.HDCAListItemEdit,\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes\n */\n initialize: function initialize(attributes) {\n attributes = attributes || {};\n _super.prototype.initialize.call(this, attributes);\n\n // ---- set up instance vars\n /** editor for tags - sub-view */\n this.tagsEditor = null;\n\n /** enable drag and drop - sub-view */\n this.dragItems = true;\n\n /** editor for annotations - sub-view */\n this.annotationEditor = null;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n // states/modes the panel can be in\n /** is the panel currently showing the dataset selection controls? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n },\n\n /** Override to handle history as drag-drop target */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n return this.on({\n \"droptarget:drop\": function droptargetDrop(ev, data) {\n // process whatever was dropped and re-hide the drop target\n this.dataDropped(data);\n this.dropTargetOff();\n },\n \"view:attached view:removed\": function viewAttachedViewRemoved() {\n this._renderCounts();\n },\n \"search:loading-progress\": this._renderSearchProgress,\n \"search:searching\": this._renderSearchFindings\n });\n },\n\n // ------------------------------------------------------------------------ listeners\n /** listening for history and HDA events */\n _setUpModelListeners: function _setUpModelListeners() {\n _super.prototype._setUpModelListeners.call(this);\n this.listenTo(this.model, \"change:size\", this.updateHistoryDiskSize);\n return this;\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n _super.prototype._setUpCollectionListeners.call(this);\n this.listenTo(this.collection, {\n \"change:deleted\": this._handleItemDeletedChange,\n \"change:visible\": this._handleItemVisibleChange,\n \"change:purged\": function changePurged(model) {\n // hafta get the new nice-size w/o the purged model\n this.model.fetch();\n },\n // loading indicators for deleted/hidden\n \"fetching-deleted\": function fetchingDeleted(collection) {\n this.$(\"> .controls .deleted-count\").html(\"\" + (0, _localization2.default)(\"loading...\") + \"\");\n },\n \"fetching-hidden\": function fetchingHidden(collection) {\n this.$(\"> .controls .hidden-count\").html(\"\" + (0, _localization2.default)(\"loading...\") + \"\");\n },\n \"fetching-deleted-done fetching-hidden-done\": this._renderCounts\n });\n return this;\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** In this override, add tag and annotation editors and a btn to toggle the selectors */\n _buildNewRender: function _buildNewRender() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = _super.prototype._buildNewRender.call(this);\n if (!this.model) {\n return $newRender;\n }\n\n if (Galaxy && Galaxy.user && Galaxy.user.id && Galaxy.user.id === this.model.get(\"user_id\")) {\n this._renderTags($newRender);\n this._renderAnnotation($newRender);\n }\n return $newRender;\n },\n\n /** Update the history size display (curr. upper right of panel). */\n updateHistoryDiskSize: function updateHistoryDiskSize() {\n this.$(\".history-size\").text(this.model.get(\"nice_size\"));\n },\n\n /** override to render counts when the items are rendered */\n renderItems: function renderItems($whereTo) {\n var views = _super.prototype.renderItems.call(this, $whereTo);\n if (!this.searchFor) {\n this._renderCounts($whereTo);\n } else {\n this._renderSearchFindings($whereTo);\n }\n return views;\n },\n\n /** override to show counts, what's deleted/hidden, and links to toggle those */\n _renderCounts: function _renderCounts($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.counts(this.model.toJSON(), this);\n return $whereTo.find(\"> .controls .subtitle\").html(html);\n },\n\n /** render the tags sub-view controller */\n _renderTags: function _renderTags($where) {\n var panel = this;\n this.tagsEditor = new _tag2.default.TagsEditor({\n model: this.model,\n el: $where.find(\".controls .tags-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // show hide sub-view tag editors when this is shown/hidden\n onshow: function onshow() {\n panel.toggleHDATagEditors(true, panel.fxSpeed);\n },\n onhide: function onhide() {\n panel.toggleHDATagEditors(false, panel.fxSpeed);\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit history tags\"),\n classes: \"history-tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n /** render the annotation sub-view controller */\n _renderAnnotation: function _renderAnnotation($where) {\n var panel = this;\n this.annotationEditor = new _annotation2.default.AnnotationEditor({\n model: this.model,\n el: $where.find(\".controls .annotation-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // show hide sub-view view annotation editors when this is shown/hidden\n onshow: function onshow() {\n panel.toggleHDAAnnotationEditors(true, panel.fxSpeed);\n },\n onhide: function onhide() {\n panel.toggleHDAAnnotationEditors(false, panel.fxSpeed);\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit history annotation\"),\n classes: \"history-annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n\n /** Set up HistoryViewEdit js/widget behaviours\n * In this override, make the name editable\n */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n _super.prototype._setUpBehaviors.call(this, $where);\n if (!this.model) {\n return;\n }\n\n // anon users shouldn't have access to any of the following\n if (!Galaxy.user || Galaxy.user.isAnonymous() || Galaxy.user.id !== this.model.get(\"user_id\")) {\n return;\n }\n\n var panel = this;\n var nameSelector = \"> .controls .name\";\n $where.find(nameSelector).attr(\"title\", (0, _localization2.default)(\"Click to rename history\")).tooltip({ placement: \"bottom\" }).make_text_editable({\n on_finish: function on_finish(newName) {\n var previousName = panel.model.get(\"name\");\n if (newName && newName !== previousName) {\n panel.$el.find(nameSelector).text(newName);\n panel.model.save({ name: newName }).fail(function () {\n panel.$el.find(nameSelector).text(panel.model.previous(\"name\"));\n });\n } else {\n panel.$el.find(nameSelector).text(previousName);\n }\n }\n });\n },\n\n /** return a new popup menu for choosing a multi selection action\n * ajax calls made for multiple datasets are queued\n */\n multiselectActions: function multiselectActions() {\n var panel = this;\n\n var actions = [{\n html: (0, _localization2.default)(\"Hide datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.hide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }, {\n html: (0, _localization2.default)(\"Unhide datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.unhide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }, {\n html: (0, _localization2.default)(\"Delete datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype[\"delete\"];\n panel.getSelectedModels().ajaxQueue(action);\n }\n }, {\n html: (0, _localization2.default)(\"Undelete datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.undelete;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }];\n\n if (panel.purgeAllowed) {\n actions.push({\n html: (0, _localization2.default)(\"Permanently delete datasets\"),\n func: function func() {\n if (confirm((0, _localization2.default)(\"This will permanently remove the data in your datasets. Are you sure?\"))) {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.purge;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }\n });\n }\n actions = actions.concat(panel._collectionActions());\n return actions;\n },\n\n /** */\n _collectionActions: function _collectionActions() {\n var panel = this;\n return [{\n html: (0, _localization2.default)(\"Build Dataset List\"),\n func: function func() {\n panel.buildCollection(\"list\");\n }\n },\n // TODO: Only show quick pair if two things selected.\n {\n html: (0, _localization2.default)(\"Build Dataset Pair\"),\n func: function func() {\n panel.buildCollection(\"paired\");\n }\n }, {\n html: (0, _localization2.default)(\"Build List of Dataset Pairs\"),\n func: function func() {\n panel.buildCollection(\"list:paired\");\n }\n }];\n },\n\n buildCollection: function buildCollection(collectionType, selection, hideSourceItems) {\n var panel = this;\n var selection = selection || panel.getSelectedModels();\n var hideSourceItems = hideSourceItems || false;\n var createFunc;\n if (collectionType == \"list\") {\n createFunc = _listCollectionCreator2.default.createListCollection;\n } else if (collectionType == \"paired\") {\n createFunc = _pairCollectionCreator2.default.createPairCollection;\n } else if (collectionType == \"list:paired\") {\n createFunc = _listOfPairsCollectionCreator2.default.createListOfPairsCollection;\n } else {\n console.warn(\"Unknown collectionType encountered \" + collectionType);\n }\n createFunc(selection, hideSourceItems).done(function () {\n panel.model.refresh();\n });\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, add purgeAllowed and whether tags/annotation editors should be shown */\n _getItemViewOptions: function _getItemViewOptions(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n _.extend(options, {\n purgeAllowed: this.purgeAllowed,\n tagsEditorShown: this.tagsEditor && !this.tagsEditor.hidden,\n annotationEditorShown: this.annotationEditor && !this.annotationEditor.hidden\n });\n return options;\n },\n\n /** If this item is deleted and we're not showing deleted items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemDeletedChange: function _handleItemDeletedChange(itemModel) {\n if (itemModel.get(\"deleted\")) {\n this._handleItemDeletion(itemModel);\n } else {\n this._handleItemUndeletion(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemDeletion: function _handleItemDeletion(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeDeleted) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUndeletion: function _handleItemUndeletion(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted -= 1;\n if (!this.model.contents.includeDeleted) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** If this item is hidden and we're not showing hidden items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemVisibleChange: function _handleItemVisibleChange(itemModel) {\n if (itemModel.hidden()) {\n this._handleItemHidden(itemModel);\n } else {\n this._handleItemUnhidden(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemHidden: function _handleItemHidden(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeHidden) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUnhidden: function _handleItemUnhidden(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden -= 1;\n if (!this.model.contents.includeHidden) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** toggle the visibility of each content's tagsEditor applying all the args sent to this function */\n toggleHDATagEditors: function toggleHDATagEditors(showOrHide, speed) {\n _.each(this.views, function (view) {\n if (view.tagsEditor) {\n view.tagsEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n /** toggle the visibility of each content's annotationEditor applying all the args sent to this function */\n toggleHDAAnnotationEditors: function toggleHDAAnnotationEditors(showOrHide, speed) {\n _.each(this.views, function (view) {\n if (view.annotationEditor) {\n view.annotationEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click .toggle-deleted-link\": function clickToggleDeletedLink(ev) {\n this.toggleShowDeleted();\n },\n \"click .toggle-hidden-link\": function clickToggleHiddenLink(ev) {\n this.toggleShowHidden();\n }\n }),\n\n // ------------------------------------------------------------------------ search\n _renderSearchProgress: function _renderSearchProgress(limit, offset) {\n var stop = limit + offset;\n return this.$(\"> .controls .subtitle\").html([\"\", (0, _localization2.default)(\"Searching \"), stop, \"/\", this.model.contentsShown(), \"\"].join(\"\"));\n },\n\n /** override to display number found in subtitle */\n _renderSearchFindings: function _renderSearchFindings($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.found(this.model.toJSON(), this);\n $whereTo.find(\"> .controls .subtitle\").html(html);\n return this;\n },\n\n // ------------------------------------------------------------------------ as drop target\n /** turn all the drag and drop handlers on and add some help text above the drop area */\n dropTargetOn: function dropTargetOn() {\n if (this.dropTarget) {\n return this;\n }\n this.dropTarget = true;\n\n //TODO: to init\n var dropHandlers = {\n dragenter: _.bind(this.dragenter, this),\n dragover: _.bind(this.dragover, this),\n dragleave: _.bind(this.dragleave, this),\n drop: _.bind(this.drop, this)\n };\n\n var $dropTarget = this._renderDropTarget();\n this.$list().before([this._renderDropTargetHelp(), $dropTarget]);\n for (var evName in dropHandlers) {\n if (dropHandlers.hasOwnProperty(evName)) {\n //console.debug( evName, dropHandlers[ evName ] );\n $dropTarget.on(evName, dropHandlers[evName]);\n }\n }\n return this;\n },\n\n /** render a box to serve as a 'drop here' area on the history */\n _renderDropTarget: function _renderDropTarget() {\n this.$(\".history-drop-target\").remove();\n return $(\"\").addClass(\"history-drop-target\");\n },\n\n /** tell the user how it works */\n _renderDropTargetHelp: function _renderDropTargetHelp() {\n this.$(\".history-drop-target-help\").remove();\n return $(\"\").addClass(\"history-drop-target-help\").text((0, _localization2.default)(\"Drag datasets here to copy them to the current history\"));\n },\n\n /** shut down drag and drop event handlers and remove drop target */\n dropTargetOff: function dropTargetOff() {\n if (!this.dropTarget) {\n return this;\n }\n //this.log( 'dropTargetOff' );\n this.dropTarget = false;\n var dropTarget = this.$(\".history-drop-target\").get(0);\n for (var evName in this._dropHandlers) {\n if (this._dropHandlers.hasOwnProperty(evName)) {\n dropTarget.off(evName, this._dropHandlers[evName]);\n }\n }\n this.$(\".history-drop-target\").remove();\n this.$(\".history-drop-target-help\").remove();\n return this;\n },\n /** toggle the target on/off */\n dropTargetToggle: function dropTargetToggle() {\n if (this.dropTarget) {\n this.dropTargetOff();\n } else {\n this.dropTargetOn();\n }\n return this;\n },\n\n dragenter: function dragenter(ev) {\n //console.debug( 'dragenter:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"2px solid black\");\n },\n dragover: function dragover(ev) {\n ev.preventDefault();\n ev.stopPropagation();\n },\n dragleave: function dragleave(ev) {\n //console.debug( 'dragleave:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"1px dashed black\");\n },\n /** when (text) is dropped try to parse as json and trigger an event */\n drop: function drop(ev) {\n ev.preventDefault();\n //ev.stopPropagation();\n\n var self = this;\n var dataTransfer = ev.originalEvent.dataTransfer;\n var data = dataTransfer.getData(\"text\");\n\n dataTransfer.dropEffect = \"move\";\n try {\n data = JSON.parse(data);\n } catch (err) {\n self.warn(\"error parsing JSON from drop:\", data);\n }\n\n self.trigger(\"droptarget:drop\", ev, data, self);\n return false;\n },\n\n /** handler that copies data into the contents */\n dataDropped: function dataDropped(data) {\n var self = this;\n // HDA: dropping will copy it to the history\n if (_.isObject(data) && data.model_class === \"HistoryDatasetAssociation\" && data.id) {\n if (self.contents.currentPage !== 0) {\n return self.contents.fetchPage(0).then(function () {\n return self.model.contents.copy(data.id);\n });\n }\n return self.model.contents.copy(data.id);\n }\n return jQuery.when();\n },\n\n // ........................................................................ misc\n /** Return a string rep of the history */\n toString: function toString() {\n return \"HistoryViewEdit(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryViewEdit.prototype.templates = function () {\n var countsTemplate = _baseMvc2.default.wrapTemplate([\"<% var shown = Math.max( view.views.length, history.contents_active.active ) %>\", \"<% if( shown ){ %>\", '', \"<%- shown %> \", (0, _localization2.default)(\"shown\"), \"\", \"<% } %>\", \"<% if( history.contents_active.deleted ){ %>\", '', \"<% if( view.model.contents.includeDeleted ){ %>\", '', (0, _localization2.default)(\"hide deleted\"), \"\", \"<% } else { %>\", \"<%- history.contents_active.deleted %> \", '', (0, _localization2.default)(\"deleted\"), \"\", \"<% } %>\", \"\", \"<% } %>\", \"<% if( history.contents_active.hidden ){ %>\", '', \"<% if( view.model.contents.includeHidden ){ %>\", '', (0, _localization2.default)(\"hide hidden\"), \"\", \"<% } else { %>\", \"<%- history.contents_active.hidden %> \", '', (0, _localization2.default)(\"hidden\"), \"\", \"<% } %>\", \"\", \"<% } %>\"], \"history\");\n\n var foundTemplate = _baseMvc2.default.wrapTemplate([(0, _localization2.default)(\"Found\"), \" <%- view.views.length %>, \", \"<% if( history.contents_active.deleted ){ %>\", \"<% if( view.model.contents.includeDeleted ){ %>\", '', (0, _localization2.default)(\"hide deleted\"), \", \", \"<% } else { %>\", '', (0, _localization2.default)(\"show deleted\"), \", \", \"<% } %>\", \"<% } %>\", \"<% if( history.contents_active.hidden ){ %>\", \"<% if( view.model.contents.includeHidden ){ %>\", '', (0, _localization2.default)(\"hide hidden\"), \"\", \"<% } else { %>\", '', (0, _localization2.default)(\"show hidden\"), \"\", \"<% } %>\", \"<% } %>\"], \"history\");\n\n return _.extend(_.clone(_super.prototype.templates), {\n counts: countsTemplate,\n found: foundTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n HistoryViewEdit: HistoryViewEdit\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 154 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listView = __webpack_require__(82);\n\nvar _listView2 = _interopRequireDefault(_listView);\n\nvar _historyModel = __webpack_require__(38);\n\nvar _historyModel2 = _interopRequireDefault(_historyModel);\n\nvar _historyContents = __webpack_require__(39);\n\nvar _historyContents2 = _interopRequireDefault(_historyContents);\n\nvar _historyPreferences = __webpack_require__(40);\n\nvar _historyPreferences2 = _interopRequireDefault(_historyPreferences);\n\nvar _hdaLi = __webpack_require__(84);\n\nvar _hdaLi2 = _interopRequireDefault(_hdaLi);\n\nvar _hdcaLi = __webpack_require__(85);\n\nvar _hdcaLi2 = _interopRequireDefault(_hdcaLi);\n\nvar _userModel = __webpack_require__(59);\n\nvar _userModel2 = _interopRequireDefault(_userModel);\n\nvar _errorModal = __webpack_require__(79);\n\nvar _errorModal2 = _interopRequireDefault(_errorModal);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(83);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a history model.\n * Allows:\n * changing the loaded history\n * displaying data, info, and download\n * tracking history attrs: size, tags, annotations, name, etc.\n * Does not allow:\n * changing the name\n */\nvar _super = _listView2.default.ModelListPanel;\nvar HistoryView = _super.extend(\n/** @lends HistoryView.prototype */{\n _logNamespace: \"history\",\n\n /** class to use for constructing the HDA views */\n HDAViewClass: _hdaLi2.default.HDAListItemView,\n /** class to use for constructing the HDCA views */\n HDCAViewClass: _hdcaLi2.default.HDCAListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: _historyContents2.default.HistoryContents,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n tagName: \"div\",\n className: _super.prototype.className + \" history-panel\",\n\n /** string to display when the collection is empty */\n emptyMsg: (0, _localization2.default)(\"This history is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: (0, _localization2.default)(\"No matching datasets found\"),\n /** string used for search placeholder */\n searchPlaceholder: (0, _localization2.default)(\"search datasets\"),\n\n /** @type {Number} ms to wait after history load to fetch/decorate hdcas with element_count */\n FETCH_COLLECTION_COUNTS_DELAY: 2000,\n\n // ......................................................................... SET UP\n /** Set up the view, bind listeners.\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function initialize(attributes) {\n _super.prototype.initialize.call(this, attributes);\n // ---- instance vars\n // control contents/behavior based on where (and in what context) the panel is being used\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n /** timeout id for detailed fetch of collection counts, etc... */\n this.detailedFetchTimeoutId = null;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function _createDefaultCollection() {\n // override\n return new this.collectionClass([], {\n history: this.model\n });\n },\n\n /** In this override, clear the update timer on the model */\n freeModel: function freeModel() {\n _super.prototype.freeModel.call(this);\n if (this.model) {\n this.model.clearUpdateTimeout();\n }\n this._clearDetailedFetchTimeout();\n return this;\n },\n\n /** clear the timeout and the cached timeout id */\n _clearDetailedFetchTimeout: function _clearDetailedFetchTimeout() {\n if (this.detailedFetchTimeoutId) {\n clearTimeout(this.detailedFetchTimeoutId);\n this.detailedFetchTimeoutId = null;\n }\n },\n\n /** create any event listeners for the panel\n * @fires: rendered:initial on the first render\n * @fires: empty-history when switching to a history with no contents or creating a new history\n */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n this.on({\n error: function error(model, xhr, options, msg, details) {\n this.errorHandler(model, xhr, options, msg, details);\n },\n \"loading-done\": function loadingDone() {\n var self = this;\n // after the initial load, decorate with more time consuming fields (like HDCA element_counts)\n self.detailedFetchTimeoutId = _.delay(function () {\n self.detailedFetchTimeoutId = null;\n self.model.contents.fetchCollectionCounts();\n }, self.FETCH_COLLECTION_COUNTS_DELAY);\n },\n \"views:ready view:attached view:removed\": function viewsReadyViewAttachedViewRemoved(view) {\n this._renderSelectButton();\n },\n \"view:attached\": function viewAttached(view) {\n this.scrollTo(0);\n }\n });\n // this.on( 'all', function(){ console.debug( arguments ); });\n },\n\n // ------------------------------------------------------------------------ loading history/hda models\n /** load the history with the given id then it's contents, sending ajax options to both */\n loadHistory: function loadHistory(historyId, options, contentsOptions) {\n contentsOptions = _.extend(contentsOptions || { silent: true });\n this.info(\"loadHistory:\", historyId, options, contentsOptions);\n var self = this;\n self.setModel(new _historyModel2.default.History({ id: historyId }));\n\n contentsOptions.silent = true;\n self.trigger(\"loading\");\n return self.model.fetchWithContents(options, contentsOptions).always(function () {\n self.render();\n self.trigger(\"loading-done\");\n });\n },\n\n /** convenience alias to the model. Updates the item list only (not the history) */\n refreshContents: function refreshContents(options) {\n if (this.model) {\n return this.model.refresh(options);\n }\n // may have callbacks - so return an empty promise\n return $.when();\n },\n\n /** Override to reset web storage when the id changes (since it needs the id) */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n _super.prototype._setUpCollectionListeners.call(this);\n return this.listenTo(this.collection, {\n // 'all' : function(){ console.log( this.collection + ':', arguments ); },\n \"fetching-more\": function fetchingMore() {\n this._toggleContentsLoadingIndicator(true);\n this.$emptyMessage().hide();\n },\n \"fetching-more-done\": function fetchingMoreDone() {\n this._toggleContentsLoadingIndicator(false);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function _showLoadingIndicator(msg, speed, callback) {\n var $indicator = $('
');\n this.$el.html($indicator.text(msg).slideDown(!_.isUndefined(speed) ? speed : this.fxSpeed));\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function _hideLoadingIndicator(speed) {\n // make speed a bit slower to compensate for slow rendering of up to 500 contents\n this.$(\".loading-indicator\").slideUp(!_.isUndefined(speed) ? speed : this.fxSpeed + 200, function () {\n $(this).remove();\n });\n },\n\n /** In this override, add a btn to toggle the selectors */\n _buildNewRender: function _buildNewRender() {\n var $newRender = _super.prototype._buildNewRender.call(this);\n this._renderSelectButton($newRender);\n return $newRender;\n },\n\n /** button for starting select mode */\n _renderSelectButton: function _renderSelectButton($where) {\n $where = $where || this.$el;\n // do not render selector option if no actions\n if (!this.multiselectActions().length) {\n return null;\n }\n // do not render (and remove even) if nothing to select\n if (!this.views.length) {\n this.hideSelectors();\n $where.find(\".controls .actions .show-selectors-btn\").remove();\n return null;\n }\n // don't bother rendering if there's one already\n var $existing = $where.find(\".controls .actions .show-selectors-btn\");\n if ($existing.length) {\n return $existing;\n }\n\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Operations on multiple datasets\"),\n classes: \"show-selectors-btn\",\n faIcon: \"fa-check-square-o\"\n }).prependTo($where.find(\".controls .actions\"));\n },\n\n /** override to avoid showing intial empty message using contents_active */\n _renderEmptyMessage: function _renderEmptyMessage($whereTo) {\n var self = this;\n var $emptyMsg = self.$emptyMessage($whereTo);\n\n var empty = self.model.get(\"contents_active\").active <= 0;\n if (empty) {\n return $emptyMsg.empty().append(self.emptyMsg).show();\n } else if (self.searchFor && self.model.contents.haveSearchDetails() && !self.views.length) {\n return $emptyMsg.empty().append(self.noneFoundMsg).show();\n }\n $emptyMsg.hide();\n return $();\n },\n\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function $scrollContainer($where) {\n // override or set via attributes.$scrollContainer\n return this.$list($where);\n },\n\n // ------------------------------------------------------------------------ subviews\n _toggleContentsLoadingIndicator: function _toggleContentsLoadingIndicator(show) {\n if (!show) {\n this.$list().find(\".contents-loading-indicator\").remove();\n } else {\n this.$list().html('
' + '
');\n }\n },\n\n /** override to render pagination also */\n renderItems: function renderItems($whereTo) {\n // console.log( this + '.renderItems-----------------', new Date() );\n $whereTo = $whereTo || this.$el;\n var self = this;\n var $list = self.$list($whereTo);\n\n // TODO: bootstrap hack to remove orphaned tooltips\n $(\".tooltip\").remove();\n\n $list.empty();\n self.views = [];\n\n var models = self._filterCollection();\n if (models.length) {\n self._renderPagination($whereTo);\n self.views = self._renderSomeItems(models, $list);\n } else {\n // TODO: consolidate with _renderPagination above by (???) passing in models/length?\n $whereTo.find(\"> .controls .list-pagination\").empty();\n }\n self._renderEmptyMessage($whereTo).toggle(!models.length);\n\n self.trigger(\"views:ready\", self.views);\n return self.views;\n },\n\n /** render pagination controls if not searching and contents says we're paginating */\n _renderPagination: function _renderPagination($whereTo) {\n var $paginationControls = $whereTo.find(\"> .controls .list-pagination\");\n if (this.searchFor || !this.model.contents.shouldPaginate()) return $paginationControls.empty();\n\n $paginationControls.html(this.templates.pagination({\n // pagination is 1-based for the user\n current: this.model.contents.currentPage + 1,\n last: this.model.contents.getLastPage() + 1\n }, this));\n $paginationControls.find(\"select.pages\").tooltip();\n return $paginationControls;\n },\n\n /** render a subset of the entire collection (client-side pagination) */\n _renderSomeItems: function _renderSomeItems(models, $list) {\n var self = this;\n var views = [];\n $list.append(models.map(function (m) {\n var view = self._createItemView(m);\n views.push(view);\n return self._renderItemView$el(view);\n }));\n return views;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** in this override, check if the contents would also display based on includeDeleted/hidden */\n _filterItem: function _filterItem(model) {\n var self = this;\n var contents = self.model.contents;\n return (contents.includeHidden || !model.hidden()) && (contents.includeDeleted || !model.isDeletedOrPurged()) && _super.prototype._filterItem.call(self, model);\n },\n\n /** In this override, since history contents are mixed,\n * get the appropo view class based on history_content_type\n */\n _getItemViewClass: function _getItemViewClass(model) {\n var contentType = model.get(\"history_content_type\");\n switch (contentType) {\n case \"dataset\":\n return this.HDAViewClass;\n case \"dataset_collection\":\n return this.HDCAViewClass;\n }\n throw new TypeError(\"Unknown history_content_type: \" + contentType);\n },\n\n /** in this override, add a linktarget, and expand if id is in web storage */\n _getItemViewOptions: function _getItemViewOptions(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n expanded: this.model.contents.storage.isExpanded(model.id),\n hasUser: this.model.ownedByCurrUser()\n });\n },\n\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n //TODO: send from content view: this.model.collection.storage.addExpanded\n // maintain a list of items whose bodies are expanded\n return panel.listenTo(view, {\n expanded: function expanded(v) {\n panel.model.contents.storage.addExpanded(v.model);\n },\n collapsed: function collapsed(v) {\n panel.model.contents.storage.removeExpanded(v.model);\n }\n });\n },\n\n /** override to remove expandedIds from webstorage */\n collapseAll: function collapseAll() {\n this.model.contents.storage.clearExpanded();\n _super.prototype.collapseAll.call(this);\n },\n\n // ------------------------------------------------------------------------ selection\n /** Override to correctly set the historyId of the new collection */\n getSelectedModels: function getSelectedModels() {\n var collection = _super.prototype.getSelectedModels.call(this);\n collection.historyId = this.collection.historyId;\n return collection;\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click > .controls .prev\": \"_clickPrevPage\",\n \"click > .controls .next\": \"_clickNextPage\",\n \"change > .controls .pages\": \"_changePageSelect\",\n // allow (error) messages to be clicked away\n \"click .messages [class$=message]\": \"clearMessages\"\n }),\n\n _clickPrevPage: function _clickPrevPage(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchPrevPage();\n },\n\n _clickNextPage: function _clickNextPage(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchNextPage();\n },\n\n _changePageSelect: function _changePageSelect(ev) {\n this.model.clearUpdateTimeout();\n var page = $(ev.currentTarget).val();\n this.model.contents.fetchPage(page);\n },\n\n /** Toggle and store the deleted visibility and re-render items\n * @returns {Boolean} new setting\n */\n toggleShowDeleted: function toggleShowDeleted(show, options) {\n show = show !== undefined ? show : !this.model.contents.includeDeleted;\n var self = this;\n var contents = self.model.contents;\n contents.setIncludeDeleted(show, options);\n self.trigger(\"show-deleted\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** Toggle and store whether to render explicity hidden contents\n * @returns {Boolean} new setting\n */\n toggleShowHidden: function toggleShowHidden(show, store, options) {\n // console.log( 'toggleShowHidden', show, store );\n show = show !== undefined ? show : !this.model.contents.includeHidden;\n var self = this;\n var contents = self.model.contents;\n contents.setIncludeHidden(show, options);\n self.trigger(\"show-hidden\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** On the first search, if there are no details - load them, then search */\n _firstSearch: function _firstSearch(searchFor) {\n var self = this;\n var inputSelector = \"> .controls .search-input\";\n this.log(\"onFirstSearch\", searchFor);\n\n // if the contents already have enough details to search, search and return now\n if (self.model.contents.haveSearchDetails()) {\n self.searchItems(searchFor);\n return;\n }\n\n // otherwise, load the details progressively here\n self.$(inputSelector).searchInput(\"toggle-loading\");\n // set this now so that only results will show during progress\n self.searchFor = searchFor;\n var xhr = self.model.contents.progressivelyFetchDetails({ silent: true }).progress(function (response, limit, offset) {\n self.renderItems();\n self.trigger(\"search:loading-progress\", limit, offset);\n }).always(function () {\n self.$el.find(inputSelector).searchInput(\"toggle-loading\");\n }).done(function () {\n self.searchItems(searchFor, \"force\");\n });\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function clearSearch(searchFor) {\n var self = this;\n if (!self.searchFor) return self;\n //self.log( 'onSearchClear', self );\n self.searchFor = \"\";\n self.trigger(\"search:clear\", self);\n self.$(\"> .controls .search-query\").val(\"\");\n // NOTE: silent + render prevents collection update event with merge only\n // - which causes an empty page due to event handler above\n self.model.contents.fetchCurrentPage({ silent: true }).done(function () {\n self.renderItems();\n });\n return self;\n },\n\n // ........................................................................ error handling\n /** Event handler for errors (from the panel, the history, or the history's contents)\n * Alternately use two strings for model and xhr to use custom message and title (respectively)\n * @param {Model or View} model the (Backbone) source of the error\n * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error\n * @param {Object} options the options map commonly used with bbone ajax\n */\n errorHandler: function errorHandler(model, xhr, options) {\n //TODO: to mixin or base model\n // interrupted ajax or no connection\n if (xhr && xhr.status === 0 && xhr.readyState === 0) {\n // return ERROR_MODAL.offlineErrorModal();\n // fail silently\n return;\n }\n // otherwise, leave something to report in the console\n this.error(model, xhr, options);\n // and feedback to a modal\n // if sent two strings (and possibly details as 'options'), use those as message and title\n if (_.isString(model) && _.isString(xhr)) {\n var message = model;\n var title = xhr;\n return _errorModal2.default.errorModal(message, title, options);\n }\n // bad gateway\n // TODO: possibly to global handler\n if (xhr && xhr.status === 502) {\n return _errorModal2.default.badGatewayErrorModal();\n }\n return _errorModal2.default.ajaxErrorModal(model, xhr, options);\n },\n\n /** Remove all messages from the panel. */\n clearMessages: function clearMessages(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target.fadeOut(this.fxSpeed, function () {\n $(this).remove();\n });\n return this;\n },\n\n // ........................................................................ scrolling\n /** Scrolls the panel to show the content sub-view with the given hid.\n * @param {Integer} hid the hid of item to scroll into view\n * @returns {HistoryView} the panel\n */\n scrollToHid: function scrollToHid(hid) {\n return this.scrollToItem(_.first(this.viewsWhereModel({ hid: hid })));\n },\n\n // ........................................................................ misc\n /** utility for adding -st, -nd, -rd, -th to numbers */\n ordinalIndicator: function ordinalIndicator(number) {\n var numStr = \"\" + number;\n switch (numStr.charAt(numStr.length - 1)) {\n case \"1\":\n return numStr + \"st\";\n case \"2\":\n return numStr + \"nd\";\n case \"3\":\n return numStr + \"rd\";\n default:\n return numStr + \"th\";\n }\n },\n\n /** Return a string rep of the history */\n toString: function toString() {\n return \"HistoryView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryView.prototype.templates = function () {\n var mainTemplate = _baseMvc2.default.wrapTemplate([\n // temp container\n \"
\", '', '
', '', \"
\"]);\n\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
\"].join(\"\")),\n\n /** help content */\n helpContent: _.template([\"
\", (0, _localization2.default)([\"Pair collections are permanent collections containing two datasets: one forward and one reverse. \", \"Often these are forward and reverse reads. The pair collections can be passed to tools and \", \"workflows in order to have analyses done on both datasets. This interface allows \", \"you to create a pair, name it, and swap which is forward and which reverse.\"].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)(['Click the \"Swap\" link to make your forward dataset the reverse ', \"and the reverse dataset forward.\"].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Click the \"Cancel\" button to exit the interface.'].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)(['Once your collection is complete, enter a name and ', 'click \"Create list\".'].join(\"\")), \"
\"].join(\"\")),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(['
', '
', '', \"<% if( _.size( problems ) ){ %>\", (0, _localization2.default)(\"The following selections could not be included due to problems\"), \"
<% _.each( problems, function( problem ){ %>\", \"
<%- problem.element.name %>: <%- problem.text %>
\", \"<% }); %>
\", \"<% } else if( _.size( elements ) === 0 ){ %>\", (0, _localization2.default)(\"No datasets were selected\"), \".\", \"<% } else if( _.size( elements ) === 1 ){ %>\", (0, _localization2.default)(\"Only one dataset was selected\"), \": <%- elements[0].name %>\", \"<% } else if( _.size( elements ) > 2 ){ %>\", (0, _localization2.default)(\"Too many datasets were selected\"), ': <%- _.pluck( elements, \"name\" ).join( \", \") %>', \"<% } %>\", \" \", (0, _localization2.default)(\"Two (and only two) elements are needed for the pair\"), \". \", (0, _localization2.default)(\"You may need to \"), '', (0, _localization2.default)(\"cancel\"), \" \", (0, _localization2.default)(\"and reselect new elements\"), \".\", \"\", \"
\", \"
\", '\"].join(\"\"))\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function toString() {\n return \"PairCollectionCreator\";\n }\n});\n\n//==============================================================================\n/** List collection flavor of collectionCreatorModal. */\nvar pairCollectionCreatorModal = function _pairCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = (0, _localization2.default)(\"Create a collection from a pair of datasets\");\n return _listCollectionCreator2.default.collectionCreatorModal(elements, options, PairCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a pair collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createPairCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = pairCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function creationFn(elements, name, hideSourceItems) {\n elements = [{ name: \"forward\", src: \"hda\", id: elements[0].id }, { name: \"reverse\", src: \"hda\", id: elements[1].id }];\n return contents.createHDCA(elements, \"paired\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexports.default = {\n PairCollectionCreator: PairCollectionCreator,\n pairCollectionCreatorModal: pairCollectionCreatorModal,\n createPairCollection: createPairCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 161 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, jQuery, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _levenshtein = __webpack_require__(162);\n\nvar _levenshtein2 = _interopRequireDefault(_levenshtein);\n\nvar _naturalSort = __webpack_require__(75);\n\nvar _naturalSort2 = _interopRequireDefault(_naturalSort);\n\nvar _baseCreator = __webpack_require__(74);\n\nvar _baseCreator2 = _interopRequireDefault(_baseCreator);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(76);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"collections\";\n/* ============================================================================\nTODO:\n\n\nPROGRAMMATICALLY:\ncurrPanel.once( 'rendered', function(){\n currPanel.showSelectors();\n currPanel.selectAll();\n _.last( currPanel.actionsPopup.options ).func();\n});\n\n============================================================================ */\n/** A view for paired datasets in the collections creator.\n */\nvar PairView = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n tagName: \"li\",\n className: \"dataset paired\",\n\n initialize: function initialize(attributes) {\n this.pair = attributes.pair || {};\n },\n\n template: _.template(['<%- pair.forward.name %>', '', '<%- pair.name %>', \"\", '<%- pair.reverse.name %>'].join(\"\")),\n\n render: function render() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el.attr(\"draggable\", true).data(\"pair\", this.pair).html(this.template({ pair: this.pair })).addClass(\"flex-column-container\").get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n return this;\n },\n\n events: {\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function _dragstart(ev) {\n ev.currentTarget.style.opacity = \"0.4\";\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.pair));\n\n this.$el.parent().trigger(\"pair.dragstart\", [this]);\n },\n\n /** dragging pairs for re-ordering */\n _dragend: function _dragend(ev) {\n ev.currentTarget.style.opacity = \"1.0\";\n this.$el.parent().trigger(\"pair.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function _sendToParent(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function toString() {\n return \"PairView(\" + this.pair.name + \")\";\n }\n});\n\n// ============================================================================\n/** returns an autopair function that uses the provided options.match function */\nfunction autoPairFnBuilder(options) {\n options = options || {};\n options.createPair = options.createPair || function _defaultCreatePair(params) {\n params = params || {};\n var a = params.listA.splice(params.indexA, 1)[0];\n var b = params.listB.splice(params.indexB, 1)[0];\n var aInBIndex = params.listB.indexOf(a);\n var bInAIndex = params.listA.indexOf(b);\n if (aInBIndex !== -1) {\n params.listB.splice(aInBIndex, 1);\n }\n if (bInAIndex !== -1) {\n params.listA.splice(bInAIndex, 1);\n }\n return this._pair(a, b, { silent: true });\n };\n // compile these here outside of the loop\n var _regexps = [];\n function getRegExps() {\n if (!_regexps.length) {\n _regexps = [new RegExp(this.filters[0]), new RegExp(this.filters[1])];\n }\n return _regexps;\n }\n // mangle params as needed\n options.preprocessMatch = options.preprocessMatch || function _defaultPreprocessMatch(params) {\n var regexps = getRegExps.call(this);\n return _.extend(params, {\n matchTo: params.matchTo.name.replace(regexps[0], \"\"),\n possible: params.possible.name.replace(regexps[1], \"\")\n });\n };\n\n return function _strategy(params) {\n this.debug(\"autopair _strategy ---------------------------\");\n params = params || {};\n var listA = params.listA;\n var listB = params.listB;\n var indexA = 0;\n var indexB;\n\n var bestMatch = {\n score: 0.0,\n index: null\n };\n\n var paired = [];\n //console.debug( 'params:', JSON.stringify( params, null, ' ' ) );\n this.debug(\"starting list lens:\", listA.length, listB.length);\n this.debug(\"bestMatch (starting):\", JSON.stringify(bestMatch, null, \" \"));\n\n while (indexA < listA.length) {\n var matchTo = listA[indexA];\n bestMatch.score = 0.0;\n\n for (indexB = 0; indexB < listB.length; indexB++) {\n var possible = listB[indexB];\n this.debug(indexA + \":\" + matchTo.name);\n this.debug(indexB + \":\" + possible.name);\n\n // no matching with self\n if (listA[indexA] !== listB[indexB]) {\n bestMatch = options.match.call(this, options.preprocessMatch.call(this, {\n matchTo: matchTo,\n possible: possible,\n index: indexB,\n bestMatch: bestMatch\n }));\n this.debug(\"bestMatch:\", JSON.stringify(bestMatch, null, \" \"));\n if (bestMatch.score === 1.0) {\n this.debug(\"breaking early due to perfect match\");\n break;\n }\n }\n }\n var scoreThreshold = options.scoreThreshold.call(this);\n this.debug(\"scoreThreshold:\", scoreThreshold);\n this.debug(\"bestMatch.score:\", bestMatch.score);\n\n if (bestMatch.score >= scoreThreshold) {\n //console.debug( 'autoPairFnBuilder.strategy', listA[ indexA ].name, listB[ bestMatch.index ].name );\n paired.push(options.createPair.call(this, {\n listA: listA,\n indexA: indexA,\n listB: listB,\n indexB: bestMatch.index\n }));\n //console.debug( 'list lens now:', listA.length, listB.length );\n } else {\n indexA += 1;\n }\n if (!listA.length || !listB.length) {\n return paired;\n }\n }\n this.debug(\"paired:\", JSON.stringify(paired, null, \" \"));\n this.debug(\"autopair _strategy ---------------------------\");\n return paired;\n };\n}\n\n// ============================================================================\n/** An interface for building collections of paired datasets.\n */\nvar PairedCollectionCreator = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseCreator2.default.CollectionCreatorMixin).extend({\n _logNamespace: logNamespace,\n\n className: \"list-of-pairs-collection-creator collection-creator flex-row-container\",\n\n /** set up initial options, instance vars, behaviors, and autopair (if set to do so) */\n initialize: function initialize(attributes) {\n this.metric(\"PairedCollectionCreator.initialize\", attributes);\n //this.debug( '-- PairedCollectionCreator:', attributes );\n\n attributes = _.defaults(attributes, {\n datasets: [],\n filters: this.DEFAULT_FILTERS,\n automaticallyPair: true,\n strategy: \"lcs\",\n matchPercentage: 0.9,\n twoPassAutopairing: true\n });\n\n /** unordered, original list */\n this.initialList = attributes.datasets;\n\n /** is this from a history? if so, what's its id? */\n this.historyId = attributes.historyId;\n\n /** which filters should be used initially? (String[2] or name in commonFilters) */\n this.filters = this.commonFilters[attributes.filters] || this.commonFilters[this.DEFAULT_FILTERS];\n if (_.isArray(attributes.filters)) {\n this.filters = attributes.filters;\n }\n\n /** try to auto pair the unpaired datasets on load? */\n this.automaticallyPair = attributes.automaticallyPair;\n\n /** what method to use for auto pairing (will be passed aggression level) */\n this.strategy = this.strategies[attributes.strategy] || this.strategies[this.DEFAULT_STRATEGY];\n if (_.isFunction(attributes.strategy)) {\n this.strategy = attributes.strategy;\n }\n\n /** distance/mismatch level allowed for autopairing */\n this.matchPercentage = attributes.matchPercentage;\n\n /** try to autopair using simple first, then this.strategy on the remainder */\n this.twoPassAutopairing = attributes.twoPassAutopairing;\n\n /** remove file extensions (\\.*) from created pair names? */\n this.removeExtensions = true;\n //this.removeExtensions = false;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.oncancel = attributes.oncancel;\n /** fn to call when the collection is created (scoped to this) */\n this.oncreate = attributes.oncreate;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.autoscrollDist = attributes.autoscrollDist || 24;\n\n /** is the unpaired panel shown? */\n this.unpairedPanelHidden = false;\n /** is the paired panel shown? */\n this.pairedPanelHidden = false;\n\n /** DOM elements currently being dragged */\n this.$dragging = null;\n\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n\n this._setUpCommonSettings(attributes);\n this._setUpBehaviors();\n this._dataSetUp();\n },\n\n /** map of common filter pairs by name */\n commonFilters: {\n illumina: [\"_1\", \"_2\"],\n Rs: [\"_R1\", \"_R2\"]\n },\n /** which commonFilter to use by default */\n DEFAULT_FILTERS: \"illumina\",\n\n /** map of name->fn for autopairing */\n strategies: {\n simple: \"autopairSimple\",\n lcs: \"autopairLCS\",\n levenshtein: \"autopairLevenshtein\"\n },\n /** default autopair strategy name */\n DEFAULT_STRATEGY: \"lcs\",\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data: cache initialList, sort, and autopair */\n _dataSetUp: function _dataSetUp() {\n //this.debug( '-- _dataSetUp' );\n\n this.paired = [];\n this.unpaired = [];\n\n this.selectedIds = [];\n\n // sort initial list, add ids if needed, and save new working copy to unpaired\n this._sortInitialList();\n this._ensureIds();\n this.unpaired = this.initialList.slice(0);\n\n if (this.automaticallyPair) {\n this.autoPair();\n this.once(\"rendered:initial\", function () {\n this.trigger(\"autopair\");\n });\n }\n },\n\n /** sort initial list */\n _sortInitialList: function _sortInitialList() {\n //this.debug( '-- _sortInitialList' );\n this._sortDatasetList(this.initialList);\n },\n\n /** sort a list of datasets */\n _sortDatasetList: function _sortDatasetList(list) {\n // currently only natural sort by name\n list.sort(function (a, b) {\n return (0, _naturalSort2.default)(a.name, b.name);\n });\n return list;\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureIds: function _ensureIds() {\n this.initialList.forEach(function (dataset) {\n if (!dataset.hasOwnProperty(\"id\")) {\n dataset.id = _.uniqueId();\n }\n });\n return this.initialList;\n },\n\n /** split initial list into two lists, those that pass forward filters & those passing reverse */\n _splitByFilters: function _splitByFilters() {\n var regexFilters = this.filters.map(function (stringFilter) {\n return new RegExp(stringFilter);\n });\n\n var split = [[], []];\n\n function _filter(unpaired, filter) {\n return filter.test(unpaired.name);\n //return dataset.name.indexOf( filter ) >= 0;\n }\n this.unpaired.forEach(function _filterEach(unpaired) {\n // 90% of the time this seems to work, but:\n //TODO: this treats *all* strings as regex which may confuse people - possibly check for // surrounding?\n // would need explanation in help as well\n regexFilters.forEach(function (filter, i) {\n if (_filter(unpaired, filter)) {\n split[i].push(unpaired);\n }\n });\n });\n return split;\n },\n\n /** add a dataset to the unpaired list in it's proper order */\n _addToUnpaired: function _addToUnpaired(dataset) {\n var _this = this;\n\n // currently, unpaired is natural sorted by name, use binary search to find insertion point\n var binSearchSortedIndex = function binSearchSortedIndex(low, hi) {\n if (low === hi) {\n return low;\n }\n\n var mid = Math.floor((hi - low) / 2) + low;\n\n var compared = (0, _naturalSort2.default)(dataset.name, _this.unpaired[mid].name);\n\n if (compared < 0) {\n return binSearchSortedIndex(low, mid);\n } else if (compared > 0) {\n return binSearchSortedIndex(mid + 1, hi);\n }\n // walk the equal to find the last\n while (_this.unpaired[mid] && _this.unpaired[mid].name === dataset.name) {\n mid++;\n }\n return mid;\n };\n\n this.unpaired.splice(binSearchSortedIndex(0, this.unpaired.length), 0, dataset);\n },\n\n // ------------------------------------------------------------------------ auto pairing\n /** two passes to automatically create pairs:\n * use both simpleAutoPair, then the fn mentioned in strategy\n */\n autoPair: function autoPair(strategy) {\n // split first using exact matching\n var split = this._splitByFilters();\n\n var paired = [];\n if (this.twoPassAutopairing) {\n paired = this.autopairSimple({\n listA: split[0],\n listB: split[1]\n });\n split = this._splitByFilters();\n }\n\n // uncomment to see printlns while running tests\n //this.debug = function(){ console.log.apply( console, arguments ); };\n\n // then try the remainder with something less strict\n strategy = strategy || this.strategy;\n split = this._splitByFilters();\n paired = paired.concat(this[strategy].call(this, {\n listA: split[0],\n listB: split[1]\n }));\n return paired;\n },\n\n /** autopair by exact match */\n autopairSimple: autoPairFnBuilder({\n scoreThreshold: function scoreThreshold() {\n return 0.6;\n },\n match: function _match(params) {\n params = params || {};\n if (params.matchTo === params.possible) {\n return {\n index: params.index,\n score: 1.0\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by levenshtein edit distance scoring */\n autopairLevenshtein: autoPairFnBuilder({\n scoreThreshold: function scoreThreshold() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var distance = (0, _levenshtein2.default)(params.matchTo, params.possible);\n\n var score = 1.0 - distance / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by longest common substrings scoring */\n autopairLCS: autoPairFnBuilder({\n scoreThreshold: function scoreThreshold() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var match = this._naiveStartingAndEndingLCS(params.matchTo, params.possible).length;\n\n var score = match / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** return the concat'd longest common prefix and suffix from two strings */\n _naiveStartingAndEndingLCS: function _naiveStartingAndEndingLCS(s1, s2) {\n var fwdLCS = \"\";\n var revLCS = \"\";\n var i = 0;\n var j = 0;\n while (i < s1.length && i < s2.length) {\n if (s1[i] !== s2[i]) {\n break;\n }\n fwdLCS += s1[i];\n i += 1;\n }\n if (i === s1.length) {\n return s1;\n }\n if (i === s2.length) {\n return s2;\n }\n\n i = s1.length - 1;\n j = s2.length - 1;\n while (i >= 0 && j >= 0) {\n if (s1[i] !== s2[j]) {\n break;\n }\n revLCS = [s1[i], revLCS].join(\"\");\n i -= 1;\n j -= 1;\n }\n return fwdLCS + revLCS;\n },\n\n // ------------------------------------------------------------------------ pairing / unpairing\n /** create a pair from fwd and rev, removing them from unpaired, and placing the new pair in paired */\n _pair: function _pair(fwd, rev, options) {\n options = options || {};\n this.debug(\"_pair:\", fwd, rev);\n var pair = this._createPair(fwd, rev, options.name);\n this.paired.push(pair);\n this.unpaired = _.without(this.unpaired, fwd, rev);\n if (!options.silent) {\n this.trigger(\"pair:new\", pair);\n }\n return pair;\n },\n\n /** create a pair Object from fwd and rev, adding the name attribute (will guess if not given) */\n _createPair: function _createPair(fwd, rev, name) {\n // ensure existance and don't pair something with itself\n if (!(fwd && rev) || fwd === rev) {\n throw new Error(\"Bad pairing: \" + [JSON.stringify(fwd), JSON.stringify(rev)]);\n }\n name = name || this._guessNameForPair(fwd, rev);\n return { forward: fwd, name: name, reverse: rev };\n },\n\n /** try to find a good pair name for the given fwd and rev datasets */\n _guessNameForPair: function _guessNameForPair(fwd, rev, removeExtensions) {\n removeExtensions = removeExtensions !== undefined ? removeExtensions : this.removeExtensions;\n var fwdName = fwd.name;\n var revName = rev.name;\n\n var lcs = this._naiveStartingAndEndingLCS(fwdName.replace(new RegExp(this.filters[0]), \"\"), revName.replace(new RegExp(this.filters[1]), \"\"));\n\n if (removeExtensions) {\n var lastDotIndex = lcs.lastIndexOf(\".\");\n if (lastDotIndex > 0) {\n var extension = lcs.slice(lastDotIndex, lcs.length);\n lcs = lcs.replace(extension, \"\");\n fwdName = fwdName.replace(extension, \"\");\n revName = revName.replace(extension, \"\");\n }\n }\n return lcs || fwdName + \" & \" + revName;\n },\n\n /** unpair a pair, removing it from paired, and adding the fwd,rev datasets back into unpaired */\n _unpair: function _unpair(pair, options) {\n options = options || {};\n if (!pair) {\n throw new Error(\"Bad pair: \" + JSON.stringify(pair));\n }\n this.paired = _.without(this.paired, pair);\n this._addToUnpaired(pair.forward);\n this._addToUnpaired(pair.reverse);\n\n if (!options.silent) {\n this.trigger(\"pair:unpair\", [pair]);\n }\n return pair;\n },\n\n /** unpair all paired datasets */\n unpairAll: function unpairAll() {\n var pairs = [];\n while (this.paired.length) {\n pairs.push(this._unpair(this.paired[0], { silent: true }));\n }\n this.trigger(\"pair:unpair\", pairs);\n },\n\n // ------------------------------------------------------------------------ API\n /** convert a pair into JSON compatible with the collections API */\n _pairToJSON: function _pairToJSON(pair, src) {\n src = src || \"hda\";\n //TODO: consider making this the pair structure when created instead\n return {\n collection_type: \"paired\",\n src: \"new_collection\",\n name: pair.name,\n element_identifiers: [{\n name: \"forward\",\n id: pair.forward.id,\n src: src\n }, {\n name: \"reverse\",\n id: pair.reverse.id,\n src: src\n }]\n };\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function createList(name) {\n var self = this;\n\n var url = Galaxy.root + \"api/histories/\" + this.historyId + \"/contents/dataset_collections\";\n\n //TODO: use ListPairedCollection.create()\n var ajaxData = {\n type: \"dataset_collection\",\n collection_type: \"list:paired\",\n hide_source_items: self.hideOriginals || false,\n name: _.escape(name || self.$(\".collection-name\").val()),\n element_identifiers: self.paired.map(function (pair) {\n return self._pairToJSON(pair);\n })\n };\n //this.debug( JSON.stringify( ajaxData ) );\n self.blocking = true;\n return jQuery.ajax(url, {\n type: \"POST\",\n contentType: \"application/json\",\n dataType: \"json\",\n data: JSON.stringify(ajaxData)\n }).always(function () {\n self.blocking = false;\n }).fail(function (xhr, status, message) {\n self._ajaxErrHandler(xhr, status, message);\n }).done(function (response, message, xhr) {\n //this.info( 'ok', response, message, xhr );\n self.trigger(\"collection:created\", response, message, xhr);\n self.metric(\"collection:created\", response);\n if (typeof self.oncreate === \"function\") {\n self.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n /** handle ajax errors with feedback and details to the user (if available) */\n _ajaxErrHandler: function _ajaxErrHandler(xhr, status, message) {\n this.error(xhr, status, message);\n var self = this;\n var content = (0, _localization2.default)(\"An error occurred while creating this collection\");\n if (xhr) {\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += \": \" + (0, _localization2.default)(\"Galaxy could not be reached and may be updating.\") + (0, _localization2.default)(\" Try again in a few minutes.\");\n } else if (xhr.responseJSON) {\n content += \"
\" + JSON.stringify(xhr.responseJSON) + \"
\";\n } else {\n content += \": \" + message;\n }\n }\n self._showAlert(content, \"alert-danger\");\n },\n\n // ------------------------------------------------------------------------ rendering\n /** render the entire interface */\n render: function render(speed, callback) {\n //this.debug( '-- _render' );\n //this.$el.empty().html( this.templates.main() );\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function _renderHeader(speed, callback) {\n //this.debug( '-- _renderHeader' );\n var $header = this.$(\".header\").empty().html(this.templates.header()).find(\".help-content\").prepend($(this.templates.helpContent()));\n\n this._renderFilters();\n return $header;\n },\n /** fill the filter inputs with the filter values */\n _renderFilters: function _renderFilters() {\n return this.$(\".forward-column .column-header input\").val(this.filters[0]).add(this.$(\".reverse-column .column-header input\").val(this.filters[1]));\n },\n\n /** render the middle including unpaired and paired sections (which may be hidden) */\n _renderMiddle: function _renderMiddle(speed, callback) {\n var $middle = this.$(\".middle\").empty().html(this.templates.middle());\n\n // (re-) hide the un/paired panels based on instance vars\n if (this.unpairedPanelHidden) {\n this.$(\".unpaired-columns\").hide();\n } else if (this.pairedPanelHidden) {\n this.$(\".paired-columns\").hide();\n }\n\n this._renderUnpaired();\n this._renderPaired();\n return $middle;\n },\n /** render the unpaired section, showing datasets accrd. to filters, update the unpaired counts */\n _renderUnpaired: function _renderUnpaired(speed, callback) {\n //this.debug( '-- _renderUnpaired' );\n var self = this;\n\n var $fwd;\n var $rev;\n var $prd = [];\n var split = this._splitByFilters();\n // update unpaired counts\n this.$(\".forward-column .title\").text([split[0].length, (0, _localization2.default)(\"unpaired forward\")].join(\" \"));\n this.$(\".forward-column .unpaired-info\").text(this._renderUnpairedDisplayStr(this.unpaired.length - split[0].length));\n this.$(\".reverse-column .title\").text([split[1].length, (0, _localization2.default)(\"unpaired reverse\")].join(\" \"));\n this.$(\".reverse-column .unpaired-info\").text(this._renderUnpairedDisplayStr(this.unpaired.length - split[1].length));\n\n this.$(\".unpaired-columns .column-datasets\").empty();\n\n // show/hide the auto pair button if any unpaired are left\n this.$(\".autopair-link\").toggle(this.unpaired.length !== 0);\n if (this.unpaired.length === 0) {\n this._renderUnpairedEmpty();\n return;\n }\n\n // create the dataset dom arrays\n $rev = split[1].map(function (dataset, i) {\n // if there'll be a fwd dataset across the way, add a button to pair the row\n if (split[0][i] !== undefined && split[0][i] !== dataset) {\n $prd.push(self._renderPairButton());\n }\n return self._renderUnpairedDataset(dataset);\n });\n $fwd = split[0].map(function (dataset) {\n return self._renderUnpairedDataset(dataset);\n });\n\n if (!$fwd.length && !$rev.length) {\n this._renderUnpairedNotShown();\n return;\n }\n // add to appropo cols\n //TODO: not the best way to render - consider rendering the entire unpaired-columns section in a fragment\n // and swapping out that\n this.$(\".unpaired-columns .forward-column .column-datasets\").append($fwd).add(this.$(\".unpaired-columns .paired-column .column-datasets\").append($prd)).add(this.$(\".unpaired-columns .reverse-column .column-datasets\").append($rev));\n this._adjUnpairedOnScrollbar();\n },\n /** return a string to display the count of filtered out datasets */\n _renderUnpairedDisplayStr: function _renderUnpairedDisplayStr(numFiltered) {\n return [\"(\", numFiltered, \" \", (0, _localization2.default)(\"filtered out\"), \")\"].join(\"\");\n },\n /** return an unattached jQuery DOM element to represent an unpaired dataset */\n _renderUnpairedDataset: function _renderUnpairedDataset(dataset) {\n //TODO: to underscore template\n return $(\"\").attr(\"id\", \"dataset-\" + dataset.id).addClass(\"dataset unpaired\").attr(\"draggable\", true).addClass(dataset.selected ? \"selected\" : \"\").append($(\"\").addClass(\"dataset-name\").text(dataset.name))\n //??\n .data(\"dataset\", dataset);\n },\n /** render the button that may go between unpaired datasets, allowing the user to pair a row */\n _renderPairButton: function _renderPairButton() {\n //TODO: *not* a dataset - don't pretend like it is\n return $(\"\").addClass(\"dataset unpaired\").append($(\"\").addClass(\"dataset-name\").text((0, _localization2.default)(\"Pair these datasets\")));\n },\n /** a message to display when no unpaired left */\n _renderUnpairedEmpty: function _renderUnpairedEmpty() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(\"(\" + (0, _localization2.default)(\"no remaining unpaired datasets\") + \")\");\n this.$(\".unpaired-columns .paired-column .column-datasets\").empty().prepend($msg);\n return $msg;\n },\n /** a message to display when no unpaired can be shown with the current filters */\n _renderUnpairedNotShown: function _renderUnpairedNotShown() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(\"(\" + (0, _localization2.default)(\"no datasets were found matching the current filters\") + \")\");\n this.$(\".unpaired-columns .paired-column .column-datasets\").empty().prepend($msg);\n return $msg;\n },\n /** try to detect if the unpaired section has a scrollbar and adjust left column for better centering of all */\n _adjUnpairedOnScrollbar: function _adjUnpairedOnScrollbar() {\n var $unpairedColumns = this.$(\".unpaired-columns\").last();\n\n var $firstDataset = this.$(\".unpaired-columns .reverse-column .dataset\").first();\n\n if (!$firstDataset.length) {\n return;\n }\n\n var ucRight = $unpairedColumns.offset().left + $unpairedColumns.outerWidth();\n\n var dsRight = $firstDataset.offset().left + $firstDataset.outerWidth();\n\n var rightDiff = Math.floor(ucRight) - Math.floor(dsRight);\n //this.debug( 'rightDiff:', ucRight, '-', dsRight, '=', rightDiff );\n this.$(\".unpaired-columns .forward-column\").css(\"margin-left\", rightDiff > 0 ? rightDiff : 0);\n },\n\n /** render the paired section and update counts of paired datasets */\n _renderPaired: function _renderPaired(speed, callback) {\n //this.debug( '-- _renderPaired' );\n this.$(\".paired-column-title .title\").text([this.paired.length, (0, _localization2.default)(\"paired\")].join(\" \"));\n // show/hide the unpair all link\n this.$(\".unpair-all-link\").toggle(this.paired.length !== 0);\n if (this.paired.length === 0) {\n this._renderPairedEmpty();\n return;\n //TODO: would be best to return here (the $columns)\n } else {\n // show/hide 'remove extensions link' when any paired and they seem to have extensions\n this.$(\".remove-extensions-link\").show();\n }\n\n this.$(\".paired-columns .column-datasets\").empty();\n var self = this;\n this.paired.forEach(function (pair, i) {\n //TODO: cache these?\n var pairView = new PairView({ pair: pair });\n self.$(\".paired-columns .column-datasets\").append(pairView.render().$el).append(['\"].join(\"\"));\n });\n },\n /** a message to display when none paired */\n _renderPairedEmpty: function _renderPairedEmpty() {\n var $msg = $('').text(\"(\" + (0, _localization2.default)(\"no paired datasets yet\") + \")\");\n this.$(\".paired-columns .column-datasets\").empty().prepend($msg);\n return $msg;\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\",\n \".remove-extensions\": \"removeExtensions\"\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function _addPluginComponents() {\n this._chooseFiltersPopover(\".choose-filters-link\");\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", \"rgba( 64, 255, 255, 1.0 )\");\n },\n\n /** build a filter selection popover allowing selection of common filter pairs */\n _chooseFiltersPopover: function _chooseFiltersPopover(selector) {\n function filterChoice(val1, val2) {\n return ['\"].join(\"\");\n }\n var $popoverContent = $(_.template(['
', '
', (0, _localization2.default)(\"Choose from the following filters to change which unpaired reads are shown in the display\"), \":
\"].join(\"\"))({}));\n\n return this.$(selector).popover({\n container: \".collection-creator\",\n placement: \"bottom\",\n html: true,\n //animation : false,\n content: $popoverContent\n });\n },\n\n /** add (or clear if clear is truthy) a validation warning to what */\n _validationWarning: function _validationWarning(what, clear) {\n var VALIDATION_CLASS = \"validation-warning\";\n if (what === \"name\") {\n what = this.$(\".collection-name\").add(this.$(\".collection-name-prompt\"));\n this.$(\".collection-name\").focus().select();\n }\n if (clear) {\n what = what || this.$(\".\" + VALIDATION_CLASS);\n what.removeClass(VALIDATION_CLASS);\n } else {\n what.addClass(VALIDATION_CLASS);\n }\n },\n\n // ------------------------------------------------------------------------ events\n /** set up event handlers on self */\n _setUpBehaviors: function _setUpBehaviors() {\n this.once(\"rendered\", function () {\n this.trigger(\"rendered:initial\", this);\n });\n\n this.on(\"pair:new\", function () {\n //TODO: ideally only re-render the columns (or even elements) involved\n this._renderUnpaired();\n this._renderPaired();\n\n // scroll to bottom where new pairs are added\n //TODO: this doesn't seem to work - innerHeight sticks at 133...\n // may have to do with improper flex columns\n //var $pairedView = this.$( '.paired-columns' );\n //$pairedView.scrollTop( $pairedView.innerHeight() );\n //this.debug( $pairedView.height() )\n this.$(\".paired-columns\").scrollTop(8000000);\n });\n this.on(\"pair:unpair\", function (pairs) {\n //TODO: ideally only re-render the columns (or even elements) involved\n this._renderUnpaired();\n this._renderPaired();\n this.splitView();\n });\n\n this.on(\"filter-change\", function () {\n this.filters = [this.$(\".forward-unpaired-filter input\").val(), this.$(\".reverse-unpaired-filter input\").val()];\n this.metric(\"filter-change\", this.filters);\n this._renderFilters();\n this._renderUnpaired();\n });\n\n this.on(\"autopair\", function () {\n this._renderUnpaired();\n this._renderPaired();\n\n var message;\n var msgClass = null;\n if (this.paired.length) {\n msgClass = \"alert-success\";\n message = this.paired.length + \" \" + (0, _localization2.default)(\"pairs created\");\n if (!this.unpaired.length) {\n message += \": \" + (0, _localization2.default)(\"all datasets have been successfully paired\");\n this.hideUnpaired();\n this.$(\".collection-name\").focus();\n }\n } else {\n message = (0, _localization2.default)([\"Could not automatically create any pairs from the given dataset names.\", \"You may want to choose or enter different filters and try auto-pairing again.\", \"Close this message using the X on the right to view more help.\"].join(\" \"));\n }\n this._showAlert(message, msgClass);\n });\n\n //this.on( 'all', function(){\n // this.info( arguments );\n //});\n return this;\n },\n\n events: {\n // header\n \"click .more-help\": \"_clickMoreHelp\",\n \"click .less-help\": \"_clickLessHelp\",\n \"click .main-help\": \"_toggleHelp\",\n \"click .header .alert button\": \"_hideAlert\",\n \"click .forward-column .column-title\": \"_clickShowOnlyUnpaired\",\n \"click .reverse-column .column-title\": \"_clickShowOnlyUnpaired\",\n \"click .unpair-all-link\": \"_clickUnpairAll\",\n //TODO: this seems kinda backasswards - re-sending jq event as a backbone event, can we listen directly?\n \"change .forward-unpaired-filter input\": function changeForwardUnpairedFilterInput(ev) {\n this.trigger(\"filter-change\");\n },\n \"focus .forward-unpaired-filter input\": function focusForwardUnpairedFilterInput(ev) {\n $(ev.currentTarget).select();\n },\n \"click .autopair-link\": \"_clickAutopair\",\n \"click .choose-filters .filter-choice\": \"_clickFilterChoice\",\n \"click .clear-filters-link\": \"_clearFilters\",\n \"change .reverse-unpaired-filter input\": function changeReverseUnpairedFilterInput(ev) {\n this.trigger(\"filter-change\");\n },\n \"focus .reverse-unpaired-filter input\": function focusReverseUnpairedFilterInput(ev) {\n $(ev.currentTarget).select();\n },\n // unpaired\n \"click .forward-column .dataset.unpaired\": \"_clickUnpairedDataset\",\n \"click .reverse-column .dataset.unpaired\": \"_clickUnpairedDataset\",\n \"click .paired-column .dataset.unpaired\": \"_clickPairRow\",\n \"click .unpaired-columns\": \"clearSelectedUnpaired\",\n \"mousedown .unpaired-columns .dataset\": \"_mousedownUnpaired\",\n // divider\n \"click .paired-column-title\": \"_clickShowOnlyPaired\",\n \"mousedown .flexible-partition-drag\": \"_startPartitionDrag\",\n // paired\n \"click .paired-columns .dataset.paired\": \"selectPair\",\n \"click .paired-columns\": \"clearSelectedPaired\",\n \"click .paired-columns .pair-name\": \"_clickPairName\",\n \"click .unpair-btn\": \"_clickUnpair\",\n // paired - drop target\n //'dragenter .paired-columns' : '_dragenterPairedColumns',\n //'dragleave .paired-columns .column-datasets': '_dragleavePairedColumns',\n \"dragover .paired-columns .column-datasets\": \"_dragoverPairedColumns\",\n \"drop .paired-columns .column-datasets\": \"_dropPairedColumns\",\n\n \"pair.dragstart .paired-columns .column-datasets\": \"_pairDragstart\",\n \"pair.dragend .paired-columns .column-datasets\": \"_pairDragend\",\n\n // footer\n \"change .remove-extensions\": function changeRemoveExtensions(ev) {\n this.toggleExtensions();\n },\n \"change .collection-name\": \"_changeName\",\n \"keydown .collection-name\": \"_nameCheckForEnter\",\n \"change .hide-originals\": \"_changeHideOriginals\",\n \"click .cancel-create\": \"_cancelCreate\",\n \"click .create-collection\": \"_clickCreate\" //,\n },\n\n /** toggle between showing only unpaired and split view */\n _clickShowOnlyUnpaired: function _clickShowOnlyUnpaired(ev) {\n //this.debug( 'click unpaired', ev.currentTarget );\n if (this.$(\".paired-columns\").is(\":visible\")) {\n this.hidePaired();\n } else {\n this.splitView();\n }\n },\n /** toggle between showing only paired and split view */\n _clickShowOnlyPaired: function _clickShowOnlyPaired(ev) {\n //this.debug( 'click paired' );\n if (this.$(\".unpaired-columns\").is(\":visible\")) {\n this.hideUnpaired();\n } else {\n this.splitView();\n }\n },\n\n /** hide unpaired, show paired */\n hideUnpaired: function hideUnpaired(speed, callback) {\n this.unpairedPanelHidden = true;\n this.pairedPanelHidden = false;\n this._renderMiddle(speed, callback);\n },\n /** hide paired, show unpaired */\n hidePaired: function hidePaired(speed, callback) {\n this.unpairedPanelHidden = false;\n this.pairedPanelHidden = true;\n this._renderMiddle(speed, callback);\n },\n /** show both paired and unpaired (splitting evenly) */\n splitView: function splitView(speed, callback) {\n this.unpairedPanelHidden = this.pairedPanelHidden = false;\n this._renderMiddle(speed, callback);\n return this;\n },\n\n /** unpair all paired and do other super neat stuff which I'm not really sure about yet... */\n _clickUnpairAll: function _clickUnpairAll(ev) {\n this.metric(\"unpairAll\");\n this.unpairAll();\n },\n\n /** attempt to autopair */\n _clickAutopair: function _clickAutopair(ev) {\n var paired = this.autoPair();\n this.metric(\"autopair\", paired.length, this.unpaired.length);\n this.trigger(\"autopair\");\n },\n\n /** set the filters based on the data attributes of the button click target */\n _clickFilterChoice: function _clickFilterChoice(ev) {\n var $selected = $(ev.currentTarget);\n this.$(\".forward-unpaired-filter input\").val($selected.data(\"forward\"));\n this.$(\".reverse-unpaired-filter input\").val($selected.data(\"reverse\"));\n this._hideChooseFilters();\n this.trigger(\"filter-change\");\n },\n\n /** hide the choose filters popover */\n _hideChooseFilters: function _hideChooseFilters() {\n //TODO: update bootstrap and remove the following hack\n // see also: https://github.com/twbs/bootstrap/issues/10260\n this.$(\".choose-filters-link\").popover(\"hide\");\n this.$(\".popover\").css(\"display\", \"none\");\n },\n\n /** clear both filters */\n _clearFilters: function _clearFilters(ev) {\n this.$(\".forward-unpaired-filter input\").val(\"\");\n this.$(\".reverse-unpaired-filter input\").val(\"\");\n this.trigger(\"filter-change\");\n },\n\n // ........................................................................ unpaired\n /** select an unpaired dataset */\n _clickUnpairedDataset: function _clickUnpairedDataset(ev) {\n ev.stopPropagation();\n return this.toggleSelectUnpaired($(ev.currentTarget));\n },\n\n /** Toggle the selection of an unpaired dataset representation.\n * @param [jQuery] $dataset the unpaired dataset dom rep to select\n * @param [Boolean] options.force if defined, force selection based on T/F; otherwise, toggle\n */\n toggleSelectUnpaired: function toggleSelectUnpaired($dataset, options) {\n options = options || {};\n var dataset = $dataset.data(\"dataset\");\n\n var select = options.force !== undefined ? options.force : !$dataset.hasClass(\"selected\");\n\n //this.debug( id, options.force, $dataset, dataset );\n if (!$dataset.length || dataset === undefined) {\n return $dataset;\n }\n\n if (select) {\n $dataset.addClass(\"selected\");\n if (!options.waitToPair) {\n this.pairAllSelected();\n }\n } else {\n $dataset.removeClass(\"selected\");\n //delete dataset.selected;\n }\n return $dataset;\n },\n\n /** pair all the currently selected unpaired datasets */\n pairAllSelected: function pairAllSelected(options) {\n options = options || {};\n var self = this;\n var fwds = [];\n var revs = [];\n var pairs = [];\n self.$(\".unpaired-columns .forward-column .dataset.selected\").each(function () {\n fwds.push($(this).data(\"dataset\"));\n });\n self.$(\".unpaired-columns .reverse-column .dataset.selected\").each(function () {\n revs.push($(this).data(\"dataset\"));\n });\n fwds.length = revs.length = Math.min(fwds.length, revs.length);\n //this.debug( fwds );\n //this.debug( revs );\n fwds.forEach(function (fwd, i) {\n try {\n pairs.push(self._pair(fwd, revs[i], { silent: true }));\n } catch (err) {\n //TODO: preserve selected state of those that couldn't be paired\n //TODO: warn that some could not be paired\n self.error(err);\n }\n });\n if (pairs.length && !options.silent) {\n this.trigger(\"pair:new\", pairs);\n }\n return pairs;\n },\n\n /** clear the selection on all unpaired datasets */\n clearSelectedUnpaired: function clearSelectedUnpaired() {\n this.$(\".unpaired-columns .dataset.selected\").removeClass(\"selected\");\n },\n\n /** when holding down the shift key on a click, 'paint' the moused over datasets as selected */\n _mousedownUnpaired: function _mousedownUnpaired(ev) {\n if (ev.shiftKey) {\n var self = this;\n var $startTarget = $(ev.target).addClass(\"selected\");\n\n var moveListener = function moveListener(ev) {\n self.$(ev.target).filter(\".dataset\").addClass(\"selected\");\n };\n\n $startTarget.parent().on(\"mousemove\", moveListener);\n\n // on any mouseup, stop listening to the move and try to pair any selected\n $(document).one(\"mouseup\", function (ev) {\n $startTarget.parent().off(\"mousemove\", moveListener);\n self.pairAllSelected();\n });\n }\n },\n\n /** attempt to pair two datasets directly across from one another */\n _clickPairRow: function _clickPairRow(ev) {\n //if( !ev.currentTarget ){ return true; }\n var rowIndex = $(ev.currentTarget).index();\n\n var fwd = $(\".unpaired-columns .forward-column .dataset\").eq(rowIndex).data(\"dataset\");\n\n var rev = $(\".unpaired-columns .reverse-column .dataset\").eq(rowIndex).data(\"dataset\");\n\n //this.debug( 'row:', rowIndex, fwd, rev );\n this._pair(fwd, rev);\n },\n\n // ........................................................................ divider/partition\n /** start dragging the visible divider/partition between unpaired and paired panes */\n _startPartitionDrag: function _startPartitionDrag(ev) {\n var self = this;\n var startingY = ev.pageY;\n //this.debug( 'partition drag START:', ev );\n $(\"body\").css(\"cursor\", \"ns-resize\");\n self.$(\".flexible-partition-drag\").css(\"color\", \"black\");\n\n function endDrag(ev) {\n self.$(\".flexible-partition-drag\").css(\"color\", \"\");\n $(\"body\").css(\"cursor\", \"\").unbind(\"mousemove\", trackMouse);\n }\n function trackMouse(ev) {\n var offset = ev.pageY - startingY;\n if (!self.adjPartition(offset)) {\n $(\"body\").trigger(\"mouseup\");\n }\n self._adjUnpairedOnScrollbar();\n startingY += offset;\n }\n $(\"body\").mousemove(trackMouse);\n $(\"body\").one(\"mouseup\", endDrag);\n },\n\n /** adjust the parition up/down +/-adj pixels */\n adjPartition: function adjPartition(adj) {\n var $unpaired = this.$(\".unpaired-columns\");\n var $paired = this.$(\".paired-columns\");\n var unpairedHi = parseInt($unpaired.css(\"height\"), 10);\n var pairedHi = parseInt($paired.css(\"height\"), 10);\n //this.debug( adj, 'hi\\'s:', unpairedHi, pairedHi, unpairedHi + adj, pairedHi - adj );\n\n unpairedHi = Math.max(10, unpairedHi + adj);\n pairedHi = pairedHi - adj;\n\n var movingUpwards = adj < 0;\n // when the divider gets close to the top - lock into hiding the unpaired section\n if (movingUpwards) {\n if (this.unpairedPanelHidden) {\n return false;\n } else if (unpairedHi <= 10) {\n this.hideUnpaired();\n return false;\n }\n } else {\n if (this.unpairedPanelHidden) {\n $unpaired.show();\n this.unpairedPanelHidden = false;\n }\n }\n\n // when the divider gets close to the bottom - lock into hiding the paired section\n if (!movingUpwards) {\n if (this.pairedPanelHidden) {\n return false;\n } else if (pairedHi <= 15) {\n this.hidePaired();\n return false;\n }\n } else {\n if (this.pairedPanelHidden) {\n $paired.show();\n this.pairedPanelHidden = false;\n }\n }\n\n $unpaired.css({\n height: unpairedHi + \"px\",\n flex: \"0 0 auto\"\n });\n return true;\n },\n\n // ........................................................................ paired\n /** select a pair when clicked */\n selectPair: function selectPair(ev) {\n ev.stopPropagation();\n $(ev.currentTarget).toggleClass(\"selected\");\n },\n\n /** deselect all pairs */\n clearSelectedPaired: function clearSelectedPaired(ev) {\n this.$(\".paired-columns .dataset.selected\").removeClass(\"selected\");\n },\n\n /** rename a pair when the pair name is clicked */\n _clickPairName: function _clickPairName(ev) {\n ev.stopPropagation();\n var $name = $(ev.currentTarget);\n var $pair = $name.parent().parent();\n var index = $pair.index(\".dataset.paired\");\n var pair = this.paired[index];\n var response = prompt(\"Enter a new name for the pair:\", pair.name);\n if (response) {\n pair.name = response;\n // set a flag (which won't be passed in json creation) for manual naming so we don't overwrite these\n // when adding/removing extensions\n //hackish\n pair.customizedName = true;\n $name.text(pair.name);\n }\n },\n\n /** unpair this pair */\n _clickUnpair: function _clickUnpair(ev) {\n //if( !ev.currentTarget ){ return true; }\n var pairIndex = Math.floor($(ev.currentTarget).index(\".unpair-btn\"));\n //this.debug( 'pair:', pairIndex );\n this._unpair(this.paired[pairIndex]);\n },\n\n // ........................................................................ paired - drag and drop re-ordering\n //_dragenterPairedColumns : function( ev ){\n // this.debug( '_dragenterPairedColumns:', ev );\n //},\n //_dragleavePairedColumns : function( ev ){\n // //this.debug( '_dragleavePairedColumns:', ev );\n //},\n /** track the mouse drag over the paired list adding a placeholder to show where the drop would occur */\n _dragoverPairedColumns: function _dragoverPairedColumns(ev) {\n //this.debug( '_dragoverPairedColumns:', ev );\n ev.preventDefault();\n\n var $list = this.$(\".paired-columns .column-datasets\");\n this._checkForAutoscroll($list, ev.originalEvent.clientY);\n //this.debug( ev.originalEvent.clientX, ev.originalEvent.clientY );\n var $nearest = this._getNearestPairedDatasetLi(ev.originalEvent.clientY);\n\n $(\".element-drop-placeholder\").remove();\n var $placeholder = $('');\n if (!$nearest.length) {\n $list.append($placeholder);\n } else {\n $nearest.before($placeholder);\n }\n },\n\n /** If the mouse is near enough to the list's top or bottom, scroll the list */\n _checkForAutoscroll: function _checkForAutoscroll($element, y) {\n var AUTOSCROLL_SPEED = 2;\n var offset = $element.offset();\n var scrollTop = $element.scrollTop();\n var upperDist = y - offset.top;\n var lowerDist = offset.top + $element.outerHeight() - y;\n //this.debug( '_checkForAutoscroll:', scrollTop, upperDist, lowerDist );\n if (upperDist >= 0 && upperDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop - AUTOSCROLL_SPEED);\n } else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop + AUTOSCROLL_SPEED);\n }\n },\n\n /** get the nearest *previous* paired dataset PairView based on the mouse's Y coordinate.\n * If the y is at the end of the list, return an empty jQuery object.\n */\n _getNearestPairedDatasetLi: function _getNearestPairedDatasetLi(y) {\n var WIGGLE = 4;\n var lis = this.$(\".paired-columns .column-datasets li\").toArray();\n for (var i = 0; i < lis.length; i++) {\n var $li = $(lis[i]);\n var top = $li.offset().top;\n var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;\n if (top + halfHeight > y && top - halfHeight < y) {\n //this.debug( y, top + halfHeight, top - halfHeight )\n return $li;\n }\n }\n return $();\n },\n /** drop (dragged/selected PairViews) onto the list, re-ordering both the DOM and the internal array of pairs */\n _dropPairedColumns: function _dropPairedColumns(ev) {\n // both required for firefox\n ev.preventDefault();\n ev.dataTransfer.dropEffect = \"move\";\n\n var $nearest = this._getNearestPairedDatasetLi(ev.originalEvent.clientY);\n if ($nearest.length) {\n this.$dragging.insertBefore($nearest);\n } else {\n // no nearest before - insert after last element (unpair button)\n this.$dragging.insertAfter(this.$(\".paired-columns .unpair-btn\").last());\n }\n // resync the creator's list of paired based on the new DOM order\n this._syncPairsToDom();\n return false;\n },\n /** resync the creator's list of paired based on the DOM order of pairs */\n _syncPairsToDom: function _syncPairsToDom() {\n var newPaired = [];\n //TODO: doesn't seem wise to use the dom to store these - can't we sync another way?\n this.$(\".paired-columns .dataset.paired\").each(function () {\n newPaired.push($(this).data(\"pair\"));\n });\n //this.debug( newPaired );\n this.paired = newPaired;\n this._renderPaired();\n },\n /** drag communication with pair sub-views: dragstart */\n _pairDragstart: function _pairDragstart(ev, pair) {\n //this.debug( '_pairDragstart', ev, pair )\n // auto select the pair causing the event and move all selected\n pair.$el.addClass(\"selected\");\n var $selected = this.$(\".paired-columns .dataset.selected\");\n this.$dragging = $selected;\n },\n /** drag communication with pair sub-views: dragend - remove the placeholder */\n _pairDragend: function _pairDragend(ev, pair) {\n //this.debug( '_pairDragend', ev, pair )\n $(\".element-drop-placeholder\").remove();\n this.$dragging = null;\n },\n\n // ........................................................................ footer\n toggleExtensions: function toggleExtensions(force) {\n var self = this;\n self.removeExtensions = force !== undefined ? force : !self.removeExtensions;\n\n _.each(self.paired, function (pair) {\n // don't overwrite custom names\n if (pair.customizedName) {\n return;\n }\n pair.name = self._guessNameForPair(pair.forward, pair.reverse);\n });\n\n self._renderPaired();\n self._renderFooter();\n },\n\n // ------------------------------------------------------------------------ misc\n /** debug a dataset list */\n _printList: function _printList(list) {\n var self = this;\n _.each(list, function (e) {\n if (list === self.paired) {\n self._printPair(e);\n } else {\n self.debug(e);\n }\n });\n },\n\n /** print a pair Object */\n _printPair: function _printPair(pair) {\n this.debug(pair.forward.name, pair.reverse.name, \": ->\", pair.name);\n },\n\n /** string rep */\n toString: function toString() {\n return \"PairedCollectionCreator\";\n },\n\n templates: _.extend({}, _baseCreator2.default.CollectionCreatorMixin._creatorTemplates, {\n /** the header (not including help text) */\n header: _.template(['
\"].join(\"\")),\n\n /** the middle: unpaired, divider, and paired */\n middle: _.template([\n // contains two flex rows (rows that fill available space) and a divider btwn\n '
\"].join(\"\")),\n\n /** help content */\n helpContent: _.template([\"
\", (0, _localization2.default)([\"Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). \", \"These collections can be passed to tools and workflows in order to have analyses done on each member of \", \"the entire group. This interface allows you to create a collection, choose which datasets are paired, \", \"and re-order the final collection.\"].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Unpaired datasets are shown in the unpaired section ', \"(hover over the underlined words to highlight below). \", 'Paired datasets are shown in the paired section.', \"
To pair datasets, you can:\", \"
Click a dataset in the \", 'forward column ', \"to select it then click a dataset in the \", 'reverse column.', \"
\", '
Click one of the \"Pair these datasets\" buttons in the ', 'middle column ', \"to pair the datasets in a particular row.\", \"
\", '
Click \"Auto-pair\" ', \"to have your datasets automatically paired based on name.\", \"
\", \"
\"].join(\"\")), \"\", \"
\", (0, _localization2.default)([\"
You can filter what is shown in the unpaired sections by:\", \"
Entering partial dataset names in either the \", 'forward filter or ', 'reverse filter.', \"
\", \"
Choosing from a list of preset filters by clicking the \", '\"Choose filters\" link.', \"
Clearing the filters by clicking the \", '\"Clear filters\" link.', \"
\", \"
\"].join(\"\")), \"\", \"
\", (0, _localization2.default)([\"To unpair individual dataset pairs, click the \", 'unpair buttons ( ). ', 'Click the \"Unpair all\" link to unpair all pairs.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['You can include or remove the file extensions (e.g. \".fastq\") from your pair names by toggling the ', '\"Remove file extensions from pair names?\" control.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Once your collection is complete, enter a name and ', 'click \"Create list\". ', \"(Note: you do not have to pair all unpaired datasets to finish.)\"].join(\"\")), \"
\"].join(\"\"))\n })\n});\n\n//=============================================================================\n/** a modal version of the paired collection creator */\nvar pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(datasets, options) {\n var deferred = jQuery.Deferred();\n var creator;\n\n options = _.defaults(options || {}, {\n datasets: datasets,\n oncancel: function oncancel() {\n Galaxy.modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function oncreate(creator, response) {\n Galaxy.modal.hide();\n deferred.resolve(response);\n }\n });\n\n if (!window.Galaxy || !Galaxy.modal) {\n throw new Error(\"Galaxy or Galaxy.modal not found\");\n }\n\n creator = new PairedCollectionCreator(options);\n Galaxy.modal.show({\n title: \"Create a collection of paired datasets\",\n body: creator.$el,\n width: \"80%\",\n height: \"800px\",\n closing_events: true\n });\n creator.render();\n window.creator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n//=============================================================================\nfunction createListOfPairsCollection(collection, defaultHideSourceItems) {\n var elements = collection.toJSON();\n //TODO: validate elements\n return pairedCollectionCreatorModal(elements, {\n historyId: collection.historyId,\n defaultHideSourceItems: defaultHideSourceItems\n });\n}\n\n//=============================================================================\nexports.default = {\n PairedCollectionCreator: PairedCollectionCreator,\n pairedCollectionCreatorModal: pairedCollectionCreatorModal,\n createListOfPairsCollection: createListOfPairsCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 162 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n//=============================================================================\n/**\n(Imported for edit distance algorith. From: https://gist.github.com/andrei-m/982927)\nCopyright (c) 2011 Andrei Mackenzie\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the\nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n// Compute the edit distance between the two given strings\n//exports.getEditDistance = function(a, b){\nfunction levenshteinDistance(a, b) {\n if (a.length === 0) {\n return b.length;\n }\n if (b.length === 0) {\n return a.length;\n }\n\n var matrix = [];\n\n // increment along the first column of each row\n var i;\n for (i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n\n // increment each column in the first row\n var j;\n for (j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n\n // Fill in the rest of the matrix\n for (i = 1; i <= b.length; i++) {\n for (j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution\n Math.min(matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j] + 1)); // deletion\n }\n }\n }\n\n //console.debug( '\\t\\t levenshteinDistance', a, b, matrix[b.length][a.length] );\n return matrix[b.length][a.length];\n}\n\n//=============================================================================\nexports.default = levenshteinDistance;\n\n/***/ }),\n/* 163 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _queryStringParsing = __webpack_require__(8);\n\nvar _queryStringParsing2 = _interopRequireDefault(_queryStringParsing);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Contains descriptive dictionaries describing user forms */\nvar Model = Backbone.Model.extend({\n initialize: function initialize(options) {\n options = options || {};\n options.user_id = options.user_id || Galaxy.user.id;\n this.set({\n user_id: options.user_id,\n information: {\n title: \"Manage information\",\n description: \"Edit your email, addresses and custom parameters or change your username.\",\n url: \"api/users/\" + options.user_id + \"/information/inputs\",\n icon: \"fa-user\",\n redirect: \"user\"\n },\n password: {\n title: \"Change password\",\n description: \"Allows you to change your login credentials.\",\n icon: \"fa-unlock-alt\",\n url: \"api/users/\" + options.user_id + \"/password/inputs\",\n submit_title: \"Save password\",\n redirect: \"user\"\n },\n communication: {\n title: \"Change communication settings\",\n description: \"Enable or disable the communication feature to chat with other users.\",\n url: \"api/users/\" + options.user_id + \"/communication/inputs\",\n icon: \"fa-comments-o\",\n redirect: \"user\"\n },\n permissions: {\n title: \"Set dataset permissions for new histories\",\n description: \"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.\",\n url: \"api/users/\" + options.user_id + \"/permissions/inputs\",\n icon: \"fa-users\",\n submit_title: \"Save permissions\",\n redirect: \"user\"\n },\n api_key: {\n title: \"Manage API key\",\n description: \"Access your current API key or create a new one.\",\n url: \"api/users/\" + options.user_id + \"/api_key/inputs\",\n icon: \"fa-key\",\n submit_title: \"Create a new key\",\n submit_icon: \"fa-check\"\n },\n toolbox_filters: {\n title: \"Manage Toolbox filters\",\n description: \"Customize your Toolbox by displaying or omitting sets of Tools.\",\n url: \"api/users/\" + options.user_id + \"/toolbox_filters/inputs\",\n icon: \"fa-filter\",\n submit_title: \"Save filters\",\n redirect: \"user\"\n },\n openids: {\n title: \"Manage OpenIDs\",\n description: \"Associate OpenIDs with your account.\",\n icon: \"fa-openid\",\n onclick: function onclick() {\n window.location.href = Galaxy.root + \"user/openid_manage?cntrller=user&use_panels=True\";\n }\n },\n custom_builds: {\n title: \"Manage custom builds\",\n description: \"Add or remove custom builds using history datasets.\",\n icon: \"fa-cubes\",\n onclick: function onclick() {\n window.location.href = Galaxy.root + \"custom_builds\";\n }\n },\n logout: {\n title: \"Sign out\",\n description: \"Click here to sign out of all sessions.\",\n icon: \"fa-sign-out\",\n onclick: function onclick() {\n Galaxy.modal.show({\n title: \"Sign out\",\n body: \"Do you want to continue and sign out of all active sessions?\",\n buttons: {\n Cancel: function Cancel() {\n Galaxy.modal.hide();\n },\n \"Sign out\": function SignOut() {\n window.location.href = Galaxy.root + \"user/logout?session_csrf_token=\" + Galaxy.session_csrf_token;\n }\n }\n });\n }\n }\n });\n }\n});\n\n/** View of the main user preference panel with links to individual user forms */\n/** User Preferences view */\nvar View = Backbone.View.extend({\n title: \"User Preferences\",\n initialize: function initialize() {\n this.model = new Model();\n this.setElement(\"\");\n this.render();\n },\n\n render: function render() {\n var self = this;\n var config = Galaxy.config;\n $.getJSON(Galaxy.root + \"api/users/\" + Galaxy.user.id, function (data) {\n self.$preferences = $(\"\").addClass(\"ui-panel\").append($(\"\").append(\"User preferences\")).append($(\"\").append(\"You are logged in as \" + _.escape(data.email) + \".\")).append(self.$table = $(\"
\").addClass(\"ui-panel-table\"));\n var message = _queryStringParsing2.default.get(\"message\");\n var status = _queryStringParsing2.default.get(\"status\");\n if (message && status) {\n self.$preferences.prepend(new _uiMisc2.default.Message({ message: message, status: status }).$el);\n }\n if (!config.use_remote_user) {\n self._addLink(\"information\");\n self._addLink(\"password\");\n }\n if (config.enable_communication_server) {\n self._addLink(\"communication\");\n }\n self._addLink(\"custom_builds\");\n self._addLink(\"permissions\");\n self._addLink(\"api_key\");\n if (config.has_user_tool_filters) {\n self._addLink(\"toolbox_filters\");\n }\n if (config.enable_openid && !config.use_remote_user) {\n self._addLink(\"openids\");\n }\n if (Galaxy.session_csrf_token) {\n self._addLink(\"logout\");\n }\n self.$preferences.append(self._templateFooter(data));\n self.$el.empty().append(self.$preferences);\n });\n },\n\n _addLink: function _addLink(action) {\n var options = this.model.get(action);\n var $row = $(this._templateLink(options));\n var $a = $row.find(\"a\");\n if (options.onclick) {\n $a.on(\"click\", function () {\n options.onclick();\n });\n } else {\n $a.attr(\"href\", Galaxy.root + \"user/\" + action);\n }\n this.$table.append($row);\n },\n\n _templateLink: function _templateLink(options) {\n return \"
\";\n },\n\n _templateFooter: function _templateFooter(options) {\n return \"
You are using \" + options.nice_total_disk_usage + \" of disk space in this Galaxy instance. \" + (Galaxy.config.enable_quotas ? \"Your disk quota is: \" + options.quota + \". \" : \"\") + \"Is your usage more than expected? See the documentation for tips on how to find all of the data in your account.
\";\n }\n});\n\nexports.default = {\n View: View,\n Model: Model\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 164 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _uiTable = __webpack_require__(68);\n\nvar _uiTable2 = _interopRequireDefault(_uiTable);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** This class renders the chart configuration form. */\nvar Collection = Backbone.Collection.extend({\n comparator: function comparator(a, b) {\n a = a.get(\"name\");\n b = b.get(\"name\");\n return a > b ? 1 : a < b ? -1 : 0;\n }\n});\n\nvar View = Backbone.View.extend({\n initialize: function initialize(options) {\n var self = this;\n var history_id = Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.model.id;\n this.model = new Backbone.Model();\n this.model.url = Galaxy.root + \"api/histories/\" + history_id + \"/custom_builds_metadata\";\n this.collection = new Collection();\n this.collection.url = Galaxy.root + \"api/users/\" + Galaxy.user.id + \"/custom_builds\";\n this.message = new _uiMisc2.default.Message({});\n this.installed_builds = new _uiMisc2.default.Select.View({\n optional: true,\n onchange: function onchange() {\n self.installed_builds.value(null);\n },\n empty_text: \"List of available builds:\",\n error_text: \"No system installed builds available.\"\n });\n this.table = new _uiTable2.default.View({ cls: \"grid\", selectable: false });\n this.table.addHeader(\"Name\");\n this.table.addHeader(\"Key\");\n this.table.addHeader(\"Number of chroms/contigs\");\n this.table.addHeader(\"\");\n this.table.appendHeader();\n this.setElement($(\"\").append($(\"\").text(\"Current Custom Builds\")).append(this.table.$el).append(this.$installed = $(\"\").append($(\"\").text(\"System Installed Builds\").addClass(\"ui-margin-top\")).append(this.installed_builds.$el)).append($(\"\").text(\"Add a Custom Build\").addClass(\"ui-margin-top\")).append($(\"\").addClass(\"ui-column\").append($(\"\").addClass(\"ui-column-left\").append(this.message.$el).append(this.$form = $(\"\").addClass(\"ui-margin-top\"))).append(this.$help = $(\"\").addClass(\"ui-column-right\"))));\n this.listenTo(this.collection, \"add remove reset\", function () {\n self._renderTable();\n });\n this.listenTo(this.model, \"change\", function () {\n self._renderForm();\n });\n this.collection.fetch();\n this.model.fetch();\n },\n\n render: function render() {\n this._renderTable();\n this._renderForm();\n },\n\n _renderTable: function _renderTable() {\n var self = this;\n this.table.delAll();\n this.collection.sort();\n this.collection.each(function (model) {\n self.table.add(model.get(\"name\"));\n self.table.add(model.id);\n self.table.add(model.get(\"count\") !== undefined ? model.get(\"count\") : \"Processing...\");\n self.table.add(new _uiMisc2.default.ButtonIcon({\n icon: \"fa-trash-o\",\n cls: \"ui-button-icon-plain\",\n tooltip: \"Delete custom build.\",\n onclick: function onclick() {\n model.destroy();\n }\n }).$el);\n self.table.append(model.id);\n });\n },\n\n _renderForm: function _renderForm() {\n var self = this;\n var initial_type = \"fasta\";\n var form = new _formView2.default({\n inputs: [{\n type: \"text\",\n name: \"name\",\n label: \"Name\",\n help: \"Specify a build name e.g. Hamster.\"\n }, {\n type: \"text\",\n name: \"id\",\n label: \"Key\",\n help: \"Specify a build key e.g. hamster_v1.\"\n }, {\n name: \"len\",\n type: \"conditional\",\n test_param: {\n name: \"type\",\n label: \"Definition\",\n help: \"Provide the data source.\",\n type: \"select\",\n value: initial_type,\n data: [{\n value: \"fasta\",\n label: \"FASTA-file from history\"\n }, {\n value: \"file\",\n label: \"Len-file from disk\"\n }, {\n value: \"text\",\n label: \"Len-file by copy/paste\"\n }]\n },\n cases: [{\n value: \"fasta\",\n inputs: [{\n type: \"select\",\n name: \"value\",\n label: \"FASTA-file\",\n data: this.model.get(\"fasta_hdas\")\n }]\n }, {\n value: \"file\",\n inputs: [{\n type: \"upload\",\n name: \"value\",\n label: \"Len-file\",\n data: this.model.get(\"len_hdas\")\n }]\n }, {\n value: \"text\",\n inputs: [{\n type: \"text\",\n area: true,\n name: \"value\",\n label: \"Edit/Paste\"\n }]\n }]\n }],\n buttons: {\n save: new _uiMisc2.default.Button({\n icon: \"fa-save\",\n tooltip: \"Create new Build\",\n title: \"Save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function onclick() {\n var data = form.data.create();\n if (!data.id || !data.name) {\n self.message.update({\n message: \"All inputs are required.\",\n status: \"danger\"\n });\n } else {\n self.collection.create(data, {\n wait: true,\n success: function success(response) {\n if (response.get(\"message\")) {\n self.message.update({\n message: response.get(\"message\"),\n status: \"warning\"\n });\n } else {\n self.message.update({\n message: \"Successfully added a new custom build.\",\n status: \"success\"\n });\n }\n },\n error: function error(response, err) {\n var message = err && err.responseJSON && err.responseJSON.err_msg;\n self.message.update({\n message: message || \"Failed to create custom build.\",\n status: \"danger\"\n });\n }\n });\n }\n }\n })\n },\n onchange: function onchange() {\n var input_id = form.data.match(\"len|type\");\n if (input_id) {\n var input_field = form.field_list[input_id];\n self._renderHelp(input_field.value());\n }\n }\n });\n this.$form.empty().append(form.$el);\n var installed_builds = this.model.get(\"installed_builds\");\n if (installed_builds && installed_builds.length) {\n this.$installed.show();\n this.installed_builds.update(this.model.get(\"installed_builds\"));\n } else {\n this.$installed.hide();\n }\n this._renderHelp(initial_type);\n },\n\n _renderHelp: function _renderHelp(len_type) {\n this.$help.empty().addClass(\"alert alert-info\").html(len_type == \"fasta\" ? this._templateFasta() : this._templateLen());\n },\n\n _templateLen: function _templateLen() {\n return \"
Length Format
\" + \"
\" + \"The length format is two-column, separated by whitespace, of the form:\" + \"
chrom/contig length of chrom/contig
\" + \"\" + \"
\" + \"For example, the first few entries of mm9.len are as follows:\" + \"
Trackster uses this information to populate the select box for chrom/contig, and\" + \"to set the maximum basepair of the track browser. You may either upload a .len file\" + \"of this format (Len File option), or directly enter the information into the box \" + \"(Len Entry option).
\";\n },\n\n _templateFasta: function _templateFasta() {\n return \"
FASTA format
\" + \"
\" + \"This is a multi-fasta file from your current history that provides the genome\" + \"sequences for each chromosome/contig in your build.\" + \"
\" + \"
\" + \"Here is a snippet from an example multi-fasta file:\" + \"
\";\n }\n }\n});\n\n/** View of the main workflow list page */\nvar WorkflowListView = Backbone.View.extend({\n title: \"Workflows\",\n initialize: function initialize() {\n this.setElement(\"\");\n _.bindAll(this, \"adjustActiondropdown\");\n this.collection = new _workflowModel2.default.WorkflowCollection();\n this.collection.fetch().done(this.render());\n this.collection.bind(\"add\", this.appendItem);\n this.collection.on(\"sync\", this.render, this);\n },\n\n events: {\n dragleave: \"unhighlightDropZone\",\n drop: \"drop\",\n dragover: function dragover(ev) {\n $(\".hidden_description_layer\").addClass(\"dragover\");\n $(\".menubutton\").addClass(\"background-none\");\n ev.preventDefault();\n }\n },\n\n unhighlightDropZone: function unhighlightDropZone() {\n $(\".hidden_description_layer\").removeClass(\"dragover\");\n $(\".menubutton\").removeClass(\"background-none\");\n },\n\n drop: function drop(e) {\n // TODO: check that file is valid galaxy workflow\n this.unhighlightDropZone();\n e.preventDefault();\n var files = e.dataTransfer.files;\n var self = this;\n for (var i = 0, f; f = files[i]; i++) {\n self.readWorkflowFiles(f);\n }\n },\n\n readWorkflowFiles: function readWorkflowFiles(f) {\n var self = this;\n var reader = new FileReader();\n reader.onload = function (theFile) {\n var wf_json;\n try {\n wf_json = JSON.parse(reader.result);\n } catch (e) {\n mod_toastr.error(\"Could not read file '\" + f.name + \"'. Verify it is a valid Galaxy workflow\");\n wf_json = null;\n }\n if (wf_json) {\n self.collection.create(wf_json, {\n at: 0,\n wait: true,\n success: function success() {\n mod_toastr.success(\"Successfully imported workflow '\" + wf_json.name + \"'\");\n },\n error: function error(model, resp, options) {\n mod_toastr.error(options.errorThrown);\n }\n });\n }\n };\n reader.readAsText(f, \"utf-8\");\n },\n\n _showArgErrors: _.once(function () {\n // Parse args out of params, display if there's a message.\n var msg_text = _queryStringParsing2.default.get(\"message\");\n var msg_status = _queryStringParsing2.default.get(\"status\");\n if (msg_status === \"error\") {\n mod_toastr.error(_.escape(msg_text || \"Unknown Error, please report this to an administrator.\"));\n } else if (msg_text) {\n mod_toastr.info(_.escape(msg_text));\n }\n }),\n\n render: function render() {\n // Add workflow header\n var header = this._templateHeader();\n // Add the actions buttons\n var templateActions = this._templateActionButtons();\n var tableTemplate = this._templateWorkflowTable();\n this.$el.html(header + templateActions + tableTemplate);\n var self = this;\n _(this.collection.models).each(function (item) {\n // in case collection is not empty\n self.appendItem(item);\n self.confirmDelete(item);\n }, this);\n var minQueryLength = 3;\n this.searchWorkflow(this.$(\".search-wf\"), this.$(\".workflow-search tr\"), minQueryLength);\n this.adjustActiondropdown();\n this._showArgErrors();\n return this;\n },\n\n appendItem: function appendItem(item) {\n var workflowItemView = new WorkflowItemView({\n model: item,\n collection: this.collection\n });\n $(\".workflow-search\").append(workflowItemView.render().el);\n workflowItemView.renderTagEditor();\n },\n\n /** Add confirm box before removing/unsharing workflow */\n confirmDelete: function confirmDelete(workflow) {\n var $el_shared_wf_link = this.$(\".link-confirm-shared-\" + workflow.id);\n $el_shared_wf_link.click(function () {\n return window.confirm(\"Are you sure you want to remove the shared workflow '\" + workflow.attributes.name + \"'?\");\n });\n },\n\n /** Implement client side workflow search/filtering */\n searchWorkflow: function searchWorkflow($el_searchinput, $el_tabletr, min_querylen) {\n $el_searchinput.on(\"keyup\", function () {\n var query = $(this).val();\n // Filter when query is at least 3 characters\n // otherwise show all rows\n if (query.length >= min_querylen) {\n // Ignore the query's case using 'i'\n var regular_expression = new RegExp(query, \"i\");\n $el_tabletr.hide();\n $el_tabletr.filter(function () {\n // Apply regular expression on each row's text\n // and show when there is a match\n return regular_expression.test($(this).text());\n }).show();\n } else {\n $el_tabletr.show();\n }\n });\n },\n\n /** Ajust the position of dropdown with respect to table */\n adjustActiondropdown: function adjustActiondropdown() {\n $(this.el).on(\"show.bs.dropdown\", function () {\n $(this.el).css(\"overflow\", \"inherit\");\n });\n $(this.el).on(\"hide.bs.dropdown\", function () {\n $(this.el).css(\"overflow\", \"auto\");\n });\n },\n\n /** Template for no workflow */\n _templateNoWorkflow: function _templateNoWorkflow() {\n return '
You have no workflows.
';\n },\n\n /** Template for actions buttons */\n _templateActionButtons: function _templateActionButtons() {\n return \"
\";\n },\n\n /** Template for workflow table */\n _templateWorkflowTable: function _templateWorkflowTable() {\n var tableHtml = '
' + '
' + \"
Name
\" + \"
Tags
\" + \"
Owner
\" + \"
# of Steps
\" + \"
Published
\" + \"
Show in tools panel
\" + \"
\";\n return tableHtml + \"
Drop workflow files here to import
\";\n },\n\n /** Main template */\n _templateHeader: function _templateHeader() {\n return '
' + '
' + '' + \"
Your workflows
\" + \"
\" + \"
\";\n }\n});\n\nvar ImportWorkflowView = Backbone.View.extend({\n initialize: function initialize() {\n this.setElement(\"\");\n this.render();\n },\n\n /** Open page to import workflow */\n render: function render() {\n var self = this;\n $.getJSON(Galaxy.root + \"workflow/upload_import_workflow\", function (options) {\n self.$el.empty().append(self._mainTemplate(options));\n });\n },\n\n /** Template for the import workflow page */\n _mainTemplate: function _mainTemplate(options) {\n return \"
Click the link above to visit myExperiment and browse for Galaxy workflows.
\";\n }\n});\n\nexports.default = {\n View: WorkflowListView,\n ImportWorkflowView: ImportWorkflowView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 167 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* global Backbone */\n// workflow model\n\nvar logNamespace = \"workflow\";\n//==============================================================================\n/** @class model for a single workflow.\n * @name WorkflowItem\n * @augments Backbone.Model\n */\nvar WorkflowItem = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n urlRoot: Galaxy.root + \"api/workflows\",\n\n toJSON: function toJSON() {\n // need to overwrite this as endpoint expects the 'workflow' key in payload\n return { workflow: this.attributes };\n }\n});\n\n//==============================================================================\n/** @class collection for workflows.\n * @name WorkflowCollection\n * @augments Backbone.Collection\n */\nvar WorkflowCollection = Backbone.Collection.extend({\n model: WorkflowItem,\n url: Galaxy.root + \"api/workflows\"\n});\n\n//==============================================================================\n\nexports.default = {\n WorkflowItem: WorkflowItem,\n WorkflowCollection: WorkflowCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 168 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _gridView = __webpack_require__(12);\n\nvar _gridView2 = _interopRequireDefault(_gridView);\n\nvar _historyModel = __webpack_require__(38);\n\nvar _historyModel2 = _interopRequireDefault(_historyModel);\n\nvar _copyDialog = __webpack_require__(78);\n\nvar _copyDialog2 = _interopRequireDefault(_copyDialog);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** This class renders the grid list. */\nvar View = Backbone.View.extend({\n title: \"Histories\",\n initialize: function initialize(options) {\n var self = this;\n this.setElement($(\"\"));\n this.model = new Backbone.Model();\n _utils2.default.get({\n url: Galaxy.root + \"history/\" + options.action_id + \"?\" + $.param(Galaxy.params),\n success: function success(response) {\n response[\"dict_format\"] = true;\n _.each(response[\"operations\"], function (operation) {\n if (operation.label == \"Copy\") {\n operation.onclick = function (id) {\n self._showCopyDialog(id);\n };\n }\n });\n self.model.set(response);\n self.render();\n }\n });\n },\n\n render: function render() {\n var grid = new _gridView2.default(this.model.attributes);\n this.$el.empty().append(grid.$el);\n },\n\n _showCopyDialog: function _showCopyDialog(id) {\n var history = new _historyModel2.default.History({ id: id });\n history.fetch().fail(function () {\n alert(\"History could not be fetched. Please contact an administrator\");\n }).done(function () {\n (0, _copyDialog2.default)(history, {}).done(function () {\n if (window.parent && window.parent.Galaxy && window.parent.Galaxy.currHistoryPanel) {\n window.parent.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n window.location.reload(true);\n });\n });\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 169 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Dataset edit attributes view */\nvar View = Backbone.View.extend({\n initialize: function initialize() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.render();\n },\n\n // Fetch data for the selected dataset and\n render: function render() {\n var data_url = Galaxy.root + \"api/datasets/\" + this.model.get(\"dataset_id\");\n\n var self = this;\n\n _utils2.default.get({\n url: data_url,\n success: function success(dataset) {\n var job_url = Galaxy.root + \"api/jobs/\" + dataset.creating_job + \"?full=True\";\n _utils2.default.get({\n url: job_url,\n success: function success(job) {\n var job_url = Galaxy.root + \"api/jobs/\" + dataset.creating_job + \"?full=True\";\n self.render_error_page(self, dataset, job);\n },\n error: function error(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the job.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n error: function error(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the dataset.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n\n /** Render the view */\n render_error_page: function render_error_page(self, dataset, job) {\n self.$el.empty().append(self._templateHeader());\n self.$el.append(\"
Dataset Error
\");\n self.$el.append(\"
An error occured while running the tool \" + job.tool_id + \".
\");\n self.$el.append(\"
Tool execution generated the following messages:
\");\n self.$el.append(\"
\" + job.stderr + \"
\");\n self.$el.append(\"
Report This Error\");\n self.$el.append(\"
Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.
\");\n self.$el.append(self._getBugFormTemplate(dataset, job));\n },\n\n /** Display actions messages */\n display_message: function display_message(response, $el, doNotClear, safe) {\n if (!safe) {\n if (doNotClear) {\n $el.append(new _uiMisc2.default.Message(response).$el);\n } else {\n $el.empty().html(new _uiMisc2.default.Message(response).$el);\n }\n } else {\n if (doNotClear) {\n $el.append(new _uiMisc2.default.UnescapedMessage(response).$el);\n } else {\n $el.empty().html(new _uiMisc2.default.UnescapedMessage(response).$el);\n }\n }\n },\n\n /** Main template */\n _templateHeader: function _templateHeader() {\n return '
' + '' + \"
\";\n },\n\n /** Convert tab template */\n _getBugFormTemplate: function _getBugFormTemplate(dataset, job) {\n var self = this;\n var inputs = [{\n help: \"Your email address\",\n options: [],\n type: \"text\",\n name: \"email\",\n label: \"Your email\",\n value: Galaxy.user.get(\"email\")\n }, {\n help: \"Any additional comments you can provide regarding what you were doing at the time of the bug.\",\n options: [],\n type: \"text\",\n area: true,\n name: \"message\",\n label: \"Message\"\n }];\n\n // TODO\n /*\n if (false && response.any_public) {\n inputs.push({\n name: \"public_consent\",\n label: \"Public Disclosure Consent\",\n help:\n \"This Galaxy is configured to report to one or more error reporting backends that public to the world. By selecting 'yes', you acknowledge that this bug report will be made public.\",\n value: String(Boolean(false)),\n options: [],\n type: \"boolean\"\n });\n }\n */\n\n var form = new _formView2.default({\n title: \"Error Report\",\n inputs: inputs,\n buttons: {\n save: new _uiMisc2.default.Button({\n icon: \"fa-bug\",\n title: \"Report\",\n cls: \"ui-button btn btn-primary\",\n floating: \"clear\",\n onclick: function onclick() {\n var form_data = form.data.create();\n var url = Galaxy.root + \"api/jobs/\" + job.id + \"/error\";\n form_data.dataset_id = dataset.id;\n self.submit(form_data, url);\n }\n })\n }\n });\n return form.$el;\n },\n\n /** Make ajax request */\n submit: function submit(form_data, url) {\n var self = this;\n // Some required metadata\n $.ajax({\n type: \"POST\",\n url: url,\n data: form_data,\n success: function success(response) {\n // Clear out the div\n self.$el.empty().append(self._templateHeader());\n // And display the messages.\n response.messages.forEach(function (message) {\n self.display_message({\n status: message[1],\n message: message[0],\n persistent: true\n }, self.$(\".response-message\"), true, true);\n });\n },\n error: function error(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while saving. Please fill all the required fields and try again.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 170 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiTabs = __webpack_require__(28);\n\nvar _uiTabs2 = _interopRequireDefault(_uiTabs);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Dataset edit attributes view */\nvar View = Backbone.View.extend({\n initialize: function initialize() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.message = new _uiMisc2.default.Message({ persistent: true });\n this.tabs = this._createTabs();\n this.$el.append($(\"\").append(\"Edit dataset attributes\")).append(this.message.$el).append(\"\").append(this.tabs.$el).hide();\n this.render();\n },\n\n /** fetch data for the selected dataset and build forms */\n render: function render() {\n var self = this;\n $.ajax({\n url: Galaxy.root + \"dataset/get_edit?dataset_id=\" + self.model.get(\"dataset_id\"),\n success: function success(response) {\n !self.initial_message && self.message.update(response);\n self.initial_message = true;\n _.each(self.forms, function (form, key) {\n form.model.set(\"inputs\", response[key + \"_inputs\"]);\n form.model.set(\"hide_operations\", response[key + \"_disable\"]);\n form.render();\n });\n self.$el.show();\n },\n error: function error(response) {\n var err_msg = response.responseJSON && response.responseJSON.err_msg;\n self.message.update({\n status: \"danger\",\n message: err_msg || \"Error occured while loading the dataset.\"\n });\n }\n });\n },\n\n /** submit data to backend to update attributes */\n _submit: function _submit(operation, form) {\n var self = this;\n var data = form.data.create();\n data.dataset_id = this.model.get(\"dataset_id\");\n data.operation = operation;\n $.ajax({\n type: \"PUT\",\n url: Galaxy.root + \"dataset/set_edit\",\n data: data,\n success: function success(response) {\n self.message.update(response);\n self.render();\n self._reloadHistory();\n },\n error: function error(response) {\n var err_msg = response.responseJSON && response.responseJSON.err_msg;\n self.message.update({\n status: \"danger\",\n message: err_msg || \"Error occured while editing the dataset attributes.\"\n });\n }\n });\n },\n\n /** create tabs for different dataset attribute categories*/\n _createTabs: function _createTabs() {\n this.forms = {\n attribute: this._getAttribute(),\n conversion: this._getConversion(),\n datatype: this._getDatatype(),\n permission: this._getPermission()\n };\n var tabs = new _uiTabs2.default.View();\n tabs.add({\n id: \"attribute\",\n title: \"Attributes\",\n icon: \"fa fa-bars\",\n tooltip: \"Edit dataset attributes\",\n $el: this.forms.attribute.$el\n });\n tabs.add({\n id: \"convert\",\n title: \"Convert\",\n icon: \"fa-gear\",\n tooltip: \"Convert to new format\",\n $el: this.forms.conversion.$el\n });\n tabs.add({\n id: \"datatype\",\n title: \"Datatypes\",\n icon: \"fa-database\",\n tooltip: \"Change data type\",\n $el: this.forms.datatype.$el\n });\n tabs.add({\n id: \"permissions\",\n title: \"Permissions\",\n icon: \"fa-user\",\n tooltip: \"Permissions\",\n $el: this.forms.permission.$el\n });\n return tabs;\n },\n\n /** edit main attributes form */\n _getAttribute: function _getAttribute() {\n var self = this;\n var form = new _formView2.default({\n title: \"Edit attributes\",\n operations: {\n submit_attributes: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Save attributes of the dataset.\",\n icon: \"fa-floppy-o\",\n title: \"Save\",\n onclick: function onclick() {\n self._submit(\"attributes\", form);\n }\n }),\n submit_autodetect: new _uiMisc2.default.ButtonIcon({\n tooltip: \"This will inspect the dataset and attempt to correct the values of fields if they are not accurate.\",\n icon: \"fa-undo\",\n title: \"Auto-detect\",\n onclick: function onclick() {\n self._submit(\"autodetect\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** datatype conversion form */\n _getConversion: function _getConversion() {\n var self = this;\n var form = new _formView2.default({\n title: \"Convert to new format\",\n operations: {\n submit_conversion: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Convert the datatype to a new format.\",\n title: \"Convert datatype\",\n icon: \"fa-exchange\",\n onclick: function onclick() {\n self._submit(\"conversion\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** change datatype form */\n _getDatatype: function _getDatatype() {\n var self = this;\n var form = new _formView2.default({\n title: \"Change datatype\",\n operations: {\n submit_datatype: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Change the datatype to a new type.\",\n title: \"Change datatype\",\n icon: \"fa-exchange\",\n onclick: function onclick() {\n self._submit(\"datatype\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** dataset permissions form */\n _getPermission: function _getPermission() {\n var self = this;\n var form = new _formView2.default({\n title: \"Manage dataset permissions\",\n operations: {\n submit_permission: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Save permissions.\",\n title: \"Save permissions\",\n icon: \"fa-floppy-o \",\n onclick: function onclick() {\n self._submit(\"permission\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** reload Galaxy's history after updating dataset's attributes */\n _reloadHistory: function _reloadHistory() {\n if (window.Galaxy) {\n window.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ })\n],[137]);\n\n\n// WEBPACK FOOTER //\n// analysis.bundled.js","/**\n * Popover wrapper\n */\nimport Utils from \"utils/utils\";\nvar View = Backbone.View.extend({\n optionsDefault: {\n with_close: true,\n title: null,\n placement: \"top\",\n container: \"body\",\n body: null\n },\n\n initialize: function(options) {\n this.setElement(this._template());\n this.uid = Utils.uid();\n this.options = _.defaults(options || {}, this.optionsDefault);\n this.options.container.parent().append(this.el);\n this.$title = this.$(\".popover-title-label\");\n this.$close = this.$(\".popover-close\");\n this.$body = this.$(\".popover-content\");\n\n // add initial content\n this.options.body && this.append(this.options.body);\n\n // add event to hide if click is outside of popup and not on container\n var self = this;\n $(\"body\").on(`mousedown.${this.uid}`, e => {\n // the 'is' for buttons that trigger popups\n // the 'has' for icons within a button that triggers a popup\n self.visible &&\n !$(self.options.container).is(e.target) &&\n !$(self.el).is(e.target) &&\n $(self.el).has(e.target).length === 0 &&\n self.hide();\n });\n },\n\n /**\n * Render popover\n */\n render: function() {\n this.$title.html(this.options.title);\n this.$el\n .removeClass()\n .addClass(\"ui-popover popover fade in\")\n .addClass(this.options.placement);\n this.$el.css(this._get_placement(this.options.placement));\n\n // configure close option\n var self = this;\n if (this.options.with_close) {\n this.$close\n .on(\"click\", () => {\n self.hide();\n })\n .show();\n } else {\n this.$close.off().hide();\n }\n },\n\n /**\n * Set the popover title\n * @params{ String } newTitle - New popover title\n */\n title: function(newTitle) {\n if (newTitle !== undefined) {\n this.options.title = newTitle;\n this.$title.html(newTitle);\n }\n },\n\n /**\n * Show popover\n */\n show: function() {\n this.render();\n this.$el.show();\n this.visible = true;\n },\n\n /**\n * Hide popover\n */\n hide: function() {\n this.$el.hide();\n this.visible = false;\n },\n\n /**\n * Append new content to the popover\n * @params{ Object } $el - Dom element\n */\n append: function($el) {\n this.$body.append($el);\n },\n\n /**\n * Remove all content\n */\n empty: function() {\n this.$body.empty();\n },\n\n /**\n * Remove popover\n */\n remove: function() {\n $(\"body\").off(`mousedown.${this.uid}`);\n this.$el.remove();\n },\n\n /**\n * Improve popover location/placement\n */\n _get_placement: function(placement) {\n // get popover dimensions\n var width = this._get_width(this.$el);\n var height = this.$el.height();\n\n // get container details\n var $container = this.options.container;\n var container_width = this._get_width($container);\n var container_height = this._get_height($container);\n var container_position = $container.position();\n\n // get position\n var top;\n\n var left;\n top = left = 0;\n if ([\"top\", \"bottom\"].indexOf(placement) != -1) {\n left = container_position.left - width + (container_width + width) / 2;\n switch (placement) {\n case \"top\":\n top = container_position.top - height - 5;\n break;\n case \"bottom\":\n top = container_position.top + container_height + 5;\n break;\n }\n } else {\n top = container_position.top - height + (container_height + height) / 2;\n switch (placement) {\n case \"right\":\n left = container_position.left + container_width;\n break;\n }\n }\n return { top: top, left: left };\n },\n\n /**\n * Returns padding/margin corrected width\n */\n _get_width: function($el) {\n return (\n $el.width() +\n parseInt($el.css(\"padding-left\")) +\n parseInt($el.css(\"margin-left\")) +\n parseInt($el.css(\"padding-right\")) +\n parseInt($el.css(\"margin-right\"))\n );\n },\n\n /**\n * Returns padding corrected height\n */\n _get_height: function($el) {\n return $el.height() + parseInt($el.css(\"padding-top\")) + parseInt($el.css(\"padding-bottom\"));\n },\n\n /**\n * Return the popover template\n */\n _template: function(options) {\n return (\n '
' +\n '
' +\n '
' +\n '
' +\n '' +\n \"
\" +\n '
' +\n \"
\"\n );\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/ui/ui-popover.js","//==============================================================================\n/** Map of possible HDA/collection/job states to their string equivalents.\n * A port of galaxy.model.Dataset.states.\n */\nvar STATES = {\n // NOT ready states\n /** is uploading and not ready */\n UPLOAD: \"upload\",\n /** the job that will produce the dataset queued in the runner */\n QUEUED: \"queued\",\n /** the job that will produce the dataset is running */\n RUNNING: \"running\",\n /** metadata for the dataset is being discovered/set */\n SETTING_METADATA: \"setting_metadata\",\n\n // ready states\n /** was created without a tool */\n NEW: \"new\",\n /** has no data */\n EMPTY: \"empty\",\n /** has successfully completed running */\n OK: \"ok\",\n\n /** the job that will produce the dataset paused */\n PAUSED: \"paused\",\n /** metadata discovery/setting failed or errored (but otherwise ok) */\n FAILED_METADATA: \"failed_metadata\",\n //TODO: not in trans.app.model.Dataset.states - is in database\n /** not accessible to the current user (i.e. due to permissions) */\n NOT_VIEWABLE: \"noPermission\",\n /** deleted while uploading */\n DISCARDED: \"discarded\",\n /** the tool producing this dataset failed */\n ERROR: \"error\"\n};\n\nSTATES.READY_STATES = [\n STATES.OK,\n STATES.EMPTY,\n STATES.PAUSED,\n STATES.FAILED_METADATA,\n STATES.NOT_VIEWABLE,\n STATES.DISCARDED,\n STATES.ERROR\n];\n\nSTATES.NOT_READY_STATES = [STATES.UPLOAD, STATES.QUEUED, STATES.RUNNING, STATES.SETTING_METADATA, STATES.NEW];\n\n//==============================================================================\nexport default STATES;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/states.js","// dependencies\nimport Utils from \"utils/utils\";\n/**\n * A plugin for initializing select2 input items.\n * Make sure the select2 library itself is loaded beforehand.\n * Also the element to which select2 will be appended has to\n * be created before select2 initialization (and passed as option).\n */\nvar View = Backbone.View.extend({\n // options\n optionsDefault: {\n css: \"\",\n placeholder: \"No data available\",\n data: [],\n value: null,\n multiple: false,\n minimumInputLength: 0,\n // example format of initial data: \"id:name,55:anotherrole@role.com,27:role@role.com\"\n initialData: \"\"\n },\n\n // initialize\n initialize: function(options) {\n // configure options\n this.options = Utils.merge(options, this.optionsDefault);\n\n // create new element\n this.setElement(this._template(this.options));\n\n // check if container exists\n if (!this.options.container) {\n console.log(\"ui-select::initialize() : container not specified.\");\n return;\n }\n\n // add to dom\n this.options.container.append(this.$el);\n\n // link selection dictionary\n this.select_data = this.options.data;\n\n // refresh\n this._refresh();\n\n if (!this.options.multiple) {\n // initial value\n if (this.options.value) {\n this._setValue(this.options.value);\n }\n\n // add change event\n var self = this;\n if (this.options.onchange) {\n this.$el.on(\"change\", () => {\n self.options.onchange(self.value());\n });\n }\n }\n },\n\n // value\n value: function(new_value) {\n // get current id/value\n var before = this._getValue();\n\n // check if new_value is defined\n if (new_value !== undefined) {\n this._setValue(new_value);\n }\n\n // get current id/value\n var after = this._getValue();\n\n // fire onchange\n if (after != before && this.options.onchange) {\n this.options.onchange(after);\n }\n\n // return current value\n return after;\n },\n\n // label\n text: function() {\n return this.$el.select2(\"data\").text;\n },\n\n // disabled\n disabled: function() {\n return !this.$el.select2(\"enable\");\n },\n\n // enable\n enable: function() {\n this.$el.select2(\"enable\", true);\n },\n\n // disable\n disable: function() {\n this.$el.select2(\"enable\", false);\n },\n\n // add\n add: function(options) {\n // add options\n this.select_data.push({\n id: options.id,\n text: options.text\n });\n\n // refresh\n this._refresh();\n },\n\n // remove\n del: function(id) {\n // search option\n var index = this._getIndex(id);\n\n // check if found\n if (index != -1) {\n // remove options\n this.select_data.splice(index, 1);\n\n // refresh\n this._refresh();\n }\n },\n\n // remove\n remove: function() {\n this.$el.select2(\"destroy\");\n },\n\n // update\n update: function(options) {\n // copy options\n this.select_data = [];\n for (var key in options.data) {\n this.select_data.push(options.data[key]);\n }\n\n // refresh\n this._refresh();\n },\n\n // refresh\n _refresh: function() {\n // add select2 data based on type of input\n if (!this.options.multiple) {\n var selected = this._getValue();\n var select_opt = {\n data: this.select_data,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n dropdownAutoWidth: true\n };\n this.$el.select2(select_opt);\n // select previous value (if exists)\n this._setValue(selected);\n } else {\n var select_opt = {\n multiple: this.options.multiple,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n minimumInputLength: this.options.minimumInputLength,\n ajax: this.options.ajax,\n dropdownCssClass: this.options.dropdownCssClass,\n escapeMarkup: this.options.escapeMarkup,\n formatResult: this.options.formatResult,\n formatSelection: this.options.formatSelection,\n initSelection: this.options.initSelection,\n initialData: this.options.initialData\n };\n this.$el.select2(select_opt);\n }\n },\n\n // get index\n _getIndex: function(value) {\n // returns the index of the searched value\n _.findIndex(this.select_data, { id: value });\n },\n\n // get value\n _getValue: function() {\n return this.$el.select2(\"val\");\n },\n\n // set value\n _setValue: function(new_value) {\n var index = this._getIndex(new_value);\n if (index == -1) {\n if (this.select_data.length > 0) {\n new_value = this.select_data[0].id;\n }\n }\n this.$el.select2(\"val\", new_value);\n },\n\n // element\n _template: function(options) {\n return ``;\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/ui/ui-select.js","import jQuery from \"jquery\";\n(\"use_strict\");\n\nvar $ = jQuery;\n//============================================================================\n/** Returns a jQuery object containing a clickable font-awesome button.\n * options:\n * tooltipConfig : option map for bootstrap tool tip\n * classes : array of class names (will always be classed as icon-btn)\n * disabled : T/F - add the 'disabled' class?\n * title : tooltip/title string\n * target : optional href target\n * href : optional href\n * faIcon : which font awesome icon to use\n * onclick : function to call when the button is clicked\n */\nvar faIconButton = options => {\n options = options || {};\n options.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n\n options.classes = [\"icon-btn\"].concat(options.classes || []);\n if (options.disabled) {\n options.classes.push(\"disabled\");\n }\n\n var html = [\n '',\n // could go with something less specific here - like 'html'\n '',\n \"\"\n ].join(\"\");\n var $button = $(html).tooltip(options.tooltipConfig);\n if (_.isFunction(options.onclick)) {\n $button.click(options.onclick);\n }\n return $button;\n};\n\n//============================================================================\nexport default faIconButton;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/ui/fa-icon-button.js","var Model = Backbone.Model.extend({\n defaults: {\n extension: \"auto\",\n genome: \"?\",\n url_paste: \"\",\n status: \"init\",\n info: null,\n file_name: \"\",\n file_mode: \"\",\n file_size: 0,\n file_type: null,\n file_path: \"\",\n file_data: null,\n percentage: 0,\n space_to_tab: false,\n to_posix_lines: true,\n enabled: true\n },\n reset: function(attr) {\n this.clear()\n .set(this.defaults)\n .set(attr);\n }\n});\nvar Collection = Backbone.Collection.extend({ model: Model });\nexport default { Model: Model, Collection: Collection };\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-model.js","import baseMVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n// =============================================================================\n/** A view on any model that has a 'tags' attribute (a list of tag strings)\n * Incorporates the select2 jQuery plugin for tags display/editing:\n * http://ivaynberg.github.io/select2/\n */\nvar TagsEditor = Backbone.View.extend(baseMVC.LoggableMixin)\n .extend(baseMVC.HiddenUntilActivatedViewMixin)\n .extend({\n tagName: \"div\",\n className: \"tags-display\",\n select_width: \"100%\",\n events: {},\n\n /** Set up listeners, parse options */\n initialize: function(options) {\n //console.debug( this, options );\n // only listen to the model only for changes to tags - re-render\n this.show_editor = false;\n if (options.usePrompt === false) {\n this.label = \"\";\n } else {\n this.label = ``;\n }\n this.workflow_mode = options.workflow_mode || false;\n if (this.workflow_mode) {\n this.events.click = \"showEditor\";\n this.events.keydown = \"keydownHandler\";\n }\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function() {\n var self = this;\n if (this.workflow_mode) {\n this.$el.html(this._workflowTemplate());\n } else {\n this.$el.html(this._defaultTemplate());\n }\n this.$input().select2({\n placeholder: \"Add tags\",\n width: this.workflow_mode ? this.width : this.select_width,\n tags: function() {\n // initialize possible tags in the dropdown based on all the tags the user has used so far\n return self._getTagsUsed();\n }\n });\n\n this._setUpBehaviors();\n return this;\n },\n\n _hashToName: function(tag) {\n if (tag.startsWith(\"#\")) {\n return `name:${tag.slice(1)}`;\n }\n return tag;\n },\n\n _nameToHash: function(tag) {\n if (tag.startsWith(\"name:\")) {\n tag = `#${tag.slice(5)}`;\n }\n return tag;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _defaultTemplate: function() {\n return [this.label, this._renderEditor()].join(\"\");\n },\n\n _workflowTemplate: function() {\n // Shows labels by default, event handler controls whether we show tags or editor\n return [this.show_editor ? this._renderEditor() : this._renderTags()].join(\" \");\n },\n\n keydownHandler: function(e) {\n switch (e.which) {\n // esc\n case 27:\n // hide the tag editor when pressing escape\n this.hideEditor();\n break;\n }\n },\n\n showEditor: function() {\n this.show_editor = true;\n this.render();\n },\n\n hideEditor: function() {\n this.show_editor = false;\n this.render();\n },\n\n _renderEditor: function() {\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n return ``;\n },\n\n _renderTags: function() {\n var tags = this.model.get(\"tags\");\n var addButton = \"static/images/fugue/tag--plus.png\";\n var renderedArray = [];\n _.each(tags, tag => {\n tag = tag.indexOf(\"name:\") == 0 ? tag.slice(5) : tag;\n var renderString = `${tag}`;\n renderedArray.push(renderString);\n });\n if (renderedArray.length === 0) {\n // If there are no tags to render we just show the add-tag-button\n renderedArray.push(``);\n }\n return renderedArray.join(\" \");\n },\n\n /** @returns {String} the sorted, comma-separated tags from the model */\n tagsToCSV: function() {\n var self = this;\n var tagsArray = this.model.get(\"tags\");\n if (!_.isArray(tagsArray) || _.isEmpty(tagsArray)) {\n return \"\";\n }\n return tagsArray\n .map(tag => _.escape(self._nameToHash(tag)))\n .sort()\n .join(\",\");\n },\n\n /** @returns {jQuery} the input for this view */\n $input: function() {\n return this.$el.find(\"input.tags-input\");\n },\n\n /** @returns {String[]} all tags used by the current user */\n _getTagsUsed: function() {\n //TODO: global\n var self = this;\n return _.map(Galaxy.user.get(\"tags_used\"), self._nameToHash);\n },\n\n /** set up any event listeners on the view's DOM (mostly handled by select2) */\n _setUpBehaviors: function() {\n var self = this;\n this.$input().on(\"change\", event => {\n // Modify any 'hashtag' 'nametags'\n event.val = _.map(event.val, self._hashToName);\n // save the model's tags in either remove or added event\n self.model.save({ tags: event.val });\n // if it's new, add the tag to the users tags\n if (event.added) {\n //??: solve weird behavior in FF on test.galaxyproject.org where\n // event.added.text is string object: 'String{ 0=\"o\", 1=\"n\", 2=\"e\" }'\n self._addNewTagToTagsUsed(`${event.added.text}`);\n }\n });\n },\n\n /** add a new tag (if not already there) to the list of all tags used by the user\n * @param {String} newTag the tag to add to the list of used\n */\n _addNewTagToTagsUsed: function(newTag) {\n //TODO: global\n var tagsUsed = Galaxy.user.get(\"tags_used\");\n if (!_.contains(tagsUsed, newTag)) {\n tagsUsed.push(newTag);\n tagsUsed.sort();\n Galaxy.user.set(\"tags_used\", tagsUsed);\n }\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function() {\n this.$input.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function() {\n return [\"TagsEditor(\", `${this.model}`, \")\"].join(\"\");\n }\n });\n\nexport default {\n TagsEditor: TagsEditor\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/tag.js","import jQuery from \"jquery\";\nvar $ = jQuery;\nimport QUERY_STRING from \"utils/query-string-parsing\";\nimport Ui from \"mvc/ui/ui-misc\";\n\nvar Router = Backbone.Router.extend({\n // TODO: not many client routes at this point - fill and remove from server.\n // since we're at root here, this may be the last to be routed entirely on the client.\n initialize: function(page, options) {\n this.page = page;\n this.options = options;\n },\n\n /** helper to push a new navigation state */\n push: function(url, data) {\n data = data || {};\n data.__identifer = Math.random()\n .toString(36)\n .substr(2);\n if (!$.isEmptyObject(data)) {\n url += url.indexOf(\"?\") == -1 ? \"?\" : \"&\";\n url += $.param(data, true);\n }\n Galaxy.params = data;\n this.navigate(url, { trigger: true });\n },\n\n /** override to parse query string into obj and send to each route */\n execute: function(callback, args, name) {\n Galaxy.debug(\"router execute:\", callback, args, name);\n var queryObj = QUERY_STRING.parse(args.pop());\n args.push(queryObj);\n if (callback) {\n if (this.authenticate(args, name)) {\n callback.apply(this, args);\n } else {\n this.access_denied();\n }\n }\n },\n\n authenticate: function(args, name) {\n return true;\n },\n\n access_denied: function() {\n this.page.display(\n new Ui.Message({\n status: \"danger\",\n message: \"You must be logged in with proper credentials to make this request.\",\n persistent: true\n })\n );\n }\n});\n\nexport default Router;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/layout/router.js","/** This renders the content of the settings popup, allowing users to specify flags i.e. for space-to-tab conversion **/\nimport Utils from \"utils/utils\";\nexport default Backbone.View.extend({\n options: {\n class_check: \"fa-check-square-o\",\n class_uncheck: \"fa-square-o\",\n parameters: [\n {\n id: \"space_to_tab\",\n title: \"Convert spaces to tabs\"\n },\n {\n id: \"to_posix_lines\",\n title: \"Use POSIX standard\"\n }\n ]\n },\n\n initialize: function(options) {\n var self = this;\n this.model = options.model;\n this.setElement($(\"\").addClass(\"upload-settings\"));\n this.$el.append($(\"\").addClass(\"upload-settings-cover\"));\n this.$el.append(\n $(\"
\").append(parameter.title))\n );\n });\n this.$cover[(this.model.get(\"enabled\") && \"hide\") || \"show\"]();\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-settings.js","/** This renders the content of the ftp popup **/\nimport Utils from \"utils/utils\";\nexport default Backbone.View.extend({\n initialize: function(options) {\n var self = this;\n this.model = new Backbone.Model({\n cls: \"upload-ftp\",\n class_add: \"upload-icon-button fa fa-square-o\",\n class_remove: \"upload-icon-button fa fa-check-square-o\",\n class_partial: \"upload-icon-button fa fa-minus-square-o\",\n help_enabled: true,\n help_text: `This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at ${\n options.ftp_upload_site\n } using your Galaxy credentials.`,\n collection: null,\n onchange: function() {},\n onadd: function() {},\n onremove: function() {}\n }).set(options);\n this.collection = this.model.get(\"collection\");\n this.setElement(this._template());\n this.$content = this.$(\".upload-ftp-content\");\n this.$wait = this.$(\".upload-ftp-wait\");\n this.$help = this.$(\".upload-ftp-help\");\n this.$number = this.$(\".upload-ftp-number\");\n this.$disk = this.$(\".upload-ftp-disk\");\n this.$body = this.$(\".upload-ftp-body\");\n this.$warning = this.$(\".upload-ftp-warning\");\n this.$select = this.$(\".upload-ftp-select-all\");\n this.render();\n },\n\n render: function() {\n var self = this;\n this.$wait.show();\n this.$content.hide();\n this.$warning.hide();\n this.$help.hide();\n $.ajax({\n url: `${Galaxy.root}api/remote_files`,\n method: \"GET\",\n success: function(ftp_files) {\n self.model.set(\"ftp_files\", ftp_files);\n self._index();\n self._renderTable();\n },\n error: function() {\n self._renderTable();\n }\n });\n },\n\n /** Fill table with ftp entries */\n _renderTable: function() {\n var self = this;\n var ftp_files = this.model.get(\"ftp_files\");\n this.rows = [];\n if (ftp_files && ftp_files.length > 0) {\n this.$body.empty();\n var size = 0;\n _.each(ftp_files, ftp_file => {\n self.rows.push(self._renderRow(ftp_file));\n size += ftp_file.size;\n });\n this.$number.html(`${ftp_files.length} files`);\n this.$disk.html(Utils.bytesToString(size, true));\n if (this.collection) {\n this.$(\"._has_collection\").show();\n this.$select\n .addClass(this.model.get(\"class_add\"))\n .off()\n .on(\"click\", () => {\n self._all();\n });\n this._refresh();\n }\n this.$content.show();\n } else {\n this.$warning.show();\n }\n this.model.get(\"help_enabled\") && this.$help.show();\n this.$wait.hide();\n },\n\n /** Add row */\n _renderRow: function(ftp_file) {\n var self = this;\n var options = this.model.attributes;\n var $it = $(this._templateRow(ftp_file));\n var $icon = $it.find(\".icon\");\n this.$body.append($it);\n if (this.collection) {\n var model_index = this.ftp_index[ftp_file.path];\n $icon.addClass(model_index === undefined ? options.class_add : options.class_remove);\n $it.on(\"click\", () => {\n self._switch($icon, ftp_file);\n self._refresh();\n });\n } else {\n $it.on(\"click\", () => {\n options.onchange(ftp_file);\n });\n }\n return $icon;\n },\n\n /** Create ftp index */\n _index: function() {\n var self = this;\n this.ftp_index = {};\n this.collection &&\n this.collection.each(model => {\n if (model.get(\"file_mode\") == \"ftp\") {\n self.ftp_index[model.get(\"file_path\")] = model.id;\n }\n });\n },\n\n /** Select all event handler */\n _all: function() {\n var options = this.model.attributes;\n var ftp_files = this.model.get(\"ftp_files\");\n var add = this.$select.hasClass(options.class_add);\n for (var index in ftp_files) {\n var ftp_file = ftp_files[index];\n var model_index = this.ftp_index[ftp_file.path];\n if ((model_index === undefined && add) || (model_index !== undefined && !add)) {\n this._switch(this.rows[index], ftp_file);\n }\n }\n this._refresh();\n },\n\n /** Handle collection changes */\n _switch: function($icon, ftp_file) {\n $icon.removeClass();\n var options = this.model.attributes;\n var model_index = this.ftp_index[ftp_file.path];\n if (model_index === undefined) {\n var new_index = options.onadd(ftp_file);\n $icon.addClass(options.class_remove);\n this.ftp_index[ftp_file.path] = new_index;\n } else {\n options.onremove(model_index);\n $icon.addClass(options.class_add);\n this.ftp_index[ftp_file.path] = undefined;\n }\n },\n\n /** Refresh select all button state */\n _refresh: function() {\n var counts = _.reduce(\n this.ftp_index,\n (memo, element) => {\n element !== undefined && memo++;\n return memo;\n },\n 0\n );\n this.$select.removeClass();\n if (counts == 0) {\n this.$select.addClass(this.model.get(\"class_add\"));\n } else {\n this.$select.addClass(\n counts == this.rows.length ? this.model.get(\"class_remove\") : this.model.get(\"class_partial\")\n );\n }\n },\n\n /** Template of row */\n _templateRow: function(options) {\n return `
${_.escape(\n options.path\n )}
${Utils.bytesToString(options.size)}
${\n options.ctime\n }
`;\n },\n\n /** Template of main view */\n _template: function() {\n return `
${this.model.get(\n \"help_text\"\n )}
Available files:
Name
Size
Created
Your FTP directory does not contain any files.
`;\n (\"
\");\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-ftp.js","/** This renders a popover with extension details **/\nimport Utils from \"utils/utils\";\nimport Popover from \"mvc/ui/ui-popover\";\nexport default Backbone.View.extend({\n initialize: function(options) {\n this.model = new Backbone.Model(options);\n this.setElement(\"\");\n this.render();\n },\n\n render: function() {\n var self = this;\n var options = this.model.attributes;\n var description = _.findWhere(options.list, {\n id: options.extension\n });\n this.extension_popup && this.extension_popup.remove();\n this.extension_popup = new Popover.View({\n placement: options.placement || \"bottom\",\n container: options.$el\n });\n this.extension_popup.title(options.title);\n this.extension_popup.empty();\n this.extension_popup.append(this._templateDescription(description));\n this.extension_popup.show();\n },\n\n /** Template for extensions description */\n _templateDescription: function(options) {\n if (options.description) {\n var tmpl = options.description;\n if (options.description_url) {\n tmpl += ` (read more)`;\n }\n return tmpl;\n } else {\n return \"There is no description available for this file extension.\";\n }\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-extension.js","/*\n galaxy upload plugins - requires FormData and XMLHttpRequest\n*/\n($ => {\n // add event properties\n jQuery.event.props.push(\"dataTransfer\");\n\n /**\n Posts file data to the API\n */\n $.uploadpost = config => {\n // parse options\n var cnf = $.extend(\n {},\n {\n data: {},\n success: function() {},\n error: function() {},\n progress: function() {},\n url: null,\n maxfilesize: 2048,\n error_filesize: \"File exceeds 2GB. Please use a FTP client.\",\n error_default: \"Please make sure the file is available.\",\n error_server: \"Upload request failed.\",\n error_login: \"Uploads require you to log in.\"\n },\n config\n );\n\n // link data\n var data = cnf.data;\n\n // check errors\n if (data.error_message) {\n cnf.error(data.error_message);\n return;\n }\n\n // construct form data\n var form = new FormData();\n for (var key in data.payload) {\n form.append(key, data.payload[key]);\n }\n\n // add files to submission\n var sizes = 0;\n for (var key in data.files) {\n var d = data.files[key];\n form.append(d.name, d.file, d.file.name);\n sizes += d.file.size;\n }\n\n // check file size, unless it's an ftp file\n if (sizes > 1048576 * cnf.maxfilesize) {\n cnf.error(cnf.error_filesize);\n return;\n }\n\n // prepare request\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", cnf.url, true);\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n\n // captures state changes\n xhr.onreadystatechange = () => {\n // check for request completed, server connection closed\n if (xhr.readyState == xhr.DONE) {\n // parse response\n var response = null;\n var extra_info = \"\";\n if (xhr.responseText) {\n try {\n response = jQuery.parseJSON(xhr.responseText);\n extra_info = response.err_msg;\n } catch (e) {\n response = xhr.responseText;\n extra_info = response;\n }\n }\n // pass any error to the error option\n if (xhr.status < 200 || xhr.status > 299) {\n var text = xhr.statusText;\n if (xhr.status == 403) {\n text = cnf.error_login;\n } else if (xhr.status == 0) {\n text = cnf.error_server;\n } else if (!text) {\n text = cnf.error_default;\n }\n cnf.error(`${text} (${xhr.status}). ${extra_info}`);\n } else {\n cnf.success(response);\n }\n }\n };\n\n // prepare upload progress\n xhr.upload.addEventListener(\n \"progress\",\n e => {\n if (e.lengthComputable) {\n cnf.progress(Math.round(e.loaded * 100 / e.total));\n }\n },\n false\n );\n\n // send request\n Galaxy.emit.debug(\"uploadbox::uploadpost()\", \"Posting following data.\", cnf);\n xhr.send(form);\n };\n\n /**\n Handles the upload events drag/drop etc.\n */\n $.fn.uploadinput = function(options) {\n // initialize\n var el = this;\n var opts = $.extend(\n {},\n {\n ondragover: function() {},\n ondragleave: function() {},\n onchange: function() {},\n multiple: false\n },\n options\n );\n\n // append hidden upload field\n var $input = $(``);\n el.append(\n $input.change(function(e) {\n opts.onchange(e.target.files);\n $(this).val(\"\");\n })\n );\n\n // drag/drop events\n el.on(\"drop\", e => {\n opts.ondragleave(e);\n if (e.dataTransfer) {\n opts.onchange(e.dataTransfer.files);\n e.preventDefault();\n }\n });\n el.on(\"dragover\", e => {\n e.preventDefault();\n opts.ondragover(e);\n });\n el.on(\"dragleave\", e => {\n e.stopPropagation();\n opts.ondragleave(e);\n });\n\n // exports\n return {\n dialog: function() {\n $input.trigger(\"click\");\n }\n };\n };\n\n /**\n Handles the upload queue and events such as drag/drop etc.\n */\n $.fn.uploadbox = function(options) {\n // parse options\n var opts = $.extend(\n {},\n {\n dragover: function() {},\n dragleave: function() {},\n announce: function(d) {},\n initialize: function(d) {},\n progress: function(d, m) {},\n success: function(d, m) {},\n error: function(d, m) {\n alert(m);\n },\n complete: function() {}\n },\n options\n );\n\n // file queue\n var queue = {};\n\n // queue index/length counter\n var queue_index = 0;\n var queue_length = 0;\n\n // indicates if queue is currently running\n var queue_running = false;\n var queue_stop = false;\n\n // element\n var uploadinput = $(this).uploadinput({\n multiple: true,\n onchange: function(files) {\n add(files);\n },\n ondragover: options.ondragover,\n ondragleave: options.ondragleave\n });\n\n // add new files to upload queue\n function add(files) {\n if (files && files.length && !queue_running) {\n var index = undefined;\n _.each(files, (file, key) => {\n if (\n file.mode !== \"new\" &&\n _.filter(queue, f => f.name === file.name && f.size === file.size).length\n ) {\n file.duplicate = true;\n }\n });\n _.each(files, file => {\n if (!file.duplicate) {\n index = String(queue_index++);\n queue[index] = file;\n opts.announce(index, queue[index]);\n queue_length++;\n }\n });\n return index;\n }\n }\n\n // remove file from queue\n function remove(index) {\n if (queue[index]) {\n delete queue[index];\n queue_length--;\n }\n }\n\n // process an upload, recursive\n function process() {\n // validate\n if (queue_length == 0 || queue_stop) {\n queue_stop = false;\n queue_running = false;\n opts.complete();\n return;\n } else {\n queue_running = true;\n }\n\n // get an identifier from the queue\n var index = -1;\n for (var key in queue) {\n index = key;\n break;\n }\n\n // get current file from queue\n var file = queue[index];\n\n // remove from queue\n remove(index);\n\n // create and submit data\n $.uploadpost({\n url: opts.url,\n data: opts.initialize(index),\n success: function(message) {\n opts.success(index, message);\n process();\n },\n error: function(message) {\n opts.error(index, message);\n process();\n },\n progress: function(percentage) {\n opts.progress(index, percentage);\n }\n });\n }\n\n /*\n public interface\n */\n\n // open file browser for selection\n function select() {\n uploadinput.dialog();\n }\n\n // remove all entries from queue\n function reset(index) {\n for (index in queue) {\n remove(index);\n }\n }\n\n // initiate upload process\n function start() {\n if (!queue_running) {\n queue_running = true;\n process();\n }\n }\n\n // stop upload process\n function stop() {\n queue_stop = true;\n }\n\n // set options\n function configure(options) {\n opts = $.extend({}, opts, options);\n return opts;\n }\n\n // verify browser compatibility\n function compatible() {\n return window.File && window.FormData && window.XMLHttpRequest && window.FileList;\n }\n\n // export functions\n return {\n select: select,\n add: add,\n remove: remove,\n start: start,\n stop: stop,\n reset: reset,\n configure: configure,\n compatible: compatible\n };\n };\n})(jQuery);\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/uploadbox.js","import HDCA from \"mvc/history/hdca-model\";\nimport STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport baseCreator from \"mvc/collection/base-creator\";\nimport UI_MODAL from \"mvc/ui/ui-modal\";\nimport naturalSort from \"utils/natural-sort\";\nimport _l from \"utils/localization\";\nimport \"ui/hoverhighlight\";\n\nvar logNamespace = \"collections\";\n\n/*==============================================================================\nTODO:\n use proper Element model and not just json\n straighten out createFn, collection.createHDCA\n possibly stop using modals for this\n It would be neat to do a drag and drop\n\n==============================================================================*/\n/** A view for both DatasetDCEs and NestedDCDCEs\n * (things that implement collection-model:DatasetCollectionElementMixin)\n */\nvar DatasetCollectionElementView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))\n tagName: \"li\",\n className: \"collection-element\",\n\n initialize: function(attributes) {\n this.element = attributes.element || {};\n this.selected = attributes.selected || false;\n },\n\n render: function() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el\n .attr(\"data-element-id\", this.element.id)\n .attr(\"draggable\", true)\n .html(this.template({ element: this.element }))\n .get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n if (this.selected) {\n this.$el.addClass(\"selected\");\n }\n return this;\n },\n\n //TODO: lots of unused space in the element - possibly load details and display them horiz.\n template: _.template(\n [\n '',\n \"<%- element.name %>\",\n \"\",\n '\"\n ].join(\"\")\n ),\n\n /** select this element and pub */\n select: function(toggle) {\n this.$el.toggleClass(\"selected\", toggle);\n this.trigger(\"select\", {\n source: this,\n selected: this.$el.hasClass(\"selected\")\n });\n },\n\n /** animate the removal of this element and pub */\n discard: function() {\n var view = this;\n var parentWidth = this.$el.parent().width();\n this.$el.animate({ \"margin-right\": parentWidth }, \"fast\", () => {\n view.trigger(\"discard\", {\n source: view\n });\n view.destroy();\n });\n },\n\n /** remove the DOM and any listeners */\n destroy: function() {\n this.off();\n this.$el.remove();\n },\n\n events: {\n click: \"_click\",\n \"click .name\": \"_clickName\",\n \"click .discard\": \"_clickDiscard\",\n\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** select when the li is clicked */\n _click: function(ev) {\n ev.stopPropagation();\n this.select(ev);\n },\n\n /** rename a pair when the name is clicked */\n _clickName: function(ev) {\n ev.stopPropagation();\n ev.preventDefault();\n\n var promptString = [\n _l(\"Enter a new name for the element\"),\n \":\\n(\",\n _l(\"Note that changing the name here will not rename the dataset\"),\n \")\"\n ].join(\"\");\n\n var response = prompt(`${_l(\"Enter a new name for the element\")}:`, this.element.name);\n\n if (response) {\n this.element.name = response;\n this.render();\n }\n //TODO: cancelling with ESC leads to closure of the creator...\n },\n\n /** discard when the discard button is clicked */\n _clickDiscard: function(ev) {\n ev.stopPropagation();\n this.discard();\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.element));\n\n this.$el.addClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragstart\", [this]);\n },\n\n /** dragging for re-ordering */\n _dragend: function(ev) {\n this.$el.removeClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function() {\n return \"DatasetCollectionElementView()\";\n }\n});\n\n// ============================================================================\n/** An interface for building collections.\n */\nvar ListCollectionCreator = Backbone.View.extend(BASE_MVC.LoggableMixin)\n .extend(baseCreator.CollectionCreatorMixin)\n .extend({\n _logNamespace: logNamespace,\n\n /** the class used to display individual elements */\n elementViewClass: DatasetCollectionElementView,\n /** the class this creator will create and save */\n collectionClass: HDCA.HistoryListDatasetCollection,\n className: \"list-collection-creator collection-creator flex-row-container\",\n\n /** minimum number of valid elements to start with in order to build a collection of this type */\n minElements: 1,\n\n defaultAttributes: {\n //TODO: remove - use new collectionClass().save()\n /** takes elements and creates the proper collection - returns a promise */\n creationFn: function() {\n throw new TypeError(\"no creation fn for creator\");\n },\n /** fn to call when the collection is created (scoped to this) */\n oncreate: function() {},\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n oncancel: function() {},\n /** distance from list edge to begin autoscrolling list */\n autoscrollDist: 24,\n /** Color passed to hoverhighlight */\n highlightClr: \"rgba( 64, 255, 255, 1.0 )\"\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\"\n },\n\n /** set up initial options, instance vars, behaviors */\n initialize: function(attributes) {\n this.metric(\"ListCollectionCreator.initialize\", attributes);\n var creator = this;\n _.each(this.defaultAttributes, (value, key) => {\n value = attributes[key] || value;\n creator[key] = value;\n });\n\n /** unordered, original list - cache to allow reversal */\n creator.initialElements = attributes.elements || [];\n\n this._setUpCommonSettings(attributes);\n this._instanceSetUp();\n this._elementsSetUp();\n this._setUpBehaviors();\n },\n\n /** set up instance vars */\n _instanceSetUp: function() {\n /** Ids of elements that have been selected by the user - to preserve over renders */\n this.selectedIds = {};\n /** DOM elements currently being dragged */\n this.$dragging = null;\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n },\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data */\n _elementsSetUp: function() {\n //this.debug( '-- _dataSetUp' );\n /** a list of invalid elements and the reasons they aren't valid */\n this.invalidElements = [];\n //TODO: handle fundamental problem of syncing DOM, views, and list here\n /** data for list in progress */\n this.workingElements = [];\n /** views for workingElements */\n this.elementViews = [];\n\n // copy initial list, sort, add ids if needed\n this.workingElements = this.initialElements.slice(0);\n this._ensureElementIds();\n this._validateElements();\n this._mangleDuplicateNames();\n this._sortElements();\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureElementIds: function() {\n this.workingElements.forEach(element => {\n if (!element.hasOwnProperty(\"id\")) {\n element.id = _.uniqueId();\n }\n });\n return this.workingElements;\n },\n\n /** separate working list into valid and invalid elements for this collection */\n _validateElements: function() {\n var creator = this;\n var existingNames = {};\n creator.invalidElements = [];\n\n this.workingElements = this.workingElements.filter(element => {\n var problem = creator._isElementInvalid(element);\n if (problem) {\n creator.invalidElements.push({\n element: element,\n text: problem\n });\n }\n return !problem;\n });\n return this.workingElements;\n },\n\n /** describe what is wrong with a particular element if anything */\n _isElementInvalid: function(element) {\n if (element.history_content_type !== \"dataset\") {\n return _l(\"is not a dataset\");\n }\n var validState = element.state === STATES.OK || _.contains(STATES.NOT_READY_STATES, element.state);\n if (!validState) {\n return _l(\"has errored, is paused, or is not accessible\");\n }\n if (element.deleted || element.purged) {\n return _l(\"has been deleted or purged\");\n }\n return null;\n },\n\n /** mangle duplicate names using a mac-like '(counter)' addition to any duplicates */\n _mangleDuplicateNames: function() {\n var SAFETY = 900;\n var counter = 1;\n var existingNames = {};\n this.workingElements.forEach(element => {\n var currName = element.name;\n while (existingNames.hasOwnProperty(currName)) {\n currName = `${element.name} (${counter})`;\n counter += 1;\n if (counter >= SAFETY) {\n throw new Error(\"Safety hit in while loop - thats impressive\");\n }\n }\n element.name = currName;\n existingNames[element.name] = true;\n });\n },\n\n /** sort a list of elements */\n _sortElements: function(list) {\n // // currently only natural sort by name\n // this.workingElements.sort( function( a, b ){ return naturalSort( a.name, b.name ); });\n // return this.workingElements;\n },\n\n // ------------------------------------------------------------------------ rendering\n // templates : ListCollectionCreator.templates,\n /** render the entire interface */\n render: function(speed, callback) {\n //this.debug( '-- _render' );\n if (this.workingElements.length < this.minElements) {\n return this._renderInvalid(speed, callback);\n }\n\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.$(\".collection-name\").focus();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render a simplified interface aimed at telling the user why they can't move forward */\n _renderInvalid: function(speed, callback) {\n //this.debug( '-- _render' );\n this.$el.empty().html(\n this.templates.invalidInitial({\n problems: this.invalidElements,\n elements: this.workingElements\n })\n );\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function(speed, callback) {\n var $header = this.$(\".header\")\n .empty()\n .html(this.templates.header())\n .find(\".help-content\")\n .prepend($(this.templates.helpContent()));\n //TODO: should only show once despite calling _renderHeader again\n if (this.invalidElements.length) {\n this._invalidElementsAlert();\n }\n return $header;\n },\n\n /** render the middle including the elements */\n _renderMiddle: function(speed, callback) {\n var $middle = this.$(\".middle\")\n .empty()\n .html(this.templates.middle());\n this._renderList(speed);\n return $middle;\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function() {\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", this.highlightClr);\n },\n\n /** build and show an alert describing any elements that could not be included due to problems */\n _invalidElementsAlert: function() {\n this._showAlert(\n this.templates.invalidElements({\n problems: this.invalidElements\n }),\n \"alert-warning\"\n );\n },\n\n _disableNameAndCreate: function(disable) {\n disable = !_.isUndefined(disable) ? disable : true;\n if (disable) {\n this.$(\".collection-name\").prop(\"disabled\", true);\n this.$(\".create-collection\").toggleClass(\"disabled\", true);\n // } else {\n // this.$( '.collection-name' ).prop( 'disabled', false );\n // this.$( '.create-collection' ).removeClass( 'disable' );\n }\n },\n\n // ------------------------------------------------------------------------ rendering elements\n /** conv. to the main list display DOM */\n $list: function() {\n return this.$(\".collection-elements\");\n },\n\n /** show or hide the clear selected control based on the num of selected elements */\n _renderClearSelected: function() {\n if (_.size(this.selectedIds)) {\n this.$(\".collection-elements-controls > .clear-selected\").show();\n } else {\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n }\n },\n\n /** render the elements in order (or a warning if no elements found) */\n _renderList: function(speed, callback) {\n //this.debug( '-- _renderList' );\n var creator = this;\n\n var $tmp = jQuery(\"\");\n var $list = creator.$list();\n\n _.each(this.elementViews, view => {\n view.destroy();\n creator.removeElementView(view);\n });\n\n // if( !this.workingElements.length ){\n // this._renderNoValidElements();\n // return;\n // }\n\n creator.workingElements.forEach(element => {\n var elementView = creator._createElementView(element);\n $tmp.append(elementView.$el);\n });\n\n creator._renderClearSelected();\n $list.empty().append($tmp.children());\n _.invoke(creator.elementViews, \"render\");\n\n if ($list.height() > $list.css(\"max-height\")) {\n $list.css(\"border-width\", \"1px 0px 1px 0px\");\n } else {\n $list.css(\"border-width\", \"0px\");\n }\n },\n\n /** create an element view, cache in elementViews, set up listeners, and return */\n _createElementView: function(element) {\n var elementView = new this.elementViewClass({\n //TODO: use non-generic class or not all\n // model : COLLECTION.DatasetDCE( element )\n element: element,\n selected: _.has(this.selectedIds, element.id)\n });\n this.elementViews.push(elementView);\n this._listenToElementView(elementView);\n return elementView;\n },\n\n /** listen to any element events */\n _listenToElementView: function(view) {\n var creator = this;\n creator.listenTo(view, {\n select: function(data) {\n var element = data.source.element;\n if (data.selected) {\n creator.selectedIds[element.id] = true;\n } else {\n delete creator.selectedIds[element.id];\n }\n creator.trigger(\"elements:select\", data);\n },\n discard: function(data) {\n creator.trigger(\"elements:discard\", data);\n }\n });\n },\n\n /** add a new element view based on the json in element */\n addElementView: function(element) {\n //TODO: workingElements is sorted, add element in appropo index\n // add element, sort elements, find element index\n // var view = this._createElementView( element );\n // return view;\n },\n\n /** stop listening to view and remove from caches */\n removeElementView: function(view) {\n delete this.selectedIds[view.element.id];\n this._renderClearSelected();\n\n this.elementViews = _.without(this.elementViews, view);\n this.stopListening(view);\n },\n\n /** render a message in the list that no elements remain to create a collection */\n _renderNoElementsLeft: function() {\n this._disableNameAndCreate(true);\n this.$(\".collection-elements\").append(this.templates.noElementsLeft());\n },\n\n // /** render a message in the list that no valid elements were found to create a collection */\n // _renderNoValidElements : function(){\n // this._disableNameAndCreate( true );\n // this.$( '.collection-elements' ).append( this.templates.noValidElements() );\n // },\n\n // ------------------------------------------------------------------------ API\n /** convert element into JSON compatible with the collections API */\n _elementToJSON: function(element) {\n // return element.toJSON();\n return element;\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function(name) {\n if (!this.workingElements.length) {\n var message = `${_l(\"No valid elements for final list\")}. `;\n message += `${_l(\"Cancel\")} `;\n message += _l(\"or\");\n message += ` ${_l(\"start over\")}.`;\n this._showAlert(message);\n return;\n }\n\n var creator = this;\n\n var elements = this.workingElements.map(element => creator._elementToJSON(element));\n\n creator.blocking = true;\n return creator\n .creationFn(elements, name, creator.hideOriginals)\n .always(() => {\n creator.blocking = false;\n })\n .fail((xhr, status, message) => {\n creator.trigger(\"error\", {\n xhr: xhr,\n status: status,\n message: _l(\"An error occurred while creating this collection\")\n });\n })\n .done(function(response, message, xhr) {\n creator.trigger(\"collection:created\", response, message, xhr);\n creator.metric(\"collection:created\", response);\n if (typeof creator.oncreate === \"function\") {\n creator.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n // ------------------------------------------------------------------------ events\n /** set up event handlers on self */\n _setUpBehaviors: function() {\n this.on(\"error\", this._errorHandler);\n\n this.once(\"rendered\", function() {\n this.trigger(\"rendered:initial\", this);\n });\n\n this.on(\"elements:select\", function(data) {\n this._renderClearSelected();\n });\n\n this.on(\"elements:discard\", function(data) {\n var element = data.source.element;\n this.removeElementView(data.source);\n\n this.workingElements = _.without(this.workingElements, element);\n if (!this.workingElements.length) {\n this._renderNoElementsLeft();\n }\n });\n\n //this.on( 'all', function(){\n // this.info( arguments );\n //});\n return this;\n },\n\n /** handle errors with feedback and details to the user (if available) */\n _errorHandler: function(data) {\n this.error(data);\n\n var creator = this;\n var content = data.message || _l(\"An error occurred\");\n if (data.xhr) {\n var xhr = data.xhr;\n var message = data.message;\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += `: ${_l(\"Galaxy could not be reached and may be updating.\")}${_l(\n \" Try again in a few minutes.\"\n )}`;\n } else if (xhr.responseJSON) {\n content += `:
${JSON.stringify(xhr.responseJSON)}
`;\n } else {\n content += `: ${message}`;\n }\n }\n creator._showAlert(content, \"alert-danger\");\n },\n\n events: {\n // header\n \"click .more-help\": \"_clickMoreHelp\",\n \"click .less-help\": \"_clickLessHelp\",\n \"click .main-help\": \"_toggleHelp\",\n \"click .header .alert button\": \"_hideAlert\",\n\n \"click .reset\": \"reset\",\n \"click .clear-selected\": \"clearSelectedElements\",\n\n // elements - selection\n \"click .collection-elements\": \"clearSelectedElements\",\n\n // elements - drop target\n // 'dragenter .collection-elements': '_dragenterElements',\n // 'dragleave .collection-elements': '_dragleaveElements',\n \"dragover .collection-elements\": \"_dragoverElements\",\n \"drop .collection-elements\": \"_dropElements\",\n\n // these bubble up from the elements as custom events\n \"collection-element.dragstart .collection-elements\": \"_elementDragstart\",\n \"collection-element.dragend .collection-elements\": \"_elementDragend\",\n\n // footer\n \"change .collection-name\": \"_changeName\",\n \"keydown .collection-name\": \"_nameCheckForEnter\",\n \"change .hide-originals\": \"_changeHideOriginals\",\n \"click .cancel-create\": \"_cancelCreate\",\n \"click .create-collection\": \"_clickCreate\" //,\n },\n\n // ........................................................................ elements\n /** reset all data to the initial state */\n reset: function() {\n this._instanceSetUp();\n this._elementsSetUp();\n this.render();\n },\n\n /** deselect all elements */\n clearSelectedElements: function(ev) {\n this.$(\".collection-elements .collection-element\").removeClass(\"selected\");\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n },\n\n //_dragenterElements : function( ev ){\n // //this.debug( '_dragenterElements:', ev );\n //},\n //TODO: if selected are dragged out of the list area - remove the placeholder - cuz it won't work anyway\n // _dragleaveElements : function( ev ){\n // //this.debug( '_dragleaveElements:', ev );\n // },\n\n /** track the mouse drag over the list adding a placeholder to show where the drop would occur */\n _dragoverElements: function(ev) {\n //this.debug( '_dragoverElements:', ev );\n ev.preventDefault();\n\n var $list = this.$list();\n this._checkForAutoscroll($list, ev.originalEvent.clientY);\n var $nearest = this._getNearestElement(ev.originalEvent.clientY);\n\n //TODO: no need to re-create - move instead\n this.$(\".element-drop-placeholder\").remove();\n var $placeholder = $('');\n if (!$nearest.length) {\n $list.append($placeholder);\n } else {\n $nearest.before($placeholder);\n }\n },\n\n /** If the mouse is near enough to the list's top or bottom, scroll the list */\n _checkForAutoscroll: function($element, y) {\n var AUTOSCROLL_SPEED = 2;\n var offset = $element.offset();\n var scrollTop = $element.scrollTop();\n var upperDist = y - offset.top;\n var lowerDist = offset.top + $element.outerHeight() - y;\n if (upperDist >= 0 && upperDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop - AUTOSCROLL_SPEED);\n } else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop + AUTOSCROLL_SPEED);\n }\n },\n\n /** get the nearest element based on the mouse's Y coordinate.\n * If the y is at the end of the list, return an empty jQuery object.\n */\n _getNearestElement: function(y) {\n var WIGGLE = 4;\n\n var lis = this.$(\".collection-elements li.collection-element\").toArray();\n\n for (var i = 0; i < lis.length; i++) {\n var $li = $(lis[i]);\n var top = $li.offset().top;\n var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;\n if (top + halfHeight > y && top - halfHeight < y) {\n return $li;\n }\n }\n return $();\n },\n\n /** drop (dragged/selected elements) onto the list, re-ordering the internal list */\n _dropElements: function(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n // both required for firefox\n ev.preventDefault();\n ev.dataTransfer.dropEffect = \"move\";\n\n // insert before the nearest element or after the last.\n var $nearest = this._getNearestElement(ev.clientY);\n if ($nearest.length) {\n this.$dragging.insertBefore($nearest);\n } else {\n // no nearest before - insert after last element\n this.$dragging.insertAfter(this.$(\".collection-elements .collection-element\").last());\n }\n // resync the creator's list based on the new DOM order\n this._syncOrderToDom();\n return false;\n },\n\n /** resync the creator's list of elements based on the DOM order */\n _syncOrderToDom: function() {\n var creator = this;\n var newElements = [];\n //TODO: doesn't seem wise to use the dom to store these - can't we sync another way?\n this.$(\".collection-elements .collection-element\").each(function() {\n var id = $(this).attr(\"data-element-id\");\n\n var element = _.findWhere(creator.workingElements, {\n id: id\n });\n\n if (element) {\n newElements.push(element);\n } else {\n console.error(\"missing element: \", id);\n }\n });\n this.workingElements = newElements;\n this._renderList();\n },\n\n /** drag communication with element sub-views: dragstart */\n _elementDragstart: function(ev, element) {\n // auto select the element causing the event and move all selected\n element.select(true);\n this.$dragging = this.$(\".collection-elements .collection-element.selected\");\n },\n\n /** drag communication with element sub-views: dragend - remove the placeholder */\n _elementDragend: function(ev, element) {\n $(\".element-drop-placeholder\").remove();\n this.$dragging = null;\n },\n\n // ------------------------------------------------------------------------ templates\n //TODO: move to require text plugin and load these as text\n //TODO: underscore currently unnecc. bc no vars are used\n //TODO: better way of localizing text-nodes in long strings\n /** underscore template fns attached to class */\n templates: _.extend({}, baseCreator.CollectionCreatorMixin._creatorTemplates, {\n /** the header (not including help text) */\n header: _.template(\n [\n '
\",\n _l(\n [\n \"Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and \",\n \"workflows in order to have analyses done on each member of the entire group. This interface allows \",\n \"you to create a collection and re-order the final collection.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n \"Rename elements in the list by clicking on \",\n 'the existing name.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n \"Discard elements from the final created list by clicking on the \",\n '\"Discard\" button.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n \"Reorder the list by clicking and dragging elements. Select multiple elements by clicking on \",\n 'them and you can then move those selected by dragging the ',\n \"entire group. Deselect them by clicking them again or by clicking the \",\n 'the \"Clear selected\" link.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'Click the \"Start over\" link to begin again as if you had just opened ',\n \"the interface.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n ['Click the \"Cancel\" button to exit the interface.'].join(\n \"\"\n )\n ),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n 'Once your collection is complete, enter a name and ',\n 'click \"Create list\".'\n ].join(\"\")\n ),\n \"
\"\n ].join(\"\")\n ),\n\n /** shown in list when all elements are discarded */\n invalidElements: _.template(\n [\n _l(\"The following selections could not be included due to problems:\"),\n \"
<% _.each( problems, function( problem ){ %>\",\n \"
<%- problem.element.name %>: <%- problem.text %>
\",\n \"<% }); %>
\"\n ].join(\"\")\n ),\n\n /** shown in list when all elements are discarded */\n noElementsLeft: _.template(\n [\n '
\"\n ].join(\"\")\n ),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(\n [\n '
',\n '
',\n '',\n \"<% if( _.size( problems ) ){ %>\",\n _l(\"The following selections could not be included due to problems\"),\n \":\",\n \"
<% _.each( problems, function( problem ){ %>\",\n \"
<%- problem.element.name %>: <%- problem.text %>
\",\n \"<% }); %>
\",\n \"<% } else if( _.size( elements ) < 1 ){ %>\",\n _l(\"No datasets were selected\"),\n \".\",\n \"<% } %>\",\n \" \",\n _l(\"At least one element is needed for the collection\"),\n \". \",\n _l(\"You may need to \"),\n '',\n _l(\"cancel\"),\n \" \",\n _l(\"and reselect new elements\"),\n \".\",\n \"\",\n \"
\",\n \"
\",\n '\"\n ].join(\"\")\n )\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function() {\n return \"ListCollectionCreator\";\n }\n });\n\n//=============================================================================\n/** Create a modal and load its body with the given CreatorClass creator type\n * @returns {Deferred} resolved when creator has built a collection.\n */\nvar collectionCreatorModal = function _collectionCreatorModal(elements, options, CreatorClass) {\n var deferred = jQuery.Deferred();\n var modal = Galaxy.modal || new UI_MODAL.View();\n var creator;\n\n options = _.defaults(options || {}, {\n elements: elements,\n oncancel: function() {\n modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function(creator, response) {\n modal.hide();\n deferred.resolve(response);\n }\n });\n\n creator = new CreatorClass(options);\n modal.show({\n title: options.title || _l(\"Create a collection\"),\n body: creator.$el,\n width: \"80%\",\n height: \"100%\",\n closing_events: true\n });\n creator.render();\n window._collectionCreator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n/** List collection flavor of collectionCreatorModal. */\nvar listCollectionCreatorModal = function _listCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = _l(\"Create a collection from a list of datasets\");\n return collectionCreatorModal(elements, options, ListCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a list collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createListCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = listCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function(elements, name, hideSourceItems) {\n elements = elements.map(element => ({\n id: element.id,\n name: element.name,\n\n //TODO: this allows for list:list even if the filter above does not - reconcile\n src: element.history_content_type === \"dataset\" ? \"hda\" : \"hdca\"\n }));\n return contents.createHDCA(elements, \"list\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexport default {\n DatasetCollectionElementView: DatasetCollectionElementView,\n ListCollectionCreator: ListCollectionCreator,\n\n collectionCreatorModal: collectionCreatorModal,\n listCollectionCreatorModal: listCollectionCreatorModal,\n createListCollection: createListCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/list-collection-creator.js","import DC_MODEL from \"mvc/collection/collection-model\";\nimport HISTORY_CONTENT from \"mvc/history/history-content-model\";\nimport _l from \"utils/localization\";\n\n/*==============================================================================\n\nModels for DatasetCollections contained within a history.\n\nTODO:\n these might be compactable to one class if some duplication with\n collection-model is used.\n\n==============================================================================*/\nvar hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;\n\nvar ListDC = DC_MODEL.ListDatasetCollection;\nvar PairDC = DC_MODEL.PairDatasetCollection;\nvar ListPairedDC = DC_MODEL.ListPairedDatasetCollection;\nvar ListOfListsDC = DC_MODEL.ListOfListsDatasetCollection;\n\n//==============================================================================\n/** Override to post to contents route w/o id. */\nfunction buildHDCASave(_super) {\n return function _save(attributes, options) {\n if (this.isNew()) {\n options = options || {};\n options.url = `${this.urlRoot + this.get(\"history_id\")}/contents`;\n attributes = attributes || {};\n attributes.type = \"dataset_collection\";\n }\n return _super.call(this, attributes, options);\n };\n}\n\n//==============================================================================\n/** @class Backbone model for List Dataset Collection within a History.\n */\nvar HistoryListDatasetCollection = ListDC.extend(hcontentMixin).extend(\n /** @lends HistoryListDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(ListDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for Pair Dataset Collection within a History.\n * @constructs\n */\nvar HistoryPairDatasetCollection = PairDC.extend(hcontentMixin).extend(\n /** @lends HistoryPairDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(PairDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(PairDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${PairDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for List of Pairs Dataset Collection within a History. */\nvar HistoryListPairedDatasetCollection = ListPairedDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListPairedDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListPairedDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListPairedDC.prototype.toString.call(this)}`;\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Lists Dataset Collection within a History. */\nvar HistoryListOfListsDatasetCollection = ListOfListsDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListOfListsDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListOfListsDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return [\"HistoryListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n HistoryListDatasetCollection: HistoryListDatasetCollection,\n HistoryPairDatasetCollection: HistoryPairDatasetCollection,\n HistoryListPairedDatasetCollection: HistoryListPairedDatasetCollection,\n HistoryListOfListsDatasetCollection: HistoryListOfListsDatasetCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hdca-model.js","import DATASET_MODEL from \"mvc/dataset/dataset-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/*\nNotes:\n\nTerminology:\n DatasetCollection/DC : a container of datasets or nested DatasetCollections\n Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection\n HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history\n\n\nThis all seems too complex unfortunately:\n\n- Terminology collision between DatasetCollections (DCs) and Backbone Collections.\n- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*\n either a dataset or a nested DC. This would make the hierarchy much taller. I've\n decided to merge the contained JSON with the DC element json - making the 'has a'\n relation into an 'is a' relation. This seems simpler to me and allowed a lot of\n DRY in both models and views, but may make tracking or tracing within these models\n more difficult (since DatasetCollectionElements are now *also* DatasetAssociations\n or DatasetCollections (nested)). This also violates the rule of thumb about\n favoring aggregation over inheritance.\n- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.\n These each should a) be usable on their own, b) be usable in the context of\n nesting within a collection model (at least in the case of ListPaired), and\n c) be usable within the context of other container models (like History or\n LibraryFolder, etc.). I've tried to separate/extract classes in order to\n handle those three situations, but it's proven difficult to do in a simple,\n readable manner.\n- Ideally, histories and libraries would inherit from the same server models as\n dataset collections do since they are (in essence) dataset collections themselves -\n making the whole nested structure simpler. This would be a large, error-prone\n refactoring and migration.\n\nMany of the classes and heirarchy are meant as extension points so, while the\nrelations and flow may be difficult to understand initially, they'll allow us to\nhandle the growth or flux dataset collection in the future (w/o actually implementing\nany YAGNI).\n\n*/\n//_________________________________________________________________________________________________ ELEMENTS\n/** @class mixin for Dataset collection elements.\n * When collection elements are passed from the API, the underlying element is\n * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).\n * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues\n * effectively changing a DCE from a container to a subclass (has a --> is a).\n */\nvar DatasetCollectionElementMixin = {\n /** default attributes used by elements in a dataset collection */\n defaults: {\n model_class: \"DatasetCollectionElement\",\n element_identifier: null,\n element_index: null,\n element_type: null\n },\n\n /** merge the attributes of the sub-object 'object' into this model */\n _mergeObject: function(attributes) {\n // if we don't preserve and correct ids here, the element id becomes the object id\n // and collision in backbone's _byId will occur and only\n _.extend(attributes, attributes.object, {\n element_id: attributes.id\n });\n delete attributes.object;\n return attributes;\n },\n\n /** override to merge this.object into this */\n constructor: function(attributes, options) {\n // console.debug( '\\t DatasetCollectionElement.constructor:', attributes, options );\n attributes = this._mergeObject(attributes);\n this.idAttribute = \"element_id\";\n Backbone.Model.apply(this, arguments);\n },\n\n /** when the model is fetched, merge this.object into this */\n parse: function(response, options) {\n var attributes = response;\n attributes = this._mergeObject(attributes);\n return attributes;\n }\n};\n\n/** @class Concrete class of Generic DatasetCollectionElement */\nvar DatasetCollectionElement = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(DatasetCollectionElementMixin)\n .extend({ _logNamespace: \"collections\" });\n\n//==============================================================================\n/** @class Base/Abstract Backbone collection for Generic DCEs. */\nvar DCECollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends DCECollection.prototype */ {\n _logNamespace: \"collections\",\n\n model: DatasetCollectionElement,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetCollectionElementCollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a dataset collection element that is a dataset (HDA).\n */\nvar DatasetDCE = DATASET_MODEL.DatasetAssociation.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends DatasetDCE.prototype */ {\n /** url fn */\n url: function() {\n // won't always be an hda\n if (!this.has(\"history_id\")) {\n console.warn(\"no endpoint for non-hdas within a collection yet\");\n // (a little silly since this api endpoint *also* points at hdas)\n return `${Galaxy.root}api/datasets`;\n }\n return `${Galaxy.root}api/histories/${this.get(\"history_id\")}/contents/${this.get(\"id\")}`;\n },\n\n defaults: _.extend(\n {},\n DATASET_MODEL.DatasetAssociation.prototype.defaults,\n DatasetCollectionElementMixin.defaults\n ),\n\n _downloadQueryParameters: function() {\n return `?to_ext=${this.get(\"file_ext\")}&hdca_id=${this.get(\n \"parent_hdca_id\"\n )}&element_identifier=${this.get(\"element_identifier\")}`;\n },\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually for now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t DatasetDCE.constructor:\", attributes, options);\n //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function() {\n return this.elements && this.elements.length;\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.get(\"element_identifier\");\n return [\"DatasetDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).\n */\nvar DatasetDCECollection = DCECollection.extend(\n /** @lends DatasetDCECollection.prototype */ {\n model: DatasetDCE,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//_________________________________________________________________________________________________ COLLECTIONS\n/** @class Backbone model for Dataset Collections.\n * The DC API returns an array of JSON objects under the attribute elements.\n * This model:\n * - removes that array/attribute ('elements') from the model,\n * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),\n * - passes that json onto the bbone collection\n * - caches the bbone collection in this.elements\n */\nvar DatasetCollection = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(BASE_MVC.SearchableModelMixin)\n .extend(\n /** @lends DatasetCollection.prototype */ {\n _logNamespace: \"collections\",\n\n /** default attributes for a model */\n defaults: {\n /* 'list', 'paired', or 'list:paired' */\n collection_type: null,\n //??\n deleted: false\n },\n\n /** Which class to use for elements */\n collectionClass: DCECollection,\n\n /** set up: create elements instance var and (on changes to elements) update them */\n initialize: function(model, options) {\n this.debug(`${this}(DatasetCollection).initialize:`, model, options, this);\n this.elements = this._createElementsModel();\n this.on(\"change:elements\", function() {\n this.log(\"change:elements\");\n //TODO: prob. better to update the collection instead of re-creating it\n this.elements = this._createElementsModel();\n });\n },\n\n /** move elements model attribute to full collection */\n _createElementsModel: function() {\n this.debug(`${this}._createElementsModel`, this.collectionClass, this.get(\"elements\"), this.elements);\n //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?\n var elements = this.get(\"elements\") || [];\n this.unset(\"elements\", { silent: true });\n var self = this;\n _.each(elements, (element, index) => {\n _.extend(element, {\n parent_hdca_id: self.get(\"id\")\n });\n });\n this.elements = new this.collectionClass(elements);\n //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );\n return this.elements;\n },\n\n // ........................................................................ common queries\n /** pass the elements back within the model json when this is serialized */\n toJSON: function() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n if (this.elements) {\n json.elements = this.elements.toJSON();\n }\n return json;\n },\n\n /** Is this collection in a 'ready' state no processing (for the collection) is left\n * to do on the server.\n */\n inReadyState: function() {\n var populated = this.get(\"populated\");\n return this.isDeletedOrPurged() || populated;\n },\n\n //TODO:?? the following are the same interface as DatasetAssociation - can we combine?\n /** Does the DC contain any elements yet? Is a fetch() required? */\n hasDetails: function() {\n return this.elements.length !== 0;\n },\n\n /** Given the filters, what models in this.elements would be returned? */\n getVisibleContents: function(filters) {\n // filters unused for now\n return this.elements;\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Is this collection deleted or purged? */\n isDeletedOrPurged: function() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n // ........................................................................ searchable\n /** searchable attributes for collections */\n searchAttributes: [\"name\", \"tags\"],\n\n // ........................................................................ misc\n /** String representation */\n toString: function() {\n var idAndName = [this.get(\"id\"), this.get(\"name\") || this.get(\"element_identifier\")];\n return `DatasetCollection(${idAndName.join(\",\")})`;\n }\n }\n );\n\n//==============================================================================\n/** Model for a DatasetCollection containing datasets (non-nested).\n */\nvar ListDatasetCollection = DatasetCollection.extend(\n /** @lends ListDatasetCollection.prototype */ {\n /** override since we know the collection will only contain datasets */\n collectionClass: DatasetDCECollection,\n\n /** String representation. */\n toString: function() {\n return `List${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).\n */\nvar PairDatasetCollection = ListDatasetCollection.extend(\n /** @lends PairDatasetCollection.prototype */ {\n /** String representation. */\n toString: function() {\n return `Pair${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//_________________________________________________________________________________________________ NESTED COLLECTIONS\n// this is where things get weird, man. Weird.\n//TODO: it might be possible to compact all the following...I think.\n//==============================================================================\n/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection\n * (a nested collection). Currently only list:paired.\n */\nvar NestedDCDCE = DatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedDCDCE.prototype */ {\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).\n */\nvar NestedDCDCECollection = DCECollection.extend(\n /** @lends NestedDCDCECollection.prototype */ {\n /** This is a collection of nested collections */\n model: NestedDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.\n */\nvar NestedPairDCDCE = PairDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedPairDCDCE.prototype */ {\n //TODO:?? possibly rename to NestedDatasetCollection?\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedPairDCDCE.constructor:\", attributes, options);\n //DatasetCollection.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedPairDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection for a backbone collection containing paired dataset collections.\n */\nvar NestedPairDCDCECollection = NestedDCDCECollection.extend(\n /** @lends PairDCDCECollection.prototype */ {\n /** We know this collection is composed of only nested pair collections */\n model: NestedPairDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedPairDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).\n */\nvar ListPairedDatasetCollection = DatasetCollection.extend(\n /** @lends ListPairedDatasetCollection.prototype */ {\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedPairDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListPairedDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a list dataset collection within a list:list dataset collection. */\nvar NestedListDCDCE = ListDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedListDCDCE.prototype */ {\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedListDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedListDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing list dataset collections. */\nvar NestedListDCDCECollection = NestedDCDCECollection.extend({\n /** We know this collection is composed of only nested pair collections */\n model: NestedListDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedListDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains other lists. */\nvar ListOfListsDatasetCollection = DatasetCollection.extend({\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedListDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n ListDatasetCollection: ListDatasetCollection,\n PairDatasetCollection: PairDatasetCollection,\n ListPairedDatasetCollection: ListPairedDatasetCollection,\n ListOfListsDatasetCollection: ListOfListsDatasetCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-model.js","import HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport UTILS from \"utils/utils\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Model for a Galaxy history resource - both a record of user\n * tool use and a collection of the datasets those tools produced.\n * @name History\n * @augments Backbone.Model\n */\nvar History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(\n BASE_MVC.mixin(\n BASE_MVC.SearchableModelMixin,\n /** @lends History.prototype */ {\n _logNamespace: \"history\",\n\n /** ms between fetches when checking running jobs/datasets for updates */\n UPDATE_DELAY: 4000,\n\n // values from api (may need more)\n defaults: {\n model_class: \"History\",\n id: null,\n name: \"Unnamed History\",\n state: \"new\",\n\n deleted: false,\n contents_active: {},\n contents_states: {}\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n\n contentsClass: HISTORY_CONTENTS.HistoryContents,\n\n /** What model fields to search with */\n searchAttributes: [\"name\", \"annotation\", \"tags\"],\n\n /** Adding title and singular tag */\n searchAliases: {\n title: \"name\",\n tag: \"tags\"\n },\n\n // ........................................................................ set up/tear down\n /** Set up the model\n * @param {Object} historyJSON model data for this History\n * @param {Object} options any extra settings including logger\n */\n initialize: function(historyJSON, options) {\n options = options || {};\n this.logger = options.logger || null;\n this.log(`${this}.initialize:`, historyJSON, options);\n\n /** HistoryContents collection of the HDAs contained in this history. */\n this.contents = new this.contentsClass([], {\n history: this,\n historyId: this.get(\"id\"),\n order: options.order\n });\n\n this._setUpListeners();\n this._setUpCollectionListeners();\n\n /** cached timeout id for the dataset updater */\n this.updateTimeoutId = null;\n },\n\n /** set up any event listeners for this history including those to the contained HDAs\n * events: error:contents if an error occurred with the contents collection\n */\n _setUpListeners: function() {\n // if the model's id changes ('current' or null -> an actual id), update the contents history_id\n return this.on({\n error: function(model, xhr, options, msg, details) {\n this.clearUpdateTimeout();\n },\n \"change:id\": function(model, newId) {\n if (this.contents) {\n this.contents.historyId = newId;\n }\n }\n });\n },\n\n /** event handlers for the contents submodels */\n _setUpCollectionListeners: function() {\n if (!this.contents) {\n return this;\n }\n // bubble up errors\n return this.listenTo(this.contents, {\n error: function() {\n this.trigger.apply(this, jQuery.makeArray(arguments));\n }\n });\n },\n\n // ........................................................................ derived attributes\n /** */\n contentsShown: function() {\n var contentsActive = this.get(\"contents_active\");\n var shown = contentsActive.active || 0;\n shown += this.contents.includeDeleted ? contentsActive.deleted : 0;\n shown += this.contents.includeHidden ? contentsActive.hidden : 0;\n return shown;\n },\n\n /** convert size in bytes to a more human readable version */\n nice_size: function() {\n var size = this.get(\"size\");\n return size ? UTILS.bytesToString(size, true, 2) : _l(\"(empty)\");\n },\n\n /** override to add nice_size */\n toJSON: function() {\n return _.extend(Backbone.Model.prototype.toJSON.call(this), {\n nice_size: this.nice_size()\n });\n },\n\n /** override to allow getting nice_size */\n get: function(key) {\n if (key === \"nice_size\") {\n return this.nice_size();\n }\n return Backbone.Model.prototype.get.apply(this, arguments);\n },\n\n // ........................................................................ common queries\n /** T/F is this history owned by the current user (Galaxy.user)\n * Note: that this will return false for an anon user even if the history is theirs.\n */\n ownedByCurrUser: function() {\n // no currUser\n if (!Galaxy || !Galaxy.user) {\n return false;\n }\n // user is anon or history isn't owned\n if (Galaxy.user.isAnonymous() || Galaxy.user.id !== this.get(\"user_id\")) {\n return false;\n }\n return true;\n },\n\n /** Return the number of running jobs assoc with this history (note: unknown === 0) */\n numOfUnfinishedJobs: function() {\n var unfinishedJobIds = this.get(\"non_ready_jobs\");\n return unfinishedJobIds ? unfinishedJobIds.length : 0;\n },\n\n /** Return the number of running hda/hdcas in this history (note: unknown === 0) */\n numOfUnfinishedShownContents: function() {\n return this.contents.runningAndActive().length || 0;\n },\n\n // ........................................................................ updates\n _fetchContentRelatedAttributes: function() {\n var contentRelatedAttrs = [\"size\", \"non_ready_jobs\", \"contents_active\", \"hid_counter\"];\n return this.fetch({\n data: $.param({\n keys: contentRelatedAttrs.join(\",\")\n })\n });\n },\n\n /** check for any changes since the last time we updated (or fetch all if ) */\n refresh: function(options) {\n // console.log( this + '.refresh' );\n options = options || {};\n var self = this;\n\n // note if there was no previous update time, all summary contents will be fetched\n var lastUpdateTime = self.lastUpdateTime;\n // if we don't flip this, then a fully-fetched list will not be re-checked via fetch\n this.contents.allFetched = false;\n var fetchFn =\n self.contents.currentPage !== 0\n ? () => self.contents.fetchPage(self.contents.currentPage)\n : () => self.contents.fetchUpdated(lastUpdateTime);\n // note: if there was no previous update time, all summary contents will be fetched\n return fetchFn().done((response, status, xhr) => {\n var serverResponseDatetime;\n try {\n serverResponseDatetime = new Date(xhr.getResponseHeader(\"Date\"));\n } catch (err) {}\n self.lastUpdateTime = serverResponseDatetime || new Date();\n self.checkForUpdates(options);\n });\n },\n\n /** continuously fetch updated contents every UPDATE_DELAY ms if this history's datasets or jobs are unfinished */\n checkForUpdates: function(options) {\n // console.log( this + '.checkForUpdates' );\n options = options || {};\n var delay = this.UPDATE_DELAY;\n var self = this;\n if (!self.id) {\n return;\n }\n\n function _delayThenUpdate() {\n // prevent buildup of updater timeouts by clearing previous if any, then set new and cache id\n self.clearUpdateTimeout();\n self.updateTimeoutId = setTimeout(() => {\n self.refresh(options);\n }, delay);\n }\n\n // if there are still datasets in the non-ready state, recurse into this function with the new time\n var nonReadyContentCount = this.numOfUnfinishedShownContents();\n // console.log( 'nonReadyContentCount:', nonReadyContentCount );\n if (nonReadyContentCount > 0) {\n _delayThenUpdate();\n } else {\n // no datasets are running, but currently runnning jobs may still produce new datasets\n // see if the history has any running jobs and continue to update if so\n // (also update the size for the user in either case)\n self._fetchContentRelatedAttributes().done(historyData => {\n // console.log( 'non_ready_jobs:', historyData.non_ready_jobs );\n if (self.numOfUnfinishedJobs() > 0) {\n _delayThenUpdate();\n } else {\n // otherwise, let listeners know that all updates have stopped\n self.trigger(\"ready\");\n }\n });\n }\n },\n\n /** clear the timeout and the cached timeout id */\n clearUpdateTimeout: function() {\n if (this.updateTimeoutId) {\n clearTimeout(this.updateTimeoutId);\n this.updateTimeoutId = null;\n }\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** fetch this histories data (using options) then it's contents (using contentsOptions) */\n fetchWithContents: function(options, contentsOptions) {\n options = options || {};\n var self = this;\n\n // console.log( this + '.fetchWithContents' );\n // TODO: push down to a base class\n options.view = \"dev-detailed\";\n\n // fetch history then use history data to fetch (paginated) contents\n return this.fetch(options).then(function getContents(history) {\n self.contents.history = self;\n self.contents.setHistoryId(history.id);\n return self.fetchContents(contentsOptions);\n });\n },\n\n /** fetch this histories contents, adjusting options based on the stored history preferences */\n fetchContents: function(options) {\n options = options || {};\n var self = this;\n\n // we're updating, reset the update time\n self.lastUpdateTime = new Date();\n return self.contents.fetchCurrentPage(options);\n },\n\n /** save this history, _Mark_ing it as deleted (just a flag) */\n _delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */\n purge: function(options) {\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true, purged: true }, options);\n },\n /** save this history, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Make a copy of this history on the server\n * @param {Boolean} current if true, set the copy as the new current history (default: true)\n * @param {String} name name of new history (default: none - server sets to: Copy of )\n * @fires copied passed this history and the response JSON from the copy\n * @returns {xhr}\n */\n copy: function(current, name, allDatasets) {\n current = current !== undefined ? current : true;\n if (!this.id) {\n throw new Error(\"You must set the history ID before copying it.\");\n }\n\n var postData = { history_id: this.id };\n if (current) {\n postData.current = true;\n }\n if (name) {\n postData.name = name;\n }\n if (!allDatasets) {\n postData.all_datasets = false;\n }\n postData.view = \"dev-detailed\";\n\n var history = this;\n var copy = jQuery.post(this.urlRoot, postData);\n // if current - queue to setAsCurrent before firing 'copied'\n if (current) {\n return copy.then(response => {\n var newHistory = new History(response);\n return newHistory.setAsCurrent().done(() => {\n history.trigger(\"copied\", history, response);\n });\n });\n }\n return copy.done(response => {\n history.trigger(\"copied\", history, response);\n });\n },\n\n setAsCurrent: function() {\n var history = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/set_as_current?id=${this.id}`);\n\n xhr.done(() => {\n history.trigger(\"set-as-current\", history);\n });\n return xhr;\n },\n\n // ........................................................................ misc\n toString: function() {\n return `History(${this.get(\"id\")},${this.get(\"name\")})`;\n }\n }\n )\n);\n\n//==============================================================================\nvar _collectionSuper = CONTROLLED_FETCH_COLLECTION.InfinitelyScrollingCollection;\n/** @class A collection of histories (per user)\n * that maintains the current history as the first in the collection.\n * New or copied histories become the current history.\n */\nvar HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n model: History,\n /** @type {String} initial order used by collection */\n order: \"update_time\",\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: 10,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 10,\n\n initialize: function(models, options) {\n options = options || {};\n this.log(\"HistoryCollection.initialize\", models, options);\n _collectionSuper.prototype.initialize.call(this, models, options);\n\n /** @type {boolean} should deleted histories be included */\n this.includeDeleted = options.includeDeleted || false;\n\n /** @type {String} encoded id of the history that's current */\n this.currentHistoryId = options.currentHistoryId;\n\n this.setUpListeners();\n // note: models are sent to reset *after* this fn ends; up to this point\n // the collection *is empty*\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n url: function() {\n return this.urlRoot;\n },\n\n /** set up reflexive event handlers */\n setUpListeners: function setUpListeners() {\n return this.on({\n // when a history is deleted, remove it from the collection (if optionally set to do so)\n \"change:deleted\": function(history) {\n // TODO: this becomes complicated when more filters are used\n this.debug(\"change:deleted\", this.includeDeleted, history.get(\"deleted\"));\n if (!this.includeDeleted && history.get(\"deleted\")) {\n this.remove(history);\n }\n },\n // listen for a history copy, setting it to current\n copied: function(original, newData) {\n this.setCurrent(new History(newData, []));\n },\n // when a history is made current, track the id in the collection\n \"set-as-current\": function(history) {\n var oldCurrentId = this.currentHistoryId;\n this.trigger(\"no-longer-current\", oldCurrentId);\n this.currentHistoryId = history.id;\n }\n });\n },\n\n /** override to change view */\n _buildFetchData: function(options) {\n return _.extend(_collectionSuper.prototype._buildFetchData.call(this, options), {\n view: \"dev-detailed\"\n });\n },\n\n /** override to filter out deleted and purged */\n _buildFetchFilters: function(options) {\n var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n } else {\n // force API to return both deleted and non\n //TODO: when the API is updated, remove this\n filters.deleted = null;\n }\n return _.defaults(superFilters, filters);\n },\n\n /** override to fetch current as well (as it may be outside the first 10, etc.) */\n fetchFirst: function(options) {\n var self = this;\n // TODO: batch?\n var xhr = $.when();\n if (this.currentHistoryId) {\n xhr = _collectionSuper.prototype.fetchFirst.call(self, {\n silent: true,\n limit: 1,\n filters: {\n // without these a deleted current history will return [] here and block the other xhr\n purged: \"\",\n deleted: \"\",\n \"encoded_id-in\": this.currentHistoryId\n }\n });\n }\n return xhr.then(() => {\n options = options || {};\n options.offset = 0;\n return self.fetchMore(options);\n });\n },\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_collectionSuper.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", {\n ascending: true\n }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n size: BASE_MVC.buildComparator(\"size\", {\n ascending: false\n }),\n \"size-asc\": BASE_MVC.buildComparator(\"size\", {\n ascending: true\n })\n }),\n\n /** override to always have the current history first */\n sort: function(options) {\n options = options || {};\n var silent = options.silent;\n var currentHistory = this.remove(this.get(this.currentHistoryId));\n _collectionSuper.prototype.sort.call(this, _.defaults({ silent: true }, options));\n this.unshift(currentHistory, { silent: true });\n if (!silent) {\n this.trigger(\"sort\", this, options);\n }\n return this;\n },\n\n /** create a new history and by default set it to be the current history */\n create: function create(data, hdas, historyOptions, xhrOptions) {\n //TODO: .create is actually a collection function that's overridden here\n var collection = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/create_new_current`);\n return xhr.done(newData => {\n collection.setCurrent(new History(newData, [], historyOptions || {}));\n });\n },\n\n /** set the current history to the given history, placing it first in the collection.\n * Pass standard bbone options for use in unshift.\n * @triggers new-current passed history and this collection\n */\n setCurrent: function(history, options) {\n options = options || {};\n // new histories go in the front\n this.unshift(history, options);\n this.currentHistoryId = history.get(\"id\");\n if (!options.silent) {\n this.trigger(\"new-current\", history, this);\n }\n return this;\n },\n\n toString: function toString() {\n return `HistoryCollection(${this.length},current:${this.currentHistoryId})`;\n }\n});\n\n//==============================================================================\nexport default {\n History: History,\n HistoryCollection: HistoryCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-model.js","import CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport HDA_MODEL from \"mvc/history/hda-model\";\nimport HDCA_MODEL from \"mvc/history/hdca-model\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport AJAX_QUEUE from \"utils/ajax-queue\";\n\n//==============================================================================\nvar _super = CONTROLLED_FETCH_COLLECTION.PaginatedCollection;\n/** @class Backbone collection for history content.\n * NOTE: history content seems like a dataset collection, but differs in that it is mixed:\n * each element can be either an HDA (dataset) or a DatasetCollection and co-exist on\n * the same level.\n * Dataset collections on the other hand are not mixed and (so far) can only contain either\n * HDAs or child dataset collections on one level.\n * This is why this does not inherit from any of the DatasetCollections (currently).\n */\nvar HistoryContents = _super.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n // ........................................................................ set up\n limitPerPage: 500,\n\n /** @type {Integer} how many contents per call to fetch when using progressivelyFetchDetails */\n limitPerProgressiveFetch: 500,\n\n /** @type {String} order used here and when fetching from server */\n order: \"hid\",\n\n /** root api url */\n urlRoot: `${Galaxy.root}api/histories`,\n\n /** complete api url */\n url: function() {\n return `${this.urlRoot}/${this.historyId}/contents`;\n },\n\n /** Set up */\n initialize: function(models, options) {\n options = options || {};\n _super.prototype.initialize.call(this, models, options);\n\n this.history = options.history || null;\n this.setHistoryId(options.historyId || null);\n /** @type {Boolean} does this collection contain and fetch deleted elements */\n this.includeDeleted = options.includeDeleted || this.includeDeleted;\n /** @type {Boolean} does this collection contain and fetch non-visible elements */\n this.includeHidden = options.includeHidden || this.includeHidden;\n\n // backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection\n // and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute\n // manually here - if we don't, contents will not merge but be replaced/swapped.\n this.model.prototype.idAttribute = \"type_id\";\n },\n\n // ........................................................................ composite collection\n /** since history content is a mix, override model fn into a factory, creating based on history_content_type */\n model: function(attrs, options) {\n if (attrs.history_content_type === \"dataset\") {\n return new HDA_MODEL.HistoryDatasetAssociation(attrs, options);\n } else if (attrs.history_content_type === \"dataset_collection\") {\n switch (attrs.collection_type) {\n case \"list\":\n return new HDCA_MODEL.HistoryListDatasetCollection(attrs, options);\n case \"paired\":\n return new HDCA_MODEL.HistoryPairDatasetCollection(attrs, options);\n case \"list:paired\":\n return new HDCA_MODEL.HistoryListPairedDatasetCollection(attrs, options);\n case \"list:list\":\n return new HDCA_MODEL.HistoryListOfListsDatasetCollection(attrs, options);\n }\n // This is a hack inside a hack:\n // Raise a plain object with validationError to fake a model.validationError\n // (since we don't have a model to use validate with)\n // (the outer hack being the mixed content/model function in this collection)\n var msg = `Unknown collection_type: ${attrs.collection_type}`;\n console.warn(msg, attrs);\n return { validationError: msg };\n }\n return {\n validationError: `Unknown history_content_type: ${attrs.history_content_type}`\n };\n },\n\n setHistoryId: function(newId) {\n this.historyId = newId;\n this._setUpWebStorage();\n },\n\n /** Set up client side storage. Currently PersistanStorage keyed under 'history:' */\n _setUpWebStorage: function(initialSettings) {\n // TODO: use initialSettings\n if (!this.historyId) {\n return;\n }\n this.storage = new HISTORY_PREFS.HistoryPrefs({\n id: HISTORY_PREFS.HistoryPrefs.historyStorageKey(this.historyId)\n });\n this.trigger(\"new-storage\", this.storage, this);\n\n this.on({\n \"include-deleted\": function(newVal) {\n this.storage.includeDeleted(newVal);\n },\n \"include-hidden\": function(newVal) {\n this.storage.includeHidden(newVal);\n }\n });\n\n this.includeDeleted = this.storage.includeDeleted() || false;\n this.includeHidden = this.storage.includeHidden() || false;\n return this;\n },\n\n // ........................................................................ common queries\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_super.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", { ascending: true }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n hid: BASE_MVC.buildComparator(\"hid\", { ascending: false }),\n \"hid-asc\": BASE_MVC.buildComparator(\"hid\", { ascending: true })\n }),\n\n /** Get every model in this collection not in a 'ready' state (running). */\n running: function() {\n return this.filter(c => !c.inReadyState());\n },\n\n /** return contents that are not ready and not deleted/hidden */\n runningAndActive: function() {\n return this.filter(\n c =>\n !c.inReadyState() &&\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** Get the model with the given hid\n * @param {Int} hid the hid to search for\n * @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found\n */\n getByHid: function(hid) {\n // note: there *can* be more than one content with a given hid, this finds the first based on order\n return this.findWhere({ hid: hid });\n },\n\n /** return true if all contents have details */\n haveDetails: function() {\n return this.all(c => c.hasDetails());\n },\n\n // ........................................................................ hidden / deleted\n /** return a new contents collection of only hidden items */\n hidden: function() {\n return this.filter(c => c.hidden());\n },\n\n /** return a new contents collection of only hidden items */\n deleted: function() {\n return this.filter(c => c.get(\"deleted\"));\n },\n\n /** return a new contents collection of only hidden items */\n visibleAndUndeleted: function() {\n return this.filter(\n c =>\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** create a setter in order to publish the change */\n setIncludeDeleted: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeDeleted) {\n this.includeDeleted = setting;\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-deleted\", setting, this);\n }\n },\n\n /** create a setter in order to publish the change */\n setIncludeHidden: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeHidden) {\n this.includeHidden = setting;\n options = options || {};\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-hidden\", setting, this);\n }\n },\n\n // ........................................................................ ajax\n // ............ controlled fetch collection\n /** override to get expanded ids from sessionStorage and pass to API as details */\n fetch: function(options) {\n options = options || {};\n if (this.historyId && !options.details) {\n var prefs = HISTORY_PREFS.HistoryPrefs.get(this.historyId).toJSON();\n if (!_.isEmpty(prefs.expandedIds)) {\n options.details = _.values(prefs.expandedIds).join(\",\");\n }\n }\n return _super.prototype.fetch.call(this, options);\n },\n\n // ............. ControlledFetch stuff\n /** override to include the API versioning flag */\n _buildFetchData: function(options) {\n return _.extend(_super.prototype._buildFetchData.call(this, options), {\n v: \"dev\"\n });\n },\n\n /** Extend to include details and version */\n _fetchParams: _super.prototype._fetchParams.concat([\n // TODO: remove (the need for) both\n /** version */\n \"v\",\n /** dataset ids to get full details of */\n \"details\"\n ]),\n\n /** override to add deleted/hidden filters */\n _buildFetchFilters: function(options) {\n var superFilters = _super.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n }\n if (!this.includeHidden) {\n filters.visible = true;\n }\n return _.defaults(superFilters, filters);\n },\n\n // ............ paginated collection\n getTotalItemCount: function() {\n return this.history.contentsShown();\n },\n\n // ............ history contents specific ajax\n /** override to filter requested contents to those updated after the Date 'since' */\n fetchUpdated: function(since, options) {\n if (since) {\n options = options || { filters: {} };\n options.remove = false;\n options.filters = {\n \"update_time-ge\": since.toISOString(),\n // workflows will produce hidden datasets (non-output datasets) that still\n // need to be updated in the collection or they'll update forever\n // we can remove the default visible filter by using an 'empty' value\n visible: \"\"\n };\n }\n return this.fetch(options);\n },\n\n /** fetch all the deleted==true contents of this collection */\n fetchDeleted: function(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n // all deleted, purged or not\n deleted: true,\n purged: undefined\n });\n options.remove = false;\n\n self.trigger(\"fetching-deleted\", self);\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-deleted-done\", self);\n });\n },\n\n /** fetch all the visible==false contents of this collection */\n fetchHidden: function(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n visible: false\n });\n options.remove = false;\n\n self.trigger(\"fetching-hidden\", self);\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-hidden-done\", self);\n });\n },\n\n /** fetch detailed model data for all contents in this collection */\n fetchAllDetails: function(options) {\n options = options || {};\n var detailsFlag = { details: \"all\" };\n options.data = _.extend(options.data || {}, detailsFlag);\n return this.fetch(options);\n },\n\n /** specialty fetch method for retrieving the element_counts of all hdcas in the history */\n fetchCollectionCounts: function(options) {\n options = options || {};\n options.keys = [\"type_id\", \"element_count\"].join(\",\");\n options.filters = _.extend(options.filters || {}, {\n history_content_type: \"dataset_collection\"\n });\n options.remove = false;\n return this.fetch(options);\n },\n\n // ............. quasi-batch ops\n // TODO: to batch\n /** helper that fetches using filterParams then calls save on each fetched using updateWhat as the save params */\n _filterAndUpdate: function(filterParams, updateWhat) {\n var self = this;\n var idAttribute = self.model.prototype.idAttribute;\n var updateArgs = [updateWhat];\n\n return self.fetch({ filters: filterParams, remove: false }).then(fetched => {\n // convert filtered json array to model array\n fetched = fetched.reduce((modelArray, currJson, i) => {\n var model = self.get(currJson[idAttribute]);\n return model ? modelArray.concat(model) : modelArray;\n }, []);\n return self.ajaxQueue(\"save\", updateArgs, fetched);\n });\n },\n\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function(ajaxFn, args, collection) {\n collection = collection || this.models;\n return new AJAX_QUEUE.AjaxQueue(\n collection\n .slice()\n .reverse()\n .map((content, i) => {\n var fn = _.isString(ajaxFn) ? content[ajaxFn] : ajaxFn;\n return () => fn.apply(content, args);\n })\n ).deferred;\n },\n\n /** fetch contents' details in batches of limitPerCall - note: only get searchable details here */\n progressivelyFetchDetails: function(options) {\n options = options || {};\n var deferred = jQuery.Deferred();\n var self = this;\n var limit = options.limitPerCall || self.limitPerProgressiveFetch;\n // TODO: only fetch tags and annotations if specifically requested\n var searchAttributes = HDA_MODEL.HistoryDatasetAssociation.prototype.searchAttributes;\n var detailKeys = searchAttributes.join(\",\");\n\n function _recursivelyFetch(offset) {\n offset = offset || 0;\n var _options = _.extend(_.clone(options), {\n view: \"summary\",\n keys: detailKeys,\n limit: limit,\n offset: offset,\n reset: offset === 0,\n remove: false\n });\n\n _.defer(() => {\n self.fetch\n .call(self, _options)\n .fail(deferred.reject)\n .done(response => {\n deferred.notify(response, limit, offset);\n if (response.length !== limit) {\n self.allFetched = true;\n deferred.resolve(response, limit, offset);\n } else {\n _recursivelyFetch(offset + limit);\n }\n });\n });\n }\n _recursivelyFetch();\n return deferred;\n },\n\n /** does some bit of JSON represent something that can be copied into this contents collection */\n isCopyable: function(contentsJSON) {\n var copyableModelClasses = [\"HistoryDatasetAssociation\", \"HistoryDatasetCollectionAssociation\"];\n return (\n _.isObject(contentsJSON) && contentsJSON.id && _.contains(copyableModelClasses, contentsJSON.model_class)\n );\n },\n\n /** copy an existing, accessible hda into this collection */\n copy: function(json) {\n // TODO: somehow showhorn all this into 'save'\n var id;\n\n var type;\n var contentType;\n if (_.isString(json)) {\n id = json;\n contentType = \"hda\";\n type = \"dataset\";\n } else {\n id = json.id;\n contentType =\n {\n HistoryDatasetAssociation: \"hda\",\n LibraryDatasetDatasetAssociation: \"ldda\",\n HistoryDatasetCollectionAssociation: \"hdca\"\n }[json.model_class] || \"hda\";\n type = contentType === \"hdca\" ? \"dataset_collection\" : \"dataset\";\n }\n var collection = this;\n\n var xhr = jQuery\n .ajax(this.url(), {\n method: \"POST\",\n contentType: \"application/json\",\n data: JSON.stringify({\n content: id,\n source: contentType,\n type: type\n })\n })\n .done(response => {\n collection.add([response], { parse: true });\n })\n .fail((error, status, message) => {\n collection.trigger(\"error\", collection, xhr, {}, \"Error copying contents\", {\n type: type,\n id: id,\n source: contentType\n });\n });\n\n return xhr;\n },\n\n /** create a new HDCA in this collection */\n createHDCA: function(elementIdentifiers, collectionType, name, hideSourceItems, options) {\n // normally collection.create returns the new model, but we need the promise from the ajax, so we fake create\n //precondition: elementIdentifiers is an array of plain js objects\n // in the proper form to create the collectionType\n var hdca = this.model({\n history_content_type: \"dataset_collection\",\n collection_type: collectionType,\n history_id: this.historyId,\n name: name,\n hide_source_items: hideSourceItems || false,\n // should probably be able to just send in a bunch of json here and restruct per class\n // note: element_identifiers is now (incorrectly) an attribute\n element_identifiers: elementIdentifiers\n // do not create the model on the client until the ajax returns\n });\n return hdca.save(options);\n },\n\n // ........................................................................ searching\n /** return true if all contents have the searchable attributes */\n haveSearchDetails: function() {\n return (\n this.allFetched &&\n this.all((\n content // null (which is a valid returned annotation value)\n ) =>\n // will return false when using content.has( 'annotation' )\n //TODO: a bit hacky - formalize\n _.has(content.attributes, \"annotation\")\n )\n );\n },\n\n /** return a new collection of contents whose attributes contain the substring matchesWhat */\n matches: function(matchesWhat) {\n return this.filter(content => content.matches(matchesWhat));\n },\n\n // ........................................................................ misc\n /** In this override, copy the historyId to the clone */\n clone: function() {\n var clone = Backbone.Collection.prototype.clone.call(this);\n clone.historyId = this.historyId;\n return clone;\n },\n\n /** String representation. */\n toString: function() {\n return [\"HistoryContents(\", [this.historyId, this.length].join(), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n HistoryContents: HistoryContents\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-contents.js","import BASE_MVC from \"mvc/base-mvc\";\n\nvar logNamespace = \"history\";\n\n// ============================================================================\n/** session storage for individual history preferences */\nvar HistoryPrefs = BASE_MVC.SessionStorageModel.extend(\n /** @lends HistoryPrefs.prototype */ {\n //TODO:?? move to user prefs?\n defaults: {\n //TODO:?? expandedIds to array?\n expandedIds: {},\n show_deleted: false,\n show_hidden: false\n },\n\n /** add an hda id to the hash of expanded hdas */\n addExpanded: function(model) {\n //TODO: use type_id and not model\n var current = this.get(\"expandedIds\");\n current[model.id] = model.get(\"id\");\n this.save(\"expandedIds\", current);\n },\n\n /** remove an hda id from the hash of expanded hdas */\n removeExpanded: function(model) {\n var current = this.get(\"expandedIds\");\n delete current[model.id];\n this.save(\"expandedIds\", current);\n },\n\n isExpanded: function(contentId) {\n return _.result(this.get(\"expandedIds\"), contentId, false);\n },\n\n allExpanded: function() {\n return _.values(this.get(\"expandedIds\"));\n },\n\n clearExpanded: function() {\n this.set(\"expandedIds\", {});\n },\n\n includeDeleted: function(val) {\n // moving the invocation here so other components don't need to know the key\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_deleted\", val);\n }\n return this.get(\"show_deleted\");\n },\n\n includeHidden: function(val) {\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_hidden\", val);\n }\n return this.get(\"show_hidden\");\n },\n\n toString: function() {\n return `HistoryPrefs(${this.id})`;\n }\n },\n {\n // ........................................................................ class vars\n // class lvl for access w/o instantiation\n storageKeyPrefix: \"history:\",\n\n /** key string to store each histories settings under */\n historyStorageKey: function historyStorageKey(historyId) {\n if (!historyId) {\n throw new Error(`HistoryPrefs.historyStorageKey needs valid id: ${historyId}`);\n }\n // single point of change\n return HistoryPrefs.storageKeyPrefix + historyId;\n },\n\n /** return the existing storage for the history with the given id (or create one if it doesn't exist) */\n get: function get(historyId) {\n return new HistoryPrefs({\n id: HistoryPrefs.historyStorageKey(historyId)\n });\n },\n\n /** clear all history related items in sessionStorage */\n clearAll: function clearAll(historyId) {\n for (var key in sessionStorage) {\n if (key.indexOf(HistoryPrefs.storageKeyPrefix) === 0) {\n sessionStorage.removeItem(key);\n }\n }\n }\n }\n);\n\n//==============================================================================\nexport default {\n HistoryPrefs: HistoryPrefs\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-preferences.js","import BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"list\";\n//==============================================================================\n/** A view which, when first rendered, shows only summary data/attributes, but\n * can be expanded to show further details (and optionally fetch those\n * details from the server).\n */\nvar ExpandableView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: Although the reasoning behind them is different, this shares a lot with HiddenUntilActivated above: combine them\n //PRECONDITION: model must have method hasDetails\n //PRECONDITION: subclasses must have templates.el and templates.details\n\n initialize: function(attributes) {\n /** are the details of this view expanded/shown or not? */\n this.expanded = attributes.expanded || false;\n this.log(\"\\t expanded:\", this.expanded);\n this.fxSpeed = attributes.fxSpeed !== undefined ? attributes.fxSpeed : this.fxSpeed;\n },\n\n // ........................................................................ render main\n /** jq fx speed */\n fxSpeed: \"fast\",\n\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function(speed) {\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n * If the view is already expanded, build the details as well.\n */\n _buildNewRender: function() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = $(this.templates.el(this.model.toJSON(), this));\n if (this.expanded) {\n this.$details($newRender).replaceWith(this._renderDetails().show());\n }\n return $newRender;\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var view = this;\n\n if (speed === 0) {\n view._swapNewRender($newRender);\n view.trigger(\"rendered\", view);\n } else {\n $(view).queue(\"fx\", [\n next => {\n view.$el.fadeOut(speed, next);\n },\n next => {\n view._swapNewRender($newRender);\n next();\n },\n next => {\n view.$el.fadeIn(speed, next);\n },\n next => {\n view.trigger(\"rendered\", view);\n next();\n }\n ]);\n }\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function($newRender) {\n return this.$el\n .empty()\n .attr(\"class\", _.isFunction(this.className) ? this.className() : this.className)\n .append($newRender.children());\n },\n\n /** set up js behaviors, event handlers for elements within the given container\n * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)\n //make_popup_menus( $where );\n $where.find(\"[title]\").tooltip({ placement: \"bottom\" });\n },\n\n // ......................................................................... details\n /** shortcut to details DOM (as jQ) */\n $details: function($where) {\n $where = $where || this.$el;\n return $where.find(\"> .details\");\n },\n\n /** build the DOM for the details and set up behaviors on it */\n _renderDetails: function() {\n var $newDetails = $(this.templates.details(this.model.toJSON(), this));\n this._setUpBehaviors($newDetails);\n return $newDetails;\n },\n\n // ......................................................................... expansion/details\n /** Show or hide the details\n * @param {Boolean} expand if true, expand; if false, collapse\n */\n toggleExpanded: function(expand) {\n expand = expand === undefined ? !this.expanded : expand;\n if (expand) {\n this.expand();\n } else {\n this.collapse();\n }\n return this;\n },\n\n /** Render and show the full, detailed body of this view including extra data and controls.\n * note: if the model does not have detailed data, fetch that data before showing the body\n * @fires expanded when a body has been expanded\n */\n expand: function() {\n var view = this;\n return view._fetchModelDetails().always(() => {\n view._expand();\n });\n },\n\n /** Check for model details and, if none, fetch them.\n * @returns {jQuery.promise} the model.fetch.xhr if details are being fetched, an empty promise if not\n */\n _fetchModelDetails: function() {\n if (!this.model.hasDetails()) {\n return this.model.fetch();\n }\n return jQuery.when();\n },\n\n /** Inner fn called when expand (public) has fetched the details */\n _expand: function() {\n var view = this;\n var $newDetails = view._renderDetails();\n view.$details().replaceWith($newDetails);\n // needs to be set after the above or the slide will not show\n view.expanded = true;\n view.$details().slideDown(view.fxSpeed, () => {\n view.trigger(\"expanded\", view);\n });\n },\n\n /** Hide the body/details of an HDA.\n * @fires collapsed when a body has been collapsed\n */\n collapse: function() {\n this.debug(`${this}(ExpandableView).collapse`);\n var view = this;\n view.expanded = false;\n this.$details().slideUp(view.fxSpeed, () => {\n view.trigger(\"collapsed\", view);\n });\n }\n});\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * Inherits from Expandable, Selectable, Draggable.\n * The DOM contains warnings, a title bar, and a series of primary action controls.\n * Primary actions are meant to be easily accessible item functions (such as delete)\n * that are rendered in the title bar.\n *\n * Details are rendered when the user clicks the title bar or presses enter/space when\n * the title bar is in focus.\n *\n * Designed as a base class for history panel contents - but usable elsewhere (I hope).\n */\nvar ListItemView = ExpandableView.extend(\n BASE_MVC.mixin(BASE_MVC.SelectableViewMixin, BASE_MVC.DraggableViewMixin, {\n tagName: \"div\",\n className: \"list-item\",\n\n /** Set up the base class and all mixins */\n initialize: function(attributes) {\n ExpandableView.prototype.initialize.call(this, attributes);\n BASE_MVC.SelectableViewMixin.initialize.call(this, attributes);\n BASE_MVC.DraggableViewMixin.initialize.call(this, attributes);\n this._setUpListeners();\n },\n\n /** event listeners */\n _setUpListeners: function() {\n // hide the primary actions in the title bar when selectable and narrow\n this.on(\n \"selectable\",\n function(isSelectable) {\n if (isSelectable) {\n this.$(\".primary-actions\").hide();\n } else {\n this.$(\".primary-actions\").show();\n }\n },\n this\n );\n return this;\n },\n\n // ........................................................................ rendering\n /** In this override, call methods to build warnings, titlebar and primary actions */\n _buildNewRender: function() {\n var $newRender = ExpandableView.prototype._buildNewRender.call(this);\n $newRender.children(\".warnings\").replaceWith(this._renderWarnings());\n $newRender.children(\".title-bar\").replaceWith(this._renderTitleBar());\n $newRender.children(\".primary-actions\").append(this._renderPrimaryActions());\n $newRender.find(\"> .title-bar .subtitle\").replaceWith(this._renderSubtitle());\n return $newRender;\n },\n\n /** In this override, render the selector controls and set up dragging before the swap */\n _swapNewRender: function($newRender) {\n ExpandableView.prototype._swapNewRender.call(this, $newRender);\n if (this.selectable) {\n this.showSelector(0);\n }\n if (this.draggable) {\n this.draggableOn();\n }\n return this.$el;\n },\n\n /** Render any warnings the item may need to show (e.g. \"I'm deleted\") */\n _renderWarnings: function() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.warnings, templateFn => {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderTitleBar: function() {\n return $(this.templates.titleBar(this.model.toJSON(), this));\n },\n\n /** Return an array of jQ objects containing common/easily-accessible item controls */\n _renderPrimaryActions: function() {\n // override this\n return [];\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderSubtitle: function() {\n return $(this.templates.subtitle(this.model.toJSON(), this));\n },\n\n // ......................................................................... events\n /** event map */\n events: {\n // expand the body when the title is clicked or when in focus and space or enter is pressed\n \"click .title-bar\": \"_clickTitleBar\",\n \"keydown .title-bar\": \"_keyDownTitleBar\",\n \"click .selector\": \"toggleSelect\"\n },\n\n /** expand when the title bar is clicked */\n _clickTitleBar: function(event) {\n event.stopPropagation();\n if (event.altKey) {\n this.toggleSelect(event);\n if (!this.selectable) {\n this.showSelector();\n }\n } else {\n this.toggleExpanded();\n }\n },\n\n /** expand when the title bar is in focus and enter or space is pressed */\n _keyDownTitleBar: function(event) {\n // bail (with propagation) if keydown and not space or enter\n var KEYCODE_SPACE = 32;\n\n var KEYCODE_RETURN = 13;\n if (\n event &&\n event.type === \"keydown\" &&\n (event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN)\n ) {\n this.toggleExpanded();\n event.stopPropagation();\n return false;\n }\n return true;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `ListItemView(${modelString})`;\n }\n })\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListItemView.prototype.templates = (() => {\n var elTemplato = BASE_MVC.wrapTemplate([\n '
\",\n // space for title bar buttons - gen. floated to the right\n '',\n '',\n\n // expandable area for more details\n '',\n \"
\"\n ]);\n\n var warnings = {};\n\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display\n '
',\n //TODO: prob. belongs in dataset-list-item\n '',\n '
',\n '<%- element.name %>',\n \"
\",\n '',\n \"
\"\n ],\n \"element\"\n );\n\n var subtitleTemplate = BASE_MVC.wrapTemplate([\n // override this\n ''\n ]);\n\n var detailsTemplate = BASE_MVC.wrapTemplate([\n // override this\n ''\n ]);\n\n return {\n el: elTemplato,\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate,\n details: detailsTemplate\n };\n})();\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * *AND* can display some sub-list of it's own when expanded (e.g. dataset collections).\n * This list will 'foldout' when the item is expanded depending on this.foldoutStyle:\n * If 'foldout': will expand vertically to show the nested list\n * If 'drilldown': will overlay the parent list\n *\n * Inherits from ListItemView.\n *\n * _renderDetails does the work of creating this.details: a sub-view that shows the nested list\n */\nvar FoldoutListItemView = ListItemView.extend({\n /** If 'foldout': show the sub-panel inside the expanded item\n * If 'drilldown': only fire events and handle by pub-sub\n * (allow the panel containing this item to attach it, hide itself, etc.)\n */\n foldoutStyle: \"foldout\",\n /** Panel view class to instantiate for the sub-panel */\n foldoutPanelClass: null,\n\n /** override to:\n * add attributes foldoutStyle and foldoutPanelClass for config poly\n * disrespect attributes.expanded if drilldown\n */\n initialize: function(attributes) {\n if (this.foldoutStyle === \"drilldown\") {\n this.expanded = false;\n }\n this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;\n this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;\n\n ListItemView.prototype.initialize.call(this, attributes);\n this.foldout = this._createFoldoutPanel();\n },\n\n /** in this override, attach the foldout panel when rendering details */\n _renderDetails: function() {\n if (this.foldoutStyle === \"drilldown\") {\n return $();\n }\n var $newDetails = ListItemView.prototype._renderDetails.call(this);\n return this._attachFoldout(this.foldout, $newDetails);\n },\n\n /** In this override, handle collection expansion. */\n _createFoldoutPanel: function() {\n var model = this.model;\n var FoldoutClass = this._getFoldoutPanelClass(model);\n var options = this._getFoldoutPanelOptions(model);\n\n var foldout = new FoldoutClass(\n _.extend(options, {\n model: model\n })\n );\n\n return foldout;\n },\n\n /** Stub to return proper foldout panel class */\n _getFoldoutPanelClass: function() {\n // override\n return this.foldoutPanelClass;\n },\n\n /** Stub to return proper foldout panel options */\n _getFoldoutPanelOptions: function() {\n return {\n // propagate foldout style down\n foldoutStyle: this.foldoutStyle,\n fxSpeed: this.fxSpeed\n };\n },\n\n /** Render the foldout panel inside the view, hiding controls */\n _attachFoldout: function(foldout, $whereTo) {\n $whereTo = $whereTo || this.$(\"> .details\");\n this.foldout = foldout.render(0);\n foldout.$(\"> .controls\").hide();\n return $whereTo.append(foldout.$el);\n },\n\n /** In this override, branch on foldoutStyle to show expanded */\n expand: function() {\n var view = this;\n return view._fetchModelDetails().always(() => {\n if (view.foldoutStyle === \"foldout\") {\n view._expand();\n } else if (view.foldoutStyle === \"drilldown\") {\n view._expandByDrilldown();\n }\n });\n },\n\n /** For drilldown, set up close handler and fire expanded:drilldown\n * containing views can listen to this and handle other things\n * (like hiding themselves) by listening for expanded/collapsed:drilldown\n */\n _expandByDrilldown: function() {\n var view = this;\n // attachment and rendering done by listener\n view.listenTo(view.foldout, \"close\", () => {\n view.trigger(\"collapsed:drilldown\", view, view.foldout);\n });\n view.trigger(\"expanded:drilldown\", view, view.foldout);\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nFoldoutListItemView.prototype.templates = (() => {\n var detailsTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n // override with more info (that goes above the panel)\n \"
\"\n ],\n \"collection\"\n );\n\n return _.extend({}, ListItemView.prototype.templates, {\n details: detailsTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n ExpandableView: ExpandableView,\n ListItemView: ListItemView,\n FoldoutListItemView: FoldoutListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/list/list-item.js","import LIST_ITEM from \"mvc/list/list-item\";\nimport STATES from \"mvc/dataset/states\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"dataset\";\n/*==============================================================================\nTODO:\n straighten out state rendering and templates used\n inaccessible/STATES.NOT_VIEWABLE is a special case\n simplify button rendering\n\n==============================================================================*/\nvar _super = LIST_ITEM.ListItemView;\n/** @class Read only list view for either LDDAs, HDAs, or HDADCEs.\n * Roughly, any DatasetInstance (and not a raw Dataset).\n */\nvar DatasetListItemView = _super.extend(\n /** @lends DatasetListItemView.prototype */ {\n _logNamespace: logNamespace,\n\n className: `${_super.prototype.className} dataset`,\n //TODO:?? doesn't exactly match an hda's type_id\n id: function() {\n return [\"dataset\", this.model.get(\"id\")].join(\"-\");\n },\n\n /** Set up: instance vars, options, and event handlers */\n initialize: function(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(`${this}.initialize:`, attributes);\n _super.prototype.initialize.call(this, attributes);\n\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n },\n\n /** event listeners */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n var self = this;\n\n // re-rendering on any model changes\n return self.listenTo(self.model, {\n change: function(model) {\n // if the model moved into the ready state and is expanded without details, fetch those details now\n if (\n self.model.changedAttributes().state &&\n self.model.inReadyState() &&\n self.expanded &&\n !self.model.hasDetails()\n ) {\n // normally, will render automatically (due to fetch -> change),\n // but! setting_metadata sometimes doesn't cause any other changes besides state\n // so, not rendering causes it to seem frozen in setting_metadata state\n self.model.fetch({ silent: true }).done(() => {\n self.render();\n });\n } else {\n if (_.has(model.changed, \"tags\") && _.keys(model.changed).length === 1) {\n // If only the tags have changed, rerender specifically\n // the titlebar region. Otherwise default to the full\n // render.\n self.$(\".nametags\").html(self._renderNametags());\n } else {\n self.render();\n }\n }\n }\n });\n },\n\n // ......................................................................... expandable\n /** In this override, only get details if in the ready state, get rerunnable if in other states.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... removal\n /** Remove this view's html from the DOM and remove all event listeners.\n * @param {Number or String} speed jq effect speed\n * @param {Function} callback an optional function called when removal is done (scoped to this view)\n */\n remove: function(speed, callback) {\n var view = this;\n speed = speed || this.fxSpeed;\n this.$el.fadeOut(speed, () => {\n Backbone.View.prototype.remove.call(view);\n if (callback) {\n callback.call(view);\n }\n });\n },\n\n // ......................................................................... rendering\n /* TODO:\n dataset states are the issue primarily making dataset rendering complex\n each state should have it's own way of displaying/set of details\n often with different actions that can be applied\n throw in deleted/purged/visible and things get complicated easily\n I've considered (a couple of times) - creating a view for each state\n - but recreating the view during an update...seems wrong\n */\n /** In this override, add the dataset state as a class for use with state-based CSS */\n _swapNewRender: function($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n if (this.model.has(\"state\")) {\n this.$el.addClass(`state-${this.model.get(\"state\")}`);\n }\n return this.$el;\n },\n\n // ................................................................................ titlebar\n /** In this override, add the dataset display button. */\n _renderPrimaryActions: function() {\n // render just the display for read-only\n return [this._renderDisplayButton()];\n },\n\n /** Render icon-button to display dataset data */\n _renderDisplayButton: function() {\n // don't show display if not viewable or not accessible\n var state = this.model.get(\"state\");\n if (state === STATES.NOT_VIEWABLE || state === STATES.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n\n var displayBtnData = {\n target: this.linkTarget,\n classes: \"display-btn\"\n };\n\n // show a disabled display if the data's been purged\n if (this.model.get(\"purged\")) {\n displayBtnData.disabled = true;\n displayBtnData.title = _l(\"Cannot display datasets removed from disk\");\n\n // disable if still uploading\n } else if (state === STATES.UPLOAD) {\n displayBtnData.disabled = true;\n displayBtnData.title = _l(\"This dataset must finish uploading before it can be viewed\");\n\n // disable if still new\n } else if (state === STATES.NEW) {\n displayBtnData.disabled = true;\n displayBtnData.title = _l(\"This dataset is not yet viewable\");\n } else {\n displayBtnData.title = _l(\"View data\");\n\n // default link for dataset\n displayBtnData.href = this.model.urls.display;\n\n // add frame manager option onclick event\n var self = this;\n displayBtnData.onclick = ev => {\n if (Galaxy.frame && Galaxy.frame.active) {\n // Add dataset to frames.\n Galaxy.frame.addDataset(self.model.get(\"id\"));\n ev.preventDefault();\n }\n };\n }\n displayBtnData.faIcon = \"fa-eye\";\n return faIconButton(displayBtnData);\n },\n\n // ......................................................................... rendering details\n /** Render the enclosing div of the hda body and, if expanded, the html in the body\n * @returns {jQuery} rendered DOM\n */\n _renderDetails: function() {\n //TODO: generalize to be allow different details for each state\n\n // no access - render nothing but a message\n if (this.model.get(\"state\") === STATES.NOT_VIEWABLE) {\n return $(this.templates.noAccess(this.model.toJSON(), this));\n }\n\n var $details = _super.prototype._renderDetails.call(this);\n $details\n .find(\".actions .left\")\n .empty()\n .append(this._renderSecondaryActions());\n $details\n .find(\".summary\")\n .html(this._renderSummary())\n .prepend(this._renderDetailMessages());\n $details.find(\".display-applications\").html(this._renderDisplayApplications());\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /** Defer to the appropo summary rendering fn based on state */\n _renderSummary: function() {\n var json = this.model.toJSON();\n var summaryRenderFn = this.templates.summaries[json.state];\n summaryRenderFn = summaryRenderFn || this.templates.summaries.unknown;\n return summaryRenderFn(json, this);\n },\n\n /** Render messages to be displayed only when the details are shown */\n _renderDetailMessages: function() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.detailMessages, templateFn => {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the external display application links */\n _renderDisplayApplications: function() {\n if (this.model.isDeletedOrPurged()) {\n return \"\";\n }\n // render both old and new display apps using the same template\n return [\n this.templates.displayApplications(this.model.get(\"display_apps\"), this),\n this.templates.displayApplications(this.model.get(\"display_types\"), this)\n ].join(\"\");\n },\n\n // ......................................................................... secondary/details actions\n /** A series of links/buttons for less commonly used actions: re-run, info, etc. */\n _renderSecondaryActions: function() {\n this.debug(\"_renderSecondaryActions\");\n switch (this.model.get(\"state\")) {\n case STATES.NOT_VIEWABLE:\n return [];\n case STATES.OK:\n case STATES.FAILED_METADATA:\n case STATES.ERROR:\n return [this._renderDownloadButton(), this._renderShowParamsButton()];\n }\n return [this._renderShowParamsButton()];\n },\n\n /** Render icon-button to show the input and output (stdout/err) for the job that created this.\n * @returns {jQuery} rendered DOM\n */\n _renderShowParamsButton: function() {\n // gen. safe to show in all cases\n return faIconButton({\n title: _l(\"View details\"),\n classes: \"params-btn\",\n href: this.model.urls.show_params,\n target: this.linkTarget,\n faIcon: \"fa-info-circle\",\n onclick: function(ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Dataset details\",\n url: this.href\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n }\n });\n },\n\n /** Render icon-button/popupmenu to download the data (and/or the associated meta files (bai, etc.)) for this.\n * @returns {jQuery} rendered DOM\n */\n _renderDownloadButton: function() {\n // don't show anything if the data's been purged\n if (this.model.get(\"purged\") || !this.model.hasData()) {\n return null;\n }\n\n // return either: a popupmenu with links to download assoc. meta files (if there are meta files)\n // or a single download icon-button (if there are no meta files)\n if (!_.isEmpty(this.model.get(\"meta_files\"))) {\n return this._renderMetaFileDownloadButton();\n }\n\n return $(\n [\n '`,\n '',\n \"\"\n ].join(\"\")\n );\n },\n\n /** Render the download button which opens a dropdown with links to download assoc. meta files (indeces, etc.) */\n _renderMetaFileDownloadButton: function() {\n var urls = this.model.urls;\n return $(\n [\n '
'],\n \"dataset\"\n );\n\n // messages to be displayed only within the details section ('below the fold')\n var detailMessageTemplates = {\n resubmitted: BASE_MVC.wrapTemplate([\n // deleted not purged\n \"<% if( model.resubmitted ){ %>\",\n '
',\n _l(\"The job creating this dataset has been resubmitted\"),\n \"
\",\n \"<% } %>\"\n ])\n };\n\n // this is applied to both old and new style display apps\n var displayApplicationsTemplate = BASE_MVC.wrapTemplate(\n [\n \"<% _.each( apps, function( app ){ %>\",\n '
\"\n ],\n \"collection\"\n );\n\n // use element identifier\n var subtitleTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n '<% var countText = collection.element_count? ( collection.element_count + \" \" ) : \"\"; %>',\n '<% if( collection.collection_type === \"list\" ){ %>',\n _l(\"a list of <%- countText %>datasets\"),\n '<% } else if( collection.collection_type === \"paired\" ){ %>',\n _l(\"a pair of datasets\"),\n '<% } else if( collection.collection_type === \"list:paired\" ){ %>',\n _l(\"a list of <%- countText %>dataset pairs\"),\n '<% } else if( collection.collection_type === \"list:list\" ){ %>',\n _l(\"a list of <%- countText %>dataset lists\"),\n \"<% } %>\",\n \"
\"\n ],\n \"collection\"\n );\n\n return _.extend({}, FoldoutListItemView.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate\n });\n})();\n\n//==============================================================================\n/** @class Read only view for DatasetCollectionElement.\n */\nvar DCEListItemView = ListItemView.extend(\n /** @lends DCEListItemView.prototype */ {\n /** add the DCE class to the list item */\n className: `${ListItemView.prototype.className} dataset-collection-element`,\n\n /** set up */\n initialize: function(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DCEListItemView.initialize:\", attributes);\n ListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DCEListItemView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDCEListItemView.prototype.templates = (() => {\n // use the element identifier here - since that will persist and the user will need it\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n '
',\n '<%- element.element_identifier %>',\n \"
\",\n '',\n \"
\"\n ],\n \"element\"\n );\n\n return _.extend({}, ListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation\n * (a dataset contained in a dataset collection).\n */\nvar DatasetDCEListItemView = DATASET_LI.DatasetListItemView.extend(\n /** @lends DatasetDCEListItemView.prototype */ {\n className: `${DATASET_LI.DatasetListItemView.prototype.className} dataset-collection-element`,\n\n /** set up */\n initialize: function(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DatasetDCEListItemView.initialize:\", attributes);\n DATASET_LI.DatasetListItemView.prototype.initialize.call(this, attributes);\n },\n\n /** In this override, only get details if in the ready state.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DatasetDCEListItemView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetDCEListItemView.prototype.templates = (() => {\n // use the element identifier here and not the dataset name\n //TODO:?? can we steal the DCE titlebar?\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n '',\n '
',\n '<%- element.element_identifier %>',\n \"
\",\n \"
\"\n ],\n \"element\"\n );\n\n return _.extend({}, DATASET_LI.DatasetListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection\n * (a nested DC).\n */\nvar NestedDCDCEListItemView = DCListItemView.extend(\n /** @lends NestedDCDCEListItemView.prototype */ {\n className: `${DCListItemView.prototype.className} dataset-collection-element`,\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function($newRender) {\n DCListItemView.prototype._swapNewRender.call(this, $newRender);\n var state = this.model.get(\"state\") || \"ok\";\n this.$el.addClass(`state-${state}`);\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `NestedDCDCEListItemView(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n DCListItemView: DCListItemView,\n DCEListItemView: DCEListItemView,\n DatasetDCEListItemView: DatasetDCEListItemView,\n NestedDCDCEListItemView: NestedDCDCEListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-li.js","/** Generic form view */\nimport Form from \"mvc/form/form-view\";\nimport Ui from \"mvc/ui/ui-misc\";\nvar View = Backbone.View.extend({\n initialize: function(options) {\n this.model = new Backbone.Model(options);\n this.url = this.model.get(\"url\");\n this.redirect = this.model.get(\"redirect\");\n this.setElement(\"\");\n this.render();\n },\n\n render: function() {\n var self = this;\n $.ajax({\n url: Galaxy.root + this.url,\n type: \"GET\"\n })\n .done(response => {\n var options = $.extend({}, self.model.attributes, response);\n var form = new Form({\n title: options.title,\n message: options.message,\n status: options.status || \"warning\",\n icon: options.icon,\n inputs: options.inputs,\n buttons: {\n submit: new Ui.Button({\n tooltip: options.submit_tooltip,\n title: options.submit_title || \"Save\",\n icon: options.submit_icon || \"fa-save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function() {\n self._submit(form);\n }\n })\n }\n });\n self.$el.empty().append(form.$el);\n })\n .fail(response => {\n self.$el.empty().append(\n new Ui.Message({\n message: `Failed to load resource ${self.url}.`,\n status: \"danger\",\n persistent: true\n }).$el\n );\n });\n },\n\n _submit: function(form) {\n var self = this;\n $.ajax({\n url: Galaxy.root + self.url,\n data: JSON.stringify(form.data.create()),\n type: \"PUT\",\n contentType: \"application/json\"\n })\n .done(response => {\n var success_message = {\n message: response.message,\n status: \"success\",\n persistent: false\n };\n if (self.redirect) {\n window.location = `${Galaxy.root + self.redirect}?${$.param(success_message)}`;\n } else {\n form.data.matchModel(response, (input, input_id) => {\n form.field_list[input_id].value(input.value);\n });\n self._showMessage(form, success_message);\n }\n })\n .fail(response => {\n self._showMessage(form, {\n message: response.responseJSON.err_msg,\n status: \"danger\",\n persistent: false\n });\n });\n },\n\n _showMessage: function(form, options) {\n var $panel = form.$el\n .parents()\n .filter(function() {\n return [\"auto\", \"scroll\"].indexOf($(this).css(\"overflow\")) != -1;\n })\n .first();\n $panel.animate({ scrollTop: 0 }, 500);\n form.message.update(options);\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/form/form-wrapper.js","import STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"dataset\";\n//==============================================================================\nvar searchableMixin = BASE_MVC.SearchableModelMixin;\n/** @class base model for any DatasetAssociation (HDAs, LDDAs, DatasetCollectionDAs).\n * No knowledge of what type (HDA/LDDA/DCDA) should be needed here.\n * The DA's are made searchable (by attribute) by mixing in SearchableModelMixin.\n */\nvar DatasetAssociation = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(\n BASE_MVC.mixin(\n searchableMixin,\n /** @lends DatasetAssociation.prototype */ {\n _logNamespace: logNamespace,\n\n /** default attributes for a model */\n defaults: {\n state: STATES.NEW,\n deleted: false,\n purged: false,\n name: \"(unnamed dataset)\",\n accessible: true,\n // sniffed datatype (sam, tabular, bed, etc.)\n data_type: \"\",\n file_ext: \"\",\n file_size: 0,\n\n // array of associated file types (eg. [ 'bam_index', ... ])\n meta_files: [],\n\n misc_blurb: \"\",\n misc_info: \"\",\n\n tags: []\n // do NOT default on annotation, as this default is valid and will be passed on 'save'\n // which is incorrect behavior when the model is only partially fetched (annos are not passed in summary data)\n //annotation : ''\n },\n\n /** instance vars and listeners */\n initialize: function(attributes, options) {\n this.debug(`${this}(Dataset).initialize`, attributes, options);\n\n //!! this state is not in trans.app.model.Dataset.states - set it here -\n if (!this.get(\"accessible\")) {\n this.set(\"state\", STATES.NOT_VIEWABLE);\n }\n\n /** Datasets rely/use some web controllers - have the model generate those URLs on startup */\n this.urls = this._generateUrls();\n\n this._setUpListeners();\n },\n\n /** returns misc. web urls for rendering things like re-run, display, etc. */\n _generateUrls: function() {\n var id = this.get(\"id\");\n if (!id) {\n return {};\n }\n var urls = {\n purge: `datasets/${id}/purge_async`,\n display: `datasets/${id}/display/?preview=True`,\n edit: `datasets/edit?dataset_id=${id}`,\n download: `datasets/${id}/display${this._downloadQueryParameters()}`,\n report_error: `dataset/errors?id=${id}`,\n rerun: `tool_runner/rerun?id=${id}`,\n show_params: `datasets/${id}/show_params`,\n visualization: \"visualization\",\n meta_download: `dataset/get_metadata_file?hda_id=${id}&metadata_name=`\n };\n _.each(urls, (value, key) => {\n urls[key] = Galaxy.root + value;\n });\n this.urls = urls;\n return urls;\n },\n\n _downloadQueryParameters: function() {\n return `?to_ext=${this.get(\"file_ext\")}`;\n },\n\n /** set up any event listeners\n * event: state:ready fired when this DA moves into/is already in a ready state\n */\n _setUpListeners: function() {\n // if the state has changed and the new state is a ready state, fire an event\n this.on(\"change:state\", function(currModel, newState) {\n this.log(`${this} has changed state:`, currModel, newState);\n if (this.inReadyState()) {\n this.trigger(\"state:ready\", currModel, newState, this.previous(\"state\"));\n }\n });\n // the download url (currently) relies on having a correct file extension\n this.on(\"change:id change:file_ext\", function(currModel) {\n this._generateUrls();\n });\n },\n\n // ........................................................................ common queries\n /** override to add urls */\n toJSON: function() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n //console.warn( 'returning json?' );\n //return json;\n return _.extend(json, {\n urls: this.urls\n });\n },\n\n /** Is this dataset deleted or purged? */\n isDeletedOrPurged: function() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n /** Is this dataset in a 'ready' state; where 'Ready' states are states where no\n * processing (for the ds) is left to do on the server.\n */\n inReadyState: function() {\n var ready = _.contains(STATES.READY_STATES, this.get(\"state\"));\n return this.isDeletedOrPurged() || ready;\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function() {\n // if it's inaccessible assume it has everything it needs\n if (!this.get(\"accessible\")) {\n return true;\n }\n return this.has(\"annotation\");\n },\n\n /** Convenience function to match dataset.has_data. */\n hasData: function() {\n return this.get(\"file_size\") > 0;\n },\n\n // ........................................................................ ajax\n fetch: function(options) {\n var dataset = this;\n return Backbone.Model.prototype.fetch.call(this, options).always(() => {\n dataset._generateUrls();\n });\n },\n\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** override to wait by default */\n save: function(attrs, options) {\n options = options || {};\n options.wait = _.isUndefined(options.wait) ? true : options.wait;\n return Backbone.Model.prototype.save.call(this, attrs, options);\n },\n\n //NOTE: subclasses of DA's will need to implement url and urlRoot in order to have these work properly\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** remove the file behind this dataset from the filesystem (if permitted) */\n purge: function _purge(options) {\n //TODO: use, override model.destroy, HDA.delete({ purge: true })\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n options = options || {};\n options.url = this.urls.purge;\n\n //TODO: ideally this would be a DELETE call to the api\n // using purge async for now\n var hda = this;\n\n var xhr = jQuery.ajax(options);\n xhr.done((message, status, responseObj) => {\n hda.set({ deleted: true, purged: true });\n });\n xhr.fail((xhr, status, message) => {\n // Exception messages are hidden within error page including: '...not allowed in this Galaxy instance.'\n // unbury and re-add to xhr\n var error = _l(\"Unable to purge dataset\");\n var messageBuriedInUnfortunatelyFormattedError =\n \"Removal of datasets by users \" + \"is not allowed in this Galaxy instance\";\n if (xhr.responseJSON && xhr.responseJSON.error) {\n error = xhr.responseJSON.error;\n } else if (xhr.responseText.indexOf(messageBuriedInUnfortunatelyFormattedError) !== -1) {\n error = messageBuriedInUnfortunatelyFormattedError;\n }\n xhr.responseText = error;\n hda.trigger(\"error\", hda, xhr, options, _l(error), {\n error: error\n });\n });\n return xhr;\n },\n\n // ........................................................................ searching\n /** what attributes of an HDA will be used in a text search */\n searchAttributes: [\"name\", \"file_ext\", \"genome_build\", \"misc_blurb\", \"misc_info\", \"annotation\", \"tags\"],\n\n /** our attr keys don't often match the labels we display to the user - so, when using\n * attribute specifiers ('name=\"bler\"') in a term, allow passing in aliases for the\n * following attr keys.\n */\n searchAliases: {\n title: \"name\",\n format: \"file_ext\",\n database: \"genome_build\",\n blurb: \"misc_blurb\",\n description: \"misc_blurb\",\n info: \"misc_info\",\n tag: \"tags\"\n },\n\n // ........................................................................ misc\n /** String representation */\n toString: function() {\n var nameAndId = this.get(\"id\") || \"\";\n if (this.get(\"name\")) {\n nameAndId = `\"${this.get(\"name\")}\",${nameAndId}`;\n }\n return `Dataset(${nameAndId})`;\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection for dataset associations.\n */\nvar DatasetAssociationCollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends HistoryContents.prototype */ {\n _logNamespace: logNamespace,\n\n model: DatasetAssociation,\n\n /** root api url */\n urlRoot: `${Galaxy.root}api/datasets`,\n\n /** url fn */\n url: function() {\n return this.urlRoot;\n },\n\n // ........................................................................ common queries\n /** Get the ids of every item in this collection\n * @returns array of encoded ids\n */\n ids: function() {\n return this.map(item => item.get(\"id\"));\n },\n\n /** Get contents that are not ready\n * @returns array of content models\n */\n notReady: function() {\n return this.filter(content => !content.inReadyState());\n },\n\n /** return true if any datasets don't have details */\n haveDetails: function() {\n return this.all(dataset => dataset.hasDetails());\n },\n\n // ........................................................................ ajax\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function(ajaxFn, options) {\n var deferred = jQuery.Deferred();\n var startingLength = this.length;\n var responses = [];\n\n if (!startingLength) {\n deferred.resolve([]);\n return deferred;\n }\n\n // use reverse order (stylistic choice)\n var ajaxFns = this.chain()\n .reverse()\n .map((dataset, i) => () => {\n var xhr = ajaxFn.call(dataset, options);\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(response => {\n deferred.notify({\n curr: i,\n total: startingLength,\n response: response,\n model: dataset\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(response => {\n responses.push(response);\n if (ajaxFns.length) {\n ajaxFns.shift()();\n } else {\n deferred.resolve(responses);\n }\n });\n })\n .value();\n // start the queue\n ajaxFns.shift()();\n\n return deferred;\n },\n\n // ........................................................................ sorting/filtering\n /** return a new collection of datasets whose attributes contain the substring matchesWhat */\n matches: function(matchesWhat) {\n return this.filter(dataset => dataset.matches(matchesWhat));\n },\n\n /** String representation. */\n toString: function() {\n return [\"DatasetAssociationCollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\nexport default {\n DatasetAssociation: DatasetAssociation,\n DatasetAssociationCollection: DatasetAssociationCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/dataset-model.js","import STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Mixin for HistoryContents content (HDAs, HDCAs).\n */\nvar HistoryContentMixin = {\n /** default attributes for a model */\n defaults: {\n /** parent (containing) history */\n history_id: null,\n /** some content_type (HistoryContents can contain mixed model classes) */\n history_content_type: null,\n /** indicating when/what order the content was generated in the context of the history */\n hid: null,\n /** whether the user wants the content shown (visible) */\n visible: true\n },\n\n // ........................................................................ mixed content element\n // In order to be part of a MIXED bbone collection, we can't rely on the id\n // (which may collide btwn models of different classes)\n // Instead, use type_id which prefixes the history_content_type so the bbone collection can differentiate\n idAttribute: \"type_id\",\n\n // ........................................................................ common queries\n /** the more common alias of visible */\n hidden: function() {\n return !this.get(\"visible\");\n },\n\n //TODO: remove\n /** based on includeDeleted, includeHidden (gen. from the container control),\n * would this ds show in the list of ds's?\n * @param {Boolean} includeDeleted are we showing deleted hdas?\n * @param {Boolean} includeHidden are we showing hidden hdas?\n */\n isVisible: function(includeDeleted, includeHidden) {\n var isVisible = true;\n if (!includeDeleted && (this.get(\"deleted\") || this.get(\"purged\"))) {\n isVisible = false;\n }\n if (!includeHidden && !this.get(\"visible\")) {\n isVisible = false;\n }\n return isVisible;\n },\n\n // ........................................................................ ajax\n //TODO?: these are probably better done on the leaf classes\n /** history content goes through the 'api/histories' API */\n urlRoot: `${Galaxy.root}api/histories/`,\n\n /** full url spec. for this content */\n url: function() {\n var url = `${this.urlRoot + this.get(\"history_id\")}/contents/${this.get(\"history_content_type\")}s/${this.get(\n \"id\"\n )}`;\n return url;\n },\n\n /** save this content as not visible */\n hide: function(options) {\n if (!this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: false }, options);\n },\n /** save this content as visible */\n unhide: function(options) {\n if (this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: true }, options);\n },\n\n // ........................................................................ misc\n toString: function() {\n return [this.get(\"type_id\"), this.get(\"hid\"), this.get(\"name\")].join(\":\");\n }\n};\n\n//==============================================================================\nexport default {\n HistoryContentMixin: HistoryContentMixin\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-content-model.js","/* For presentation-related functionality shared across collection creators.\n Particularily overlapping functionality related to name processing and help.\n*/\nvar CollectionCreatorMixin = {\n /** add (or clear if clear is truthy) a validation warning to the DOM element described in what */\n _validationWarning: function(what, clear) {\n var VALIDATION_CLASS = \"validation-warning\";\n if (what === \"name\") {\n what = this.$(\".collection-name\").add(this.$(\".collection-name-prompt\"));\n this.$(\".collection-name\")\n .focus()\n .select();\n }\n if (clear) {\n what = what || this.$(`.${VALIDATION_CLASS}`);\n what.removeClass(VALIDATION_CLASS);\n } else {\n what.addClass(VALIDATION_CLASS);\n }\n },\n\n _changeHideOriginals: function(ev) {\n this.hideOriginals = this.$(\".hide-originals\").prop(\"checked\");\n },\n\n // ........................................................................ footer\n /** handle a collection name change */\n _changeName: function(ev) {\n this._validationWarning(\"name\", !!this._getName());\n },\n\n /** check for enter key press when in the collection name and submit */\n _nameCheckForEnter: function(ev) {\n if (ev.keyCode === 13 && !this.blocking) {\n this._clickCreate();\n }\n },\n\n /** get the current collection name */\n _getName: function() {\n return _.escape(this.$(\".collection-name\").val());\n },\n\n // ........................................................................ header\n /** expand help */\n _clickMoreHelp: function(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").addClass(\"expanded\");\n this.$(\".more-help\").hide();\n },\n /** collapse help */\n _clickLessHelp: function(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").removeClass(\"expanded\");\n this.$(\".more-help\").show();\n },\n /** toggle help */\n _toggleHelp: function(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").toggleClass(\"expanded\");\n this.$(\".more-help\").toggle();\n },\n\n /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */\n _showAlert: function(message, alertClass) {\n alertClass = alertClass || \"alert-danger\";\n this.$(\".main-help\").hide();\n this.$(\".header .alert\")\n .attr(\"class\", \"alert alert-dismissable\")\n .addClass(alertClass)\n .show()\n .find(\".alert-message\")\n .html(message);\n },\n /** hide the alerts at the top */\n _hideAlert: function(message) {\n this.$(\".main-help\").show();\n this.$(\".header .alert\").hide();\n },\n\n _cancelCreate: function(ev) {\n if (typeof this.oncancel === \"function\") {\n this.oncancel.call(this);\n }\n },\n\n /** attempt to create the current collection */\n _clickCreate: function(ev) {\n var name = this._getName();\n if (!name) {\n this._validationWarning(\"name\");\n } else if (!this.blocking) {\n this.createList(name);\n }\n },\n\n _setUpCommonSettings: function(attributes) {\n this.hideOriginals = attributes.defaultHideSourceItems || false;\n },\n\n /** render the footer, completion controls, and cancel controls */\n _renderFooter: function(speed, callback) {\n var self = this;\n var $footer = this.$(\".footer\")\n .empty()\n .html(this.templates.footer());\n _.each(this.footerSettings, (property, selector) => {\n self.$(selector).prop(\"checked\", self[property]);\n });\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n return $footer;\n },\n\n _creatorTemplates: {\n main: _.template(\n [\n '',\n '',\n ''\n ].join(\"\")\n )\n }\n};\n\n//==============================================================================\nexport default {\n CollectionCreatorMixin: CollectionCreatorMixin\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/base-creator.js","// Alphanumeric/natural sort fn\nfunction naturalSort(a, b) {\n // setup temp-scope variables for comparison evauluation\n var re = /(-?[0-9\\.]+)/g;\n\n var x = a.toString().toLowerCase() || \"\";\n var y = b.toString().toLowerCase() || \"\";\n var nC = String.fromCharCode(0);\n var xN = x.replace(re, `${nC}$1${nC}`).split(nC);\n var yN = y.replace(re, `${nC}$1${nC}`).split(nC);\n var xD = new Date(x).getTime();\n var yD = xD ? new Date(y).getTime() : null;\n // natural sorting of dates\n if (yD) {\n if (xD < yD) {\n return -1;\n } else if (xD > yD) {\n return 1;\n }\n }\n\n // natural sorting through split numeric strings and default strings\n var oFxNcL;\n\n var oFyNcL;\n for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {\n oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];\n oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];\n if (oFxNcL < oFyNcL) {\n return -1;\n } else if (oFxNcL > oFyNcL) {\n return 1;\n }\n }\n return 0;\n}\n\nexport default naturalSort;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/natural-sort.js","import jQuery from \"jquery\";\n(\"use_strict\");\n\nvar $ = jQuery;\n//=============================================================================\n\njQuery.fn.extend({\n hoverhighlight: function $hoverhighlight(scope, color) {\n scope = scope || \"body\";\n if (!this.length) {\n return this;\n }\n\n $(this).each(function() {\n var $this = $(this);\n var targetSelector = $this.data(\"target\");\n\n if (targetSelector) {\n $this\n .mouseover(ev => {\n $(targetSelector, scope).css({\n background: color\n });\n })\n .mouseout(ev => {\n $(targetSelector).css({\n background: \"\"\n });\n });\n }\n });\n return this;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/ui/hoverhighlight.js","/** This is the run workflow tool form view. */\nimport Utils from \"utils/utils\";\nimport Deferred from \"utils/deferred\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\nimport FormData from \"mvc/form/form-data\";\nimport ToolFormBase from \"mvc/tool/tool-form-base\";\nimport Modal from \"mvc/ui/ui-modal\";\nimport Webhooks from \"mvc/webhooks\";\nimport WorkflowIcons from \"mvc/workflow/workflow-icons\";\nvar View = Backbone.View.extend({\n initialize: function(options) {\n var self = this;\n this.modal = parent.Galaxy.modal || new Modal.View();\n this.model = (options && options.model) || new Backbone.Model(options);\n this.deferred = new Deferred();\n this.setElement(\n $(\"\")\n .addClass(\"ui-form-composite\")\n .append((this.$message = $(\"\")))\n .append((this.$header = $(\"\")))\n .append((this.$steps = $(\"\")))\n );\n $(\"body\").append(this.$el);\n this._configure();\n this.render();\n $(window).resize(() => {\n self._refresh();\n });\n },\n\n /** Refresh height of scrollable div below header, handle scrolling by lazy loading steps */\n _refresh: function(step_index) {\n var margin =\n _.reduce(this.$el.children(), (memo, child) => memo + $(child).outerHeight(), 0) -\n this.$steps.height() +\n 90;\n this.$steps.css(\"height\", $(window).height() - margin);\n },\n\n /** Configures form/step options for each workflow step */\n _configure: function() {\n var self = this;\n this.forms = [];\n this.steps = [];\n this.links = [];\n this.parms = [];\n _.each(this.model.get(\"steps\"), (step, i) => {\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", `${i} : Preparing workflow step.`);\n var icon = WorkflowIcons[step.step_type];\n var title = `${parseInt(i + 1)}: ${step.step_label || step.step_name}`;\n if (step.annotation) {\n title += ` - ${step.annotation}`;\n }\n if (step.step_version) {\n title += ` (Galaxy Version ${step.step_version})`;\n }\n step = Utils.merge(\n {\n index: i,\n fixed_title: _.escape(title),\n icon: icon || \"\",\n help: null,\n citations: null,\n collapsible: true,\n collapsed: i > 0 && !self._isDataStep(step),\n sustain_version: true,\n sustain_repeats: true,\n sustain_conditionals: true,\n narrow: true,\n text_enable: \"Edit\",\n text_disable: \"Undo\",\n cls_enable: \"fa fa-edit\",\n cls_disable: \"fa fa-undo\",\n errors: step.messages,\n initial_errors: true,\n cls: \"ui-portlet-narrow\",\n hide_operations: true,\n needs_refresh: false,\n always_refresh: step.step_type != \"tool\"\n },\n step\n );\n self.steps[i] = step;\n self.links[i] = [];\n self.parms[i] = {};\n });\n\n // build linear index of step input pairs\n _.each(this.steps, (step, i) => {\n FormData.visitInputs(step.inputs, (input, name) => {\n self.parms[i][name] = input;\n });\n });\n\n // iterate through data input modules and collect linked sub steps\n _.each(this.steps, (step, i) => {\n _.each(step.output_connections, output_connection => {\n _.each(self.steps, (sub_step, j) => {\n sub_step.step_index === output_connection.input_step_index && self.links[i].push(sub_step);\n });\n });\n });\n\n // convert all connected data inputs to hidden fields with proper labels,\n // and track the linked source step\n _.each(this.steps, (step, i) => {\n _.each(self.steps, (sub_step, j) => {\n var connections_by_name = {};\n _.each(step.output_connections, connection => {\n sub_step.step_index === connection.input_step_index &&\n (connections_by_name[connection.input_name] = connection);\n });\n _.each(self.parms[j], (input, name) => {\n var connection = connections_by_name[name];\n if (connection) {\n input.type = \"hidden\";\n input.help = input.step_linked ? `${input.help}, ` : \"\";\n input.help += `Output dataset '${connection.output_name}' from step ${parseInt(i) + 1}`;\n input.step_linked = input.step_linked || [];\n input.step_linked.push(step);\n }\n });\n });\n });\n\n // identify and configure workflow parameters\n var wp_count = 0;\n this.wp_inputs = {};\n function _handleWorkflowParameter(value, callback) {\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while ((match = re.exec(String(value)))) {\n var wp_name = match[1];\n callback(\n (self.wp_inputs[wp_name] = self.wp_inputs[wp_name] || {\n label: wp_name,\n name: wp_name,\n type: \"text\",\n color: `hsl( ${++wp_count * 100}, 70%, 30% )`,\n style: \"ui-form-wp-source\",\n links: []\n })\n );\n }\n }\n _.each(this.steps, (step, i) => {\n _.each(self.parms[i], (input, name) => {\n _handleWorkflowParameter(input.value, wp_input => {\n wp_input.links.push(step);\n input.wp_linked = true;\n input.type = \"text\";\n input.backdrop = true;\n input.style = \"ui-form-wp-target\";\n });\n });\n _.each(step.post_job_actions, pja => {\n _.each(pja.action_arguments, arg => {\n _handleWorkflowParameter(arg, () => {});\n });\n });\n });\n\n // select fields are shown for dynamic fields if all putative data inputs are available,\n // or if an explicit reference is specified as data_ref and available\n _.each(this.steps, (step, i) => {\n if (step.step_type == \"tool\") {\n var data_resolved = true;\n FormData.visitInputs(step.inputs, (input, name, context) => {\n var is_runtime_value = input.value && input.value.__class__ == \"RuntimeValue\";\n var is_data_input = [\"data\", \"data_collection\"].indexOf(input.type) != -1;\n var data_ref = context[input.data_ref];\n input.step_linked && !self._isDataStep(input.step_linked) && (data_resolved = false);\n input.options &&\n ((input.options.length == 0 && !data_resolved) || input.wp_linked) &&\n (input.is_workflow = true);\n data_ref &&\n (input.is_workflow =\n (data_ref.step_linked && !self._isDataStep(data_ref.step_linked)) || input.wp_linked);\n (is_data_input || (input.value && input.value.__class__ == \"RuntimeValue\" && !input.step_linked)) &&\n (step.collapsed = false);\n is_runtime_value && (input.value = input.default_value);\n input.flavor = \"workflow\";\n if (!is_runtime_value && !is_data_input && input.type !== \"hidden\" && !input.wp_linked) {\n if (input.optional || (!Utils.isEmpty(input.value) && input.value !== \"\")) {\n input.collapsible_value = input.value;\n input.collapsible_preview = true;\n }\n }\n });\n }\n });\n },\n\n render: function() {\n var self = this;\n this.deferred.reset();\n this._renderHeader();\n this._renderMessage();\n this._renderParameters();\n this._renderHistory();\n _.each(this.steps, step => {\n self._renderStep(step);\n });\n },\n\n /** Render header */\n _renderHeader: function() {\n var self = this;\n this.execute_btn = new Ui.Button({\n icon: \"fa-check\",\n title: \"Run workflow\",\n cls: \"btn btn-primary\",\n onclick: function() {\n self._execute();\n }\n });\n this.$header\n .addClass(\"ui-form-header\")\n .empty()\n .append(\n new Ui.Label({\n title: `Workflow: ${this.model.get(\"name\")}`\n }).$el\n )\n .append(this.execute_btn.$el);\n },\n\n /** Render message */\n _renderMessage: function() {\n this.$message.empty();\n if (this.model.get(\"has_upgrade_messages\")) {\n this.$message.append(\n new Ui.Message({\n message:\n \"Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el\n );\n }\n var step_version_changes = this.model.get(\"step_version_changes\");\n if (step_version_changes && step_version_changes.length > 0) {\n this.$message.append(\n new Ui.Message({\n message:\n \"Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el\n );\n }\n },\n\n /** Render workflow parameters */\n _renderParameters: function() {\n var self = this;\n this.wp_form = null;\n if (!_.isEmpty(this.wp_inputs)) {\n this.wp_form = new Form({\n title: \"Workflow Parameters\",\n inputs: this.wp_inputs,\n cls: \"ui-portlet-narrow\",\n onchange: function() {\n _.each(self.wp_form.input_list, (input_def, i) => {\n _.each(input_def.links, step => {\n self._refreshStep(step);\n });\n });\n }\n });\n this._append(this.$steps.empty(), this.wp_form.$el);\n }\n },\n\n /** Render workflow parameters */\n _renderHistory: function() {\n this.history_form = new Form({\n cls: \"ui-portlet-narrow\",\n title: \"History Options\",\n inputs: [\n {\n type: \"conditional\",\n name: \"new_history\",\n test_param: {\n name: \"check\",\n label: \"Send results to a new history\",\n type: \"boolean\",\n value: \"false\",\n help: \"\"\n },\n cases: [\n {\n value: \"true\",\n inputs: [\n {\n name: \"name\",\n label: \"History name\",\n type: \"text\",\n value: this.model.get(\"name\")\n }\n ]\n }\n ]\n }\n ]\n });\n this._append(this.$steps, this.history_form.$el);\n },\n\n /** Render step */\n _renderStep: function(step) {\n var self = this;\n var form = null;\n this.deferred.execute(promise => {\n self.$steps.addClass(\"ui-steps\");\n if (step.step_type == \"tool\") {\n step.postchange = function(process, form) {\n var self = this;\n var current_state = {\n tool_id: step.id,\n tool_version: step.version,\n inputs: $.extend(true, {}, form.data.create())\n };\n form.wait(true);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Sending current state.\", current_state);\n Utils.request({\n type: \"POST\",\n url: `${Galaxy.root}api/tools/${step.id}/build`,\n data: current_state,\n success: function(data) {\n form.update(data);\n form.wait(false);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Received new model.\", data);\n process.resolve();\n },\n error: function(response) {\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Refresh request failed.\", response);\n process.reject();\n }\n });\n };\n form = new ToolFormBase(step);\n if (step.post_job_actions && step.post_job_actions.length) {\n form.portlet.append(\n $(\"\")\n .addClass(\"ui-form-element-disabled\")\n .append(\n $(\"\")\n .addClass(\"ui-form-title\")\n .html(\"Job Post Actions\")\n )\n .append(\n $(\"\")\n .addClass(\"ui-form-preview\")\n .html(\n _.reduce(\n step.post_job_actions,\n (memo, value) => `${memo} ${value.short_str}`,\n \"\"\n )\n )\n )\n );\n }\n } else {\n var is_simple_input = [\"data_input\", \"data_collection_input\"].indexOf(step.step_type) != -1;\n _.each(step.inputs, input => {\n input.flavor = \"module\";\n input.hide_label = is_simple_input;\n });\n form = new Form(\n Utils.merge(\n {\n title: step.fixed_title,\n onchange: function() {\n _.each(self.links[step.index], link => {\n self._refreshStep(link);\n });\n },\n inputs:\n step.inputs && step.inputs.length > 0\n ? step.inputs\n : [\n {\n type: \"hidden\",\n name: \"No options available.\",\n ignore: null\n }\n ]\n },\n step\n )\n );\n }\n self.forms[step.index] = form;\n self._append(self.$steps, form.$el);\n self._refresh();\n step.needs_refresh && self._refreshStep(step);\n form.portlet[!self.show_progress ? \"enable\" : \"disable\"]();\n self.show_progress &&\n self.execute_btn.model.set({\n wait: true,\n wait_text: \"Preparing...\",\n percentage: (step.index + 1) * 100.0 / self.steps.length\n });\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", `${step.index} : Workflow step state ready.`, step);\n setTimeout(() => {\n promise.resolve();\n }, 0);\n });\n },\n\n /** Refreshes step values from source step values */\n _refreshStep: function(step) {\n var self = this;\n var form = this.forms[step.index];\n if (form) {\n _.each(self.parms[step.index], (input, name) => {\n if (input.step_linked || input.wp_linked) {\n var field = form.field_list[form.data.match(name)];\n if (field) {\n var new_value = undefined;\n if (input.step_linked) {\n new_value = { values: [] };\n _.each(input.step_linked, source_step => {\n if (self._isDataStep(source_step)) {\n var value = self.forms[source_step.index].data.create().input;\n value &&\n _.each(value.values, v => {\n new_value.values.push(v);\n });\n }\n });\n if (!input.multiple && new_value.values.length > 0) {\n new_value = {\n values: [new_value.values[0]]\n };\n }\n } else if (input.wp_linked) {\n new_value = input.value;\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while ((match = re.exec(input.value))) {\n var wp_field = self.wp_form.field_list[self.wp_form.data.match(match[1])];\n var wp_value = wp_field && wp_field.value();\n if (wp_value) {\n new_value = new_value.split(match[0]).join(wp_value);\n }\n }\n }\n if (new_value !== undefined) {\n field.value(new_value);\n }\n }\n }\n });\n form.trigger(\"change\");\n } else {\n step.needs_refresh = true;\n }\n },\n\n /** Refresh the history after job submission while form is shown */\n _refreshHistory: function() {\n var self = this;\n var history = parent.Galaxy && parent.Galaxy.currHistoryPanel && parent.Galaxy.currHistoryPanel.model;\n this._refresh_history && clearTimeout(this._refresh_history);\n if (history) {\n history.refresh().success(() => {\n if (history.numOfUnfinishedShownContents() === 0) {\n self._refresh_history = setTimeout(() => {\n self._refreshHistory();\n }, history.UPDATE_DELAY);\n }\n });\n }\n },\n\n /** Build remaining steps */\n _execute: function() {\n var self = this;\n this.show_progress = true;\n this._enabled(false);\n this.deferred.execute(promise => {\n setTimeout(() => {\n promise.resolve();\n self._submit();\n }, 0);\n });\n },\n\n /** Validate and submit workflow */\n _submit: function() {\n var self = this;\n var history_form_data = this.history_form.data.create();\n var job_def = {\n new_history_name: history_form_data[\"new_history|name\"] ? history_form_data[\"new_history|name\"] : null,\n history_id: !history_form_data[\"new_history|name\"] ? this.model.get(\"history_id\") : null,\n replacement_params: this.wp_form ? this.wp_form.data.create() : {},\n parameters: {},\n // Tool form will submit flat maps for each parameter\n // (e.g. \"repeat_0|cond|param\": \"foo\" instead of nested\n // data structures).\n parameters_normalized: true,\n // Tool form always wants a list of invocations back\n // so that inputs can be batched.\n batch: true\n };\n var validated = true;\n for (var i in this.forms) {\n var form = this.forms[i];\n var job_inputs = form.data.create();\n var step = self.steps[i];\n var step_index = step.step_index;\n form.trigger(\"reset\");\n for (var job_input_id in job_inputs) {\n var input_value = job_inputs[job_input_id];\n var input_id = form.data.match(job_input_id);\n var input_field = form.field_list[input_id];\n var input_def = form.input_list[input_id];\n if (!input_def.step_linked) {\n if (this._isDataStep(step)) {\n validated = input_value && input_value.values && input_value.values.length > 0;\n } else {\n validated =\n input_def.optional ||\n (input_def.is_workflow && input_value !== \"\") ||\n (!input_def.is_workflow && input_value !== null);\n }\n if (!validated) {\n form.highlight(input_id);\n break;\n }\n job_def.parameters[step_index] = job_def.parameters[step_index] || {};\n job_def.parameters[step_index][job_input_id] = job_inputs[job_input_id];\n }\n }\n if (!validated) {\n break;\n }\n }\n if (!validated) {\n self._enabled(true);\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation failed.\", job_def);\n } else {\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation complete.\", job_def);\n Utils.request({\n type: \"POST\",\n url: `${Galaxy.root}api/workflows/${this.model.id}/invocations`,\n data: job_def,\n success: function(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission successful.\", response);\n self.$el.children().hide();\n self.$el.append(self._templateSuccess(response));\n\n // Show Webhook if job is running\n if ($.isArray(response) && response.length > 0) {\n self.$el.append($(\"\", { id: \"webhook-view\" }));\n var WebhookApp = new Webhooks.WebhookView({\n urlRoot: `${Galaxy.root}api/webhooks/workflow`,\n toolId: job_def.tool_id,\n toolVersion: job_def.tool_version\n });\n }\n\n self._refreshHistory();\n },\n error: function(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission failed.\", response);\n var input_found = false;\n if (response && response.err_data) {\n for (var i in self.forms) {\n var form = self.forms[i];\n var step_related_errors = response.err_data[form.model.get(\"step_index\")];\n if (step_related_errors) {\n var error_messages = form.data.matchResponse(step_related_errors);\n for (var input_id in error_messages) {\n form.highlight(input_id, error_messages[input_id]);\n input_found = true;\n break;\n }\n }\n }\n }\n if (!input_found) {\n self.modal.show({\n title: \"Workflow submission failed\",\n body: self._templateError(job_def, response && response.err_msg),\n buttons: {\n Close: function() {\n self.modal.hide();\n }\n }\n });\n }\n },\n complete: function() {\n self._enabled(true);\n }\n });\n }\n },\n\n /** Append new dom to body */\n _append: function($container, $el) {\n $container.append(\"\").append($el);\n },\n\n /** Set enabled/disabled state */\n _enabled: function(enabled) {\n this.execute_btn.model.set({\n wait: !enabled,\n wait_text: \"Sending...\",\n percentage: -1\n });\n this.wp_form && this.wp_form.portlet[enabled ? \"enable\" : \"disable\"]();\n this.history_form && this.history_form.portlet[enabled ? \"enable\" : \"disable\"]();\n _.each(this.forms, form => {\n form && form.portlet[enabled ? \"enable\" : \"disable\"]();\n });\n },\n\n /** Is data input module/step */\n _isDataStep: function(steps) {\n var lst = $.isArray(steps) ? steps : [steps];\n for (var i = 0; i < lst.length; i++) {\n var step = lst[i];\n if (!step || !step.step_type || !step.step_type.startsWith(\"data\")) {\n return false;\n }\n }\n return true;\n },\n\n /** Templates */\n _templateSuccess: function(response) {\n if ($.isArray(response) && response.length > 0) {\n return $(\"\")\n .addClass(\"donemessagelarge\")\n .append(\n $(\"\").html(\n `Successfully invoked workflow ${Utils.sanitize(this.model.get(\"name\"))}${\n response.length > 1 ? ` ${response.length} times` : \"\"\n }.`\n )\n )\n .append(\n $(\"\")\n .append(\"\")\n .text(\n \"You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.\"\n )\n );\n } else {\n return this._templateError(response, \"Invalid success response. No invocations found.\");\n }\n },\n\n _templateError: function(response, err_msg) {\n return $(\"\")\n .addClass(\"errormessagelarge\")\n .append(\n $(\"\").text(\n `The server could not complete the request. Please contact the Galaxy Team if this error persists. ${JSON.stringify(\n err_msg\n ) || \"\"}`\n )\n )\n .append($(\"\").text(JSON.stringify(response, null, 4)));\n }\n});\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/tool/tool-form-composite.js","import MODAL from \"mvc/ui/ui-modal\";\nimport ERROR_MODAL from \"mvc/ui/error-modal\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/**\n * A dialog/modal that allows copying a user history or 'importing' from user\n * another. Generally called via historyCopyDialog below.\n * @type {Object}\n */\nvar CopyDialog = {\n // language related strings/fns\n defaultName: _.template(\"Copy of '<%- name %>'\"),\n title: _.template(`${_l(\"Copying history\")} \"<%- name %>\"`),\n submitLabel: _l(\"Copy\"),\n errorMessage: _l(\"History could not be copied.\"),\n progressive: _l(\"Copying history\"),\n activeLabel: _l(\"Copy only the active, non-deleted datasets\"),\n allLabel: _l(\"Copy all datasets including deleted ones\"),\n anonWarning:\n _l(\"As an anonymous user, unless you login or register, you will lose your current history \") +\n _l(\"after copying this history. \"),\n\n // template for modal body\n _template: _.template(\n [\n //TODO: remove inline styles\n // show a warning message for losing current to anon users\n \"<% if( isAnon ){ %>\",\n '
\",\n \"<% } %>\",\n \"\"\n ].join(\"\")\n ),\n\n // empty modal body and let the user know the copy is happening\n _showAjaxIndicator: function _showAjaxIndicator() {\n var indicator = `
${this.progressive}...
`;\n this.modal\n .$(\".modal-body\")\n .empty()\n .append(indicator)\n .css({ \"margin-top\": \"8px\" });\n },\n\n // (sorta) public interface - display the modal, render the form, and potentially copy the history\n // returns a jQuery.Deferred done->history copied, fail->user cancelled\n dialog: function _dialog(modal, history, options) {\n options = options || {};\n\n var dialog = this;\n var deferred = jQuery.Deferred();\n\n var // TODO: getting a little byzantine here\n defaultCopyNameFn = options.nameFn || this.defaultName;\n\n var defaultCopyName = defaultCopyNameFn({\n name: history.get(\"name\")\n });\n\n var // TODO: these two might be simpler as one 3 state option (all,active,no-choice)\n defaultCopyWhat = options.allDatasets ? \"copy-all\" : \"copy-non-deleted\";\n\n var allowAll = !_.isUndefined(options.allowAll) ? options.allowAll : true;\n\n var autoClose = !_.isUndefined(options.autoClose) ? options.autoClose : true;\n\n this.modal = modal;\n\n // validate the name and copy if good\n function checkNameAndCopy() {\n var name = modal.$(\"#copy-modal-title\").val();\n if (!name) {\n modal.$(\".invalid-title\").show();\n return;\n }\n // get further settings, shut down and indicate the ajax call, then hide and resolve/reject\n var copyAllDatasets = modal.$('input[name=\"copy-what\"]:checked').val() === \"copy-all\";\n modal.$(\"button\").prop(\"disabled\", true);\n dialog._showAjaxIndicator();\n history\n .copy(true, name, copyAllDatasets)\n .done(response => {\n deferred.resolve(response);\n })\n .fail(function(xhr, status, message) {\n var options = {\n name: name,\n copyAllDatasets: copyAllDatasets\n };\n ERROR_MODAL.ajaxErrorModal(history, xhr, options, dialog.errorMessage);\n deferred.rejectWith(deferred, arguments);\n })\n .done(() => {\n if (autoClose) {\n modal.hide();\n }\n });\n }\n\n var originalClosingCallback = options.closing_callback;\n modal.show(\n _.extend(options, {\n title: this.title({ name: history.get(\"name\") }),\n body: $(\n dialog._template({\n name: defaultCopyName,\n isAnon: Galaxy.user.isAnonymous(),\n allowAll: allowAll,\n copyWhat: defaultCopyWhat,\n activeLabel: this.activeLabel,\n allLabel: this.allLabel,\n anonWarning: this.anonWarning\n })\n ),\n buttons: _.object([\n [\n _l(\"Cancel\"),\n () => {\n modal.hide();\n }\n ],\n [this.submitLabel, checkNameAndCopy]\n ]),\n height: \"auto\",\n closing_events: true,\n closing_callback: function _historyCopyClose(cancelled) {\n if (cancelled) {\n deferred.reject({ cancelled: true });\n }\n if (originalClosingCallback) {\n originalClosingCallback(cancelled);\n }\n }\n })\n );\n\n // set the default dataset copy, autofocus the title, and set up for a simple return\n modal\n .$(\"#copy-modal-title\")\n .focus()\n .select();\n modal.$(\"#copy-modal-title\").on(\"keydown\", ev => {\n if (ev.keyCode === 13) {\n ev.preventDefault();\n checkNameAndCopy();\n }\n });\n\n return deferred;\n }\n};\n\n//==============================================================================\n// maintain the (slight) distinction between copy and import\n/**\n * Subclass CopyDialog to use the import language.\n */\nvar ImportDialog = _.extend({}, CopyDialog, {\n defaultName: _.template(\"imported: <%- name %>\"),\n title: _.template(`${_l(\"Importing history\")} \"<%- name %>\"`),\n submitLabel: _l(\"Import\"),\n errorMessage: _l(\"History could not be imported.\"),\n progressive: _l(\"Importing history\"),\n activeLabel: _l(\"Import only the active, non-deleted datasets\"),\n allLabel: _l(\"Import all datasets including deleted ones\"),\n anonWarning:\n _l(\"As an anonymous user, unless you login or register, you will lose your current history \") +\n _l(\"after importing this history. \")\n});\n\n//==============================================================================\n/**\n * Main interface for both history import and history copy dialogs.\n * @param {Backbone.Model} history the history to copy\n * @param {Object} options a hash\n * @return {jQuery.Deferred} promise that fails on close and succeeds on copy\n *\n * options:\n * (this object is also passed to the modal used to display the dialog and accepts modal options)\n * {Function} nameFn if defined, use this to build the default name shown to the user\n * (the fn is passed: {name: })\n * {bool} useImport if true, use the 'import' language (instead of Copy)\n * {bool} allowAll if true, allow the user to choose between copying all datasets and\n * only non-deleted datasets\n * {String} allDatasets default initial checked radio button: 'copy-all' or 'copy-non-deleted',\n */\nvar historyCopyDialog = (history, options) => {\n options = options || {};\n // create our own modal if Galaxy doesn't have one (mako tab without use_panels)\n var modal = window.parent.Galaxy.modal || new MODAL.View({});\n return options.useImport\n ? ImportDialog.dialog(modal, history, options)\n : CopyDialog.dialog(modal, history, options);\n};\n\n//==============================================================================\nexport default historyCopyDialog;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/copy-dialog.js","import _l from \"utils/localization\";\n\n//TODO: toastr is another possibility - I didn't see where I might add details, tho\n\n/* ============================================================================\nError modals meant to replace the o-so-easy alerts.\n\nThese are currently styled as errormessages but use the Galaxy.modal\ninfrastructure to be shown/closed. They're capable of showing details in a\ntogglable dropdown and the details are formatted in a pre.\n\nExample:\n errorModal( 'Heres a message', 'A Title', { some_details: 'here' });\n errorModal( 'Heres a message' ); // no details, title is 'Error'\n\nThere are three specialized forms:\n offlineErrorModal a canned response for when there's no connection\n badGatewayErrorModal canned response for when Galaxy is restarting\n ajaxErrorModal plugable into any Backbone class as an\n error event handler by accepting the error args: model, xhr, options\n\nExamples:\n if( navigator.offLine ){ offlineErrorModal(); }\n if( xhr.status === 502 ){ badGatewayErrorModal(); }\n this.listenTo( this.model, 'error', ajaxErrorModal );\n\n============================================================================ */\n\nvar CONTACT_MSG = _l(\"Please contact a Galaxy administrator if the problem persists.\");\nvar DEFAULT_AJAX_ERR_MSG = _l(\"An error occurred while updating information with the server.\");\nvar DETAILS_MSG = _l(\"The following information can assist the developers in finding the source of the error:\");\n\n/** private helper that builds the modal and handles adding details */\nfunction _errorModal(message, title, details) {\n // create and return the modal, adding details button only if needed\n Galaxy.modal.show({\n title: title,\n body: message,\n closing_events: true,\n buttons: {\n Ok: function() {\n Galaxy.modal.hide();\n }\n }\n });\n Galaxy.modal.$el.addClass(\"error-modal\");\n\n if (details) {\n Galaxy.modal\n .$(\".error-details\")\n .add(Galaxy.modal.$('button:contains(\"Details\")'))\n .remove();\n $(\"\")\n .addClass(\"error-details\")\n .hide()\n .appendTo(Galaxy.modal.$(\".modal-content\"))\n .append([$(\"\").text(DETAILS_MSG), $(\"\").text(JSON.stringify(details, null, \" \"))]);\n\n $(``)\n .appendTo(Galaxy.modal.$(\".buttons\"))\n .click(() => {\n Galaxy.modal.$(\".error-details\").toggle();\n });\n }\n return Galaxy.modal;\n}\n\n/** Display a modal showing an error message but fallback to alert if there's no modal */\nfunction errorModal(message, title, details) {\n if (!message) {\n return;\n }\n\n message = _l(message);\n title = _l(title) || _l(\"Error:\");\n if (window.Galaxy && Galaxy.modal) {\n return _errorModal(message, title, details);\n }\n\n alert(`${title}\\n\\n${message}`);\n console.log(\"error details:\", JSON.stringify(details));\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal when the user may be offline */\nfunction offlineErrorModal() {\n return errorModal(_l(\"You appear to be offline. Please check your connection and try again.\"), _l(\"Offline?\"));\n}\n\n// ----------------------------------------------------------------------------\n/** 502 messages that should be displayed when galaxy is restarting */\nfunction badGatewayErrorModal() {\n return errorModal(\n `${_l(\"Galaxy is currently unreachable. Please try again in a few minutes.\")} ${CONTACT_MSG}`,\n _l(\"Cannot connect to Galaxy\")\n );\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal (with details) about a failed Backbone ajax operation */\nfunction ajaxErrorModal(model, xhr, options, message, title) {\n message = message || DEFAULT_AJAX_ERR_MSG;\n message += ` ${CONTACT_MSG}`;\n title = title || _l(\"An error occurred\");\n var details = _ajaxDetails(model, xhr, options);\n return errorModal(message, title, details);\n}\n\n/** build details which may help debugging the ajax call */\nfunction _ajaxDetails(model, xhr, options) {\n return {\n //TODO: still can't manage Raven id\n raven: _.result(window.Raven, \"lastEventId\"),\n userAgent: navigator.userAgent,\n onLine: navigator.onLine,\n version: _.result(Galaxy.config, \"version_major\"),\n xhr: _.omit(xhr, _.functions(xhr)),\n options: _.omit(options, \"xhr\"),\n // add ajax data from Galaxy object cache\n url: _.result(Galaxy.lastAjax, \"url\"),\n data: _.result(Galaxy.lastAjax, \"data\"),\n // backbone stuff (auto-redacting email for user)\n model: _.result(model, \"toJSON\", `${model}`),\n user: _.omit(_.result(Galaxy.user, \"toJSON\"), \"email\")\n };\n}\n\n//=============================================================================\nexport default {\n errorModal: errorModal,\n offlineErrorModal: offlineErrorModal,\n badGatewayErrorModal: badGatewayErrorModal,\n ajaxErrorModal: ajaxErrorModal\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/ui/error-modal.js","import * as _ from \"libs/underscore\";\nimport * as Backbone from \"libs/backbone\";\nimport BASE_MVC from \"mvc/base-mvc\";\n\n//=============================================================================\n/**\n * A Collection that can be limited/offset/re-ordered/filtered.\n * @type {Backbone.Collection}\n */\nvar ControlledFetchCollection = Backbone.Collection.extend({\n /** call setOrder on initialization to build the comparator based on options */\n initialize: function(models, options) {\n Backbone.Collection.prototype.initialize.call(this, models, options);\n this.setOrder(options.order || this.order, { silent: true });\n },\n\n /** set up to track order changes and re-sort when changed */\n _setUpListeners: function() {\n return this.on({\n \"changed-order\": this.sort\n });\n },\n\n /** override to provide order and offsets based on instance vars, set limit if passed,\n * and set allFetched/fire 'all-fetched' when xhr returns\n */\n fetch: function(options) {\n options = this._buildFetchOptions(options);\n Galaxy.debug(\"fetch options:\", options);\n return Backbone.Collection.prototype.fetch.call(this, options);\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function(options) {\n // note: we normally want options passed in to override the defaults built here\n // so most of these fns will generate defaults\n options = _.clone(options) || {};\n var self = this;\n\n // jquery ajax option; allows multiple q/qv for filters (instead of 'q[]')\n options.traditional = true;\n\n // options.data\n // we keep limit, offset, etc. in options *as well as move it into data* because:\n // - it makes fetch calling convenient to add it to a single options map (instead of as mult. args)\n // - it allows the std. event handlers (for fetch, etc.) to have access\n // to the pagination options too\n // (i.e. this.on( 'sync', function( options ){ if( options.limit ){ ... } }))\n // however, when we send to xhr/jquery we copy them to data also so that they become API query params\n options.data = options.data || self._buildFetchData(options);\n Galaxy.debug(\"data:\", options.data);\n\n // options.data.filters --> options.data.q, options.data.qv\n var filters = this._buildFetchFilters(options);\n Galaxy.debug(\"filters:\", filters);\n if (!_.isEmpty(filters)) {\n _.extend(options.data, this._fetchFiltersToAjaxData(filters));\n }\n Galaxy.debug(\"data:\", options.data);\n return options;\n },\n\n /** Build the dictionary to send to fetch's XHR as data */\n _buildFetchData: function(options) {\n var defaults = {};\n if (this.order) {\n defaults.order = this.order;\n }\n return _.defaults(_.pick(options, this._fetchParams), defaults);\n },\n\n /** These attribute keys are valid params to fetch/API-index */\n _fetchParams: [\n /** model dependent string to control the order of models returned */\n \"order\",\n /** limit the number of models returned from a fetch */\n \"limit\",\n /** skip this number of models when fetching */\n \"offset\",\n /** what series of attributes to return (model dependent) */\n \"view\",\n /** individual keys to return for the models (see api/histories.index) */\n \"keys\"\n ],\n\n /** add any needed filters here based on collection state */\n _buildFetchFilters: function(options) {\n // override\n return _.clone(options.filters || {});\n },\n\n /** Convert dictionary filters to qqv style arrays */\n _fetchFiltersToAjaxData: function(filters) {\n // return as a map so ajax.data can extend from it\n var filterMap = {\n q: [],\n qv: []\n };\n _.each(filters, (v, k) => {\n // don't send if filter value is empty\n if (v === undefined || v === \"\") {\n return;\n }\n // json to python\n if (v === true) {\n v = \"True\";\n }\n if (v === false) {\n v = \"False\";\n }\n if (v === null) {\n v = \"None\";\n }\n // map to k/v arrays (q/qv)\n filterMap.q.push(k);\n filterMap.qv.push(v);\n });\n return filterMap;\n },\n\n /** override to reset allFetched flag to false */\n reset: function(models, options) {\n this.allFetched = false;\n return Backbone.Collection.prototype.reset.call(this, models, options);\n },\n\n // ........................................................................ order\n order: null,\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: {\n update_time: BASE_MVC.buildComparator(\"update_time\", {\n ascending: false\n }),\n \"update_time-asc\": BASE_MVC.buildComparator(\"update_time\", {\n ascending: true\n }),\n create_time: BASE_MVC.buildComparator(\"create_time\", {\n ascending: false\n }),\n \"create_time-asc\": BASE_MVC.buildComparator(\"create_time\", {\n ascending: true\n })\n },\n\n /** set the order and comparator for this collection then sort with the new order\n * @event 'changed-order' passed the new order and the collection\n */\n setOrder: function(order, options) {\n options = options || {};\n var collection = this;\n var comparator = collection.comparators[order];\n if (_.isUndefined(comparator)) {\n throw new Error(`unknown order: ${order}`);\n }\n // if( _.isUndefined( comparator ) ){ return; }\n if (comparator === collection.comparator) {\n return;\n }\n\n collection.order = order;\n collection.comparator = comparator;\n\n if (!options.silent) {\n collection.trigger(\"changed-order\", options);\n }\n return collection;\n }\n});\n\n//=============================================================================\n/**\n *\n */\nvar PaginatedCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for each page's fetch */\n limitPerPage: 500,\n\n initialize: function(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n this.currentPage = options.currentPage || 0;\n },\n\n getTotalItemCount: function() {\n return this.length;\n },\n\n shouldPaginate: function() {\n return this.getTotalItemCount() >= this.limitPerPage;\n },\n\n getLastPage: function() {\n return Math.floor(this.getTotalItemCount() / this.limitPerPage);\n },\n\n getPageCount: function() {\n return this.getLastPage() + 1;\n },\n\n getPageLimitOffset: function(pageNum) {\n pageNum = this.constrainPageNum(pageNum);\n return {\n limit: this.limitPerPage,\n offset: pageNum * this.limitPerPage\n };\n },\n\n constrainPageNum: function(pageNum) {\n return Math.max(0, Math.min(pageNum, this.getLastPage()));\n },\n\n /** fetch the next page of data */\n fetchPage: function(pageNum, options) {\n var self = this;\n pageNum = self.constrainPageNum(pageNum);\n self.currentPage = pageNum;\n options = _.defaults(options || {}, self.getPageLimitOffset(pageNum));\n\n self.trigger(\"fetching-more\");\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-more-done\");\n });\n },\n\n fetchCurrentPage: function(options) {\n return this.fetchPage(this.currentPage, options);\n },\n\n fetchPrevPage: function(options) {\n return this.fetchPage(this.currentPage - 1, options);\n },\n\n fetchNextPage: function(options) {\n return this.fetchPage(this.currentPage + 1, options);\n }\n});\n\n//=============================================================================\n/**\n * A Collection that will load more elements without reseting.\n */\nvar InfinitelyScrollingCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: null,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 100,\n\n initialize: function(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n /** @type {Integer} number of contents to return from the first fetch */\n this.limitOnFirstFetch = options.limitOnFirstFetch || this.limitOnFirstFetch;\n /** @type {Integer} limit for every fetch after the first */\n this.limitPerFetch = options.limitPerFetch || this.limitPerFetch;\n /** @type {Boolean} are all contents fetched? */\n this.allFetched = false;\n /** @type {Integer} what was the offset of the last content returned */\n this.lastFetched = options.lastFetched || 0;\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function(options) {\n // options (options for backbone.fetch and jquery.ajax generally)\n // backbone option; false here to make fetching an addititive process\n options.remove = options.remove || false;\n return ControlledFetchCollection.prototype._buildFetchOptions.call(this, options);\n },\n\n /** fetch the first 'page' of data */\n fetchFirst: function(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchFirst:\", options);\n options = options ? _.clone(options) : {};\n this.allFetched = false;\n this.lastFetched = 0;\n return this.fetchMore(\n _.defaults(options, {\n reset: true,\n limit: this.limitOnFirstFetch\n })\n );\n },\n\n /** fetch the next page of data */\n fetchMore: function(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchMore:\", options);\n options = _.clone(options || {});\n var collection = this;\n\n Galaxy.debug(\"fetchMore, options.reset:\", options.reset);\n if (!options.reset && collection.allFetched) {\n return jQuery.when();\n }\n\n // TODO: this fails in the edge case where\n // the first fetch offset === limit (limit 4, offset 4, collection.length 4)\n if (options.reset) {\n options.offset = 0;\n } else if (options.offset === undefined) {\n options.offset = collection.lastFetched;\n }\n var limit = (options.limit = options.limit || collection.limitPerFetch || null);\n Galaxy.debug(\"fetchMore, limit:\", limit, \"offset:\", options.offset);\n\n collection.trigger(\"fetching-more\");\n return (\n collection\n .fetch(options)\n .always(() => {\n collection.trigger(\"fetching-more-done\");\n })\n // maintain allFetched flag and trigger if all were fetched this time\n .done(function _postFetchMore(fetchedData) {\n var numFetched = _.isArray(fetchedData) ? fetchedData.length : 0;\n collection.lastFetched += numFetched;\n Galaxy.debug(\"fetchMore, lastFetched:\", collection.lastFetched);\n // anything less than a full page means we got all there is to get\n if (!limit || numFetched < limit) {\n collection.allFetched = true;\n collection.trigger(\"all-fetched\", this);\n }\n })\n );\n },\n\n /** fetch all the collection */\n fetchAll: function(options) {\n // whitelist options to prevent allowing limit/offset/filters\n // (use vanilla fetch instead)\n options = options || {};\n var self = this;\n options = _.pick(options, \"silent\");\n options.filters = {};\n return self.fetch(options).done(() => {\n self.allFetched = true;\n self.trigger(\"all-fetched\", self);\n });\n }\n});\n\n//==============================================================================\nexport default {\n ControlledFetchCollection: ControlledFetchCollection,\n PaginatedCollection: PaginatedCollection,\n InfinitelyScrollingCollection: InfinitelyScrollingCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/base/controlled-fetch-collection.js","import DATASET from \"mvc/dataset/dataset-model\";\nimport HISTORY_CONTENT from \"mvc/history/history-content-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DATASET.DatasetAssociation;\n\nvar hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;\n/** @class (HDA) model for a Galaxy dataset contained in and related to a history.\n */\nvar HistoryDatasetAssociation = _super.extend(\n BASE_MVC.mixin(\n hcontentMixin,\n /** @lends HistoryDatasetAssociation.prototype */ {\n /** default attributes for a model */\n defaults: _.extend({}, _super.prototype.defaults, hcontentMixin.defaults, {\n history_content_type: \"dataset\",\n model_class: \"HistoryDatasetAssociation\"\n })\n }\n )\n);\n\n//==============================================================================\nexport default {\n HistoryDatasetAssociation: HistoryDatasetAssociation\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hda-model.js","import LIST_ITEM from \"mvc/list/list-item\";\nimport LoadingIndicator from \"ui/loading-indicator\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/search-input\";\n\nvar logNamespace = \"list\";\n/* ============================================================================\nTODO:\n\n============================================================================ */\n/** @class View for a list/collection of models and the sub-views of those models.\n * Sub-views must (at least have the interface if not) inherit from ListItemView.\n * (For a list panel that also includes some 'container' model (History->HistoryContents)\n * use ModelWithListPanel)\n *\n * Allows for:\n * searching collection/sub-views\n * selecting/multi-selecting sub-views\n *\n * Currently used:\n * for dataset/dataset-choice\n * as superclass of ModelListPanel\n */\nvar ListPanel = Backbone.View.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends ListPanel.prototype */ {\n _logNamespace: logNamespace,\n\n /** class to use for constructing the sub-views */\n viewClass: LIST_ITEM.ListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: Backbone.Collection,\n\n tagName: \"div\",\n className: \"list-panel\",\n\n /** (in ms) that jquery effects will use */\n fxSpeed: \"fast\",\n\n /** string to display when the collection has no contents */\n emptyMsg: _l(\"This list is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: _l(\"No matching items found\"),\n /** string used for search placeholder */\n searchPlaceholder: _l(\"search\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the list\n */\n initialize: function(attributes, options) {\n attributes = attributes || {};\n // set the logger if requested\n if (attributes.logger) {\n this.logger = attributes.logger;\n }\n this.log(`${this}.initialize:`, attributes);\n\n // ---- instance vars\n /** how quickly should jquery fx run? */\n this.fxSpeed = _.has(attributes, \"fxSpeed\") ? attributes.fxSpeed : this.fxSpeed;\n\n /** filters for displaying subviews */\n this.filters = [];\n /** current search terms */\n this.searchFor = attributes.searchFor || \"\";\n\n /** loading indicator */\n // this.indicator = new LoadingIndicator( this.$el );\n\n /** currently showing selectors on items? */\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : true;\n //this.selecting = false;\n\n /** cached selected item.model.ids to persist btwn renders */\n this.selected = attributes.selected || [];\n /** the last selected item.model.id */\n this.lastSelected = null;\n\n /** are sub-views draggable */\n this.dragItems = attributes.dragItems || false;\n\n /** list item view class (when passed models) */\n this.viewClass = attributes.viewClass || this.viewClass;\n\n /** list item views */\n this.views = [];\n /** list item models */\n this.collection = attributes.collection || this._createDefaultCollection();\n\n /** filter fns run over collection items to see if they should show in the list */\n this.filters = attributes.filters || [];\n\n /** override $scrollContainer fn via attributes - fn should return jq for elem to call scrollTo on */\n this.$scrollContainer = attributes.$scrollContainer || this.$scrollContainer;\n\n /** @type {String} generic title */\n this.title = attributes.title || \"\";\n /** @type {String} generic subtitle */\n this.subtitle = attributes.subtitle || \"\";\n\n this._setUpListeners();\n },\n\n // ------------------------------------------------------------------------ listeners\n /** create any event listeners for the list */\n _setUpListeners: function() {\n this.off();\n\n //TODO: move errorHandler down into list-view from history-view or\n // pass to global error handler (Galaxy)\n this.on({\n error: function(model, xhr, options, msg, details) {\n //this.errorHandler( model, xhr, options, msg, details );\n console.error(model, xhr, options, msg, details);\n },\n // show hide the loading indicator\n loading: function() {\n this._showLoadingIndicator(\"loading...\", 40);\n },\n \"loading-done\": function() {\n this._hideLoadingIndicator(40);\n }\n });\n\n // throw the first render up as a diff namespace using once (for outside consumption)\n this.once(\"rendered\", function() {\n this.trigger(\"rendered:initial\", this);\n });\n\n this._setUpCollectionListeners();\n this._setUpViewListeners();\n return this;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function() {\n // override\n return new this.collectionClass([]);\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function() {\n this.log(`${this}._setUpCollectionListeners`, this.collection);\n this.stopListening(this.collection);\n\n // bubble up error events\n this.listenTo(this.collection, {\n error: function(model, xhr, options, msg, details) {\n this.trigger(\"error\", model, xhr, options, msg, details);\n },\n update: function(collection, options) {\n var changes = options.changes;\n // console.info( collection + ', update:', changes, '\\noptions:', options );\n // more than one: render everything\n if (options.renderAll || changes.added.length + changes.removed.length > 1) {\n return this.renderItems();\n }\n // otherwise, let the single add/remove handlers do it\n if (changes.added.length === 1) {\n return this.addItemView(_.first(changes.added), collection, options);\n }\n if (changes.removed.length === 1) {\n return this.removeItemView(_.first(changes.removed), collection, options);\n }\n }\n });\n return this;\n },\n\n /** listening for sub-view events that bubble up with the 'view:' prefix */\n _setUpViewListeners: function() {\n this.log(`${this}._setUpViewListeners`);\n\n // shift to select a range\n this.on({\n \"view:selected\": function(view, ev) {\n if (ev && ev.shiftKey && this.lastSelected) {\n var lastSelectedView = this.viewFromModelId(this.lastSelected);\n if (lastSelectedView) {\n this.selectRange(view, lastSelectedView);\n }\n } else if (ev && ev.altKey && !this.selecting) {\n this.showSelectors();\n }\n this.selected.push(view.model.id);\n this.lastSelected = view.model.id;\n },\n\n \"view:de-selected\": function(view, ev) {\n this.selected = _.without(this.selected, view.model.id);\n }\n });\n },\n\n // ------------------------------------------------------------------------ rendering\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function(speed) {\n this.log(`${this}.render`, speed);\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _buildNewRender: function() {\n this.debug(`${this}(ListPanel)._buildNewRender`);\n var $newRender = $(this.templates.el({}, this));\n this._renderControls($newRender);\n this._renderTitle($newRender);\n this._renderSubtitle($newRender);\n this._renderSearch($newRender);\n this.renderItems($newRender);\n return $newRender;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _renderControls: function($newRender) {\n this.debug(`${this}(ListPanel)._renderControls`);\n var $controls = $(this.templates.controls({}, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n /** return a jQuery object containing the title DOM */\n _renderTitle: function($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** return a jQuery object containing the subtitle DOM (if any) */\n _renderSubtitle: function($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n $(panel).queue(\"fx\", [\n next => {\n panel.$el.fadeOut(speed, next);\n },\n next => {\n panel._swapNewRender($newRender);\n next();\n },\n next => {\n panel.$el.fadeIn(speed, next);\n },\n next => {\n panel.trigger(\"rendered\", panel);\n next();\n }\n ]);\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function($newRender) {\n this.$el\n .empty()\n .attr(\"class\", this.className)\n .append($newRender.children());\n if (this.selecting) {\n this.showSelectors(0);\n }\n return this;\n },\n\n /** Set up any behaviors, handlers (ep. plugins) that need to be called when the entire view has been built but\n * not attached to the page yet.\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n this.$controls($where)\n .find(\"[title]\")\n .tooltip();\n // set up the pupup for actions available when multi selecting\n this._renderMultiselectActionMenu($where);\n return this;\n },\n\n /** render a menu containing the actions available to sets of selected items */\n _renderMultiselectActionMenu: function($where) {\n $where = $where || this.$el;\n var $menu = $where.find(\".list-action-menu\");\n var actions = this.multiselectActions();\n if (!actions.length) {\n return $menu.empty();\n }\n\n var $newMenu = $(\n [\n '
',\n '\",\n '
',\n \"
\",\n \"
\"\n ].join(\"\")\n );\n var $actions = actions.map(action => {\n var html = ['
\"].join(\"\");\n return $(html).click(ev => {\n ev.preventDefault();\n return action.func(ev);\n });\n });\n $newMenu.find(\"ul\").append($actions);\n $menu.replaceWith($newMenu);\n return $newMenu;\n },\n\n /** return a list of plain objects used to render multiselect actions menu. Each object should have:\n * html: an html string used as the anchor contents\n * func: a function called when the anchor is clicked (passed the click event)\n */\n multiselectActions: function() {\n return [];\n },\n\n // ------------------------------------------------------------------------ sub-$element shortcuts\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function($where) {\n // override or set via attributes.$scrollContainer\n return ($where || this.$el).parent().parent();\n },\n /** convenience selector for the section that displays the list controls */\n $controls: function($where) {\n return ($where || this.$el).find(\"> .controls\");\n },\n /** list-items: where the subviews are contained in the view's dom */\n $list: function($where) {\n return ($where || this.$el).find(\"> .list-items\");\n },\n /** container where list messages are attached */\n $messages: function($where) {\n //TODO: controls isn't really correct here (only for ModelListPanel)\n return ($where || this.$el).find(\"> .controls .messages\");\n },\n /** the message displayed when no views can be shown (no views, none matching search) */\n $emptyMessage: function($where) {\n return ($where || this.$el).find(\"> .empty-message\");\n },\n\n // ------------------------------------------------------------------------ hda sub-views\n /** render the subviews for the list's collection */\n renderItems: function($whereTo) {\n $whereTo = $whereTo || this.$el;\n var panel = this;\n panel.log(`${this}.renderItems`, $whereTo);\n\n var $list = panel.$list($whereTo);\n panel.freeViews();\n // console.log( 'views freed' );\n //TODO:? cache and re-use views?\n var shownModels = panel._filterCollection();\n // console.log( 'models filtered:', shownModels );\n\n panel.views = shownModels.map(itemModel => {\n var view = panel._createItemView(itemModel);\n return view;\n });\n\n $list.empty();\n // console.log( 'list emptied' );\n if (panel.views.length) {\n panel._attachItems($whereTo);\n // console.log( 'items attached' );\n }\n panel._renderEmptyMessage($whereTo).toggle(!panel.views.length);\n panel.trigger(\"views:ready\", panel.views);\n\n // console.log( '------------------------------------------- rendering items' );\n return panel.views;\n },\n\n /** Filter the collection to only those models that should be currently viewed */\n _filterCollection: function() {\n // override this\n var panel = this;\n return panel.collection.filter(_.bind(panel._filterItem, panel));\n },\n\n /** Should the model be viewable in the current state?\n * Checks against this.filters and this.searchFor\n */\n _filterItem: function(model) {\n // override this\n var panel = this;\n return (\n _.every(panel.filters.map(fn => fn.call(model))) &&\n (!panel.searchFor || model.matchesAll(panel.searchFor))\n );\n },\n\n /** Create a view for a model and set up it's listeners */\n _createItemView: function(model) {\n var ViewClass = this._getItemViewClass(model);\n var options = _.extend(this._getItemViewOptions(model), {\n model: model\n });\n var view = new ViewClass(options);\n this._setUpItemViewListeners(view);\n return view;\n },\n\n /** Free a view for a model. Note: does not remove it from the DOM */\n _destroyItemView: function(view) {\n this.stopListening(view);\n this.views = _.without(this.views, view);\n },\n\n _destroyItemViews: function(view) {\n var self = this;\n self.views.forEach(v => {\n self.stopListening(v);\n });\n self.views = [];\n return self;\n },\n\n /** free any sub-views the list has */\n freeViews: function() {\n return this._destroyItemViews();\n },\n\n /** Get the bbone view class based on the model */\n _getItemViewClass: function(model) {\n // override this\n return this.viewClass;\n },\n\n /** Get the options passed to the new view based on the model */\n _getItemViewOptions: function(model) {\n // override this\n return {\n //logger : this.logger,\n fxSpeed: this.fxSpeed,\n expanded: false,\n selectable: this.selecting,\n selected: _.contains(this.selected, model.id),\n draggable: this.dragItems\n };\n },\n\n /** Set up listeners for new models */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n // send all events to the panel, re-namspaceing them with the view prefix\n this.listenTo(view, \"all\", function() {\n var args = Array.prototype.slice.call(arguments, 0);\n args[0] = `view:${args[0]}`;\n panel.trigger.apply(panel, args);\n });\n\n // drag multiple - hijack ev.setData to add all selected items\n this.listenTo(\n view,\n \"draggable:dragstart\",\n function(ev, v) {\n //TODO: set multiple drag data here\n var json = {};\n\n var selected = this.getSelectedModels();\n if (selected.length) {\n json = selected.toJSON();\n } else {\n json = [v.model.toJSON()];\n }\n ev.dataTransfer.setData(\"text\", JSON.stringify(json));\n //ev.dataTransfer.setDragImage( v.el, 60, 60 );\n },\n this\n );\n\n return panel;\n },\n\n /** Attach views in this.views to the model based on $whereTo */\n _attachItems: function($whereTo) {\n var self = this;\n // console.log( '_attachItems:', $whereTo, this.$list( $whereTo ) );\n //ASSUMES: $list has been emptied\n this.$list($whereTo).append(this.views.map(view => self._renderItemView$el(view)));\n return this;\n },\n\n /** get a given subview's $el (or whatever may wrap it) and return it */\n _renderItemView$el: function(view) {\n // useful to wrap and override\n return view.render(0).$el;\n },\n\n /** render the empty/none-found message */\n _renderEmptyMessage: function($whereTo) {\n this.debug(\"_renderEmptyMessage\", $whereTo, this.searchFor);\n var text = this.searchFor ? this.noneFoundMsg : this.emptyMsg;\n return this.$emptyMessage($whereTo).text(text);\n },\n\n /** expand all item views */\n expandAll: function() {\n _.each(this.views, view => {\n view.expand();\n });\n },\n\n /** collapse all item views */\n collapseAll: function() {\n _.each(this.views, view => {\n view.collapse();\n });\n },\n\n // ------------------------------------------------------------------------ collection/views syncing\n /** Add a view (if the model should be viewable) to the panel */\n addItemView: function(model, collection, options) {\n // console.log( this + '.addItemView:', model );\n var panel = this;\n // get the index of the model in the list of filtered models shown by this list\n // in order to insert the view in the proper place\n //TODO:? potentially expensive\n var modelIndex = panel._filterCollection().indexOf(model);\n if (modelIndex === -1) {\n return undefined;\n }\n var view = panel._createItemView(model);\n // console.log( 'adding and rendering:', modelIndex, view.toString() );\n\n $(view).queue(\"fx\", [\n next => {\n // hide the empty message first if only view\n if (panel.$emptyMessage().is(\":visible\")) {\n panel.$emptyMessage().fadeOut(panel.fxSpeed, next);\n } else {\n next();\n }\n },\n next => {\n panel._attachView(view, modelIndex);\n next();\n }\n ]);\n return view;\n },\n\n /** internal fn to add view (to both panel.views and panel.$list) */\n _attachView: function(view, modelIndex, useFx) {\n // console.log( this + '._attachView:', view, modelIndex, useFx );\n useFx = _.isUndefined(useFx) ? true : useFx;\n modelIndex = modelIndex || 0;\n var panel = this;\n\n // use the modelIndex to splice into views and insert at the proper index in the DOM\n panel.views.splice(modelIndex, 0, view);\n panel._insertIntoListAt(modelIndex, panel._renderItemView$el(view).hide());\n\n panel.trigger(\"view:attached\", view);\n if (useFx) {\n view.$el.slideDown(panel.fxSpeed, () => {\n panel.trigger(\"view:attached:rendered\");\n });\n } else {\n view.$el.show();\n panel.trigger(\"view:attached:rendered\");\n }\n return view;\n },\n\n /** insert a jq object as a child of list-items at the specified *DOM index* */\n _insertIntoListAt: function(index, $what) {\n // console.log( this + '._insertIntoListAt:', index, $what );\n var $list = this.$list();\n if (index === 0) {\n $list.prepend($what);\n } else {\n $list\n .children()\n .eq(index - 1)\n .after($what);\n }\n return $what;\n },\n\n /** Remove a view from the panel (if found) */\n removeItemView: function(model, collection, options) {\n var panel = this;\n var view = _.find(panel.views, v => v.model === model);\n if (!view) {\n return undefined;\n }\n panel.views = _.without(panel.views, view);\n panel.trigger(\"view:removed\", view);\n\n // potentially show the empty message if no views left\n // use anonymous queue here - since remove can happen multiple times\n $({}).queue(\"fx\", [\n next => {\n view.$el.fadeOut(panel.fxSpeed, next);\n },\n next => {\n view.remove();\n panel.trigger(\"view:removed:rendered\");\n if (!panel.views.length) {\n panel._renderEmptyMessage().fadeIn(panel.fxSpeed, next);\n } else {\n next();\n }\n }\n ]);\n return view;\n },\n\n /** get views based on model.id */\n viewFromModelId: function(id) {\n return _.find(this.views, v => v.model.id === id);\n },\n\n /** get views based on model */\n viewFromModel: function(model) {\n return model ? this.viewFromModelId(model.id) : undefined;\n },\n\n /** get views based on model properties */\n viewsWhereModel: function(properties) {\n return this.views.filter(view => _.isMatch(view.model.attributes, properties));\n },\n\n /** A range of views between (and including) viewA and viewB */\n viewRange: function(viewA, viewB) {\n if (viewA === viewB) {\n return viewA ? [viewA] : [];\n }\n\n var indexA = this.views.indexOf(viewA);\n var indexB = this.views.indexOf(viewB);\n\n // handle not found\n if (indexA === -1 || indexB === -1) {\n if (indexA === indexB) {\n return [];\n }\n return indexA === -1 ? [viewB] : [viewA];\n }\n // reverse if indeces are\n //note: end inclusive\n return indexA < indexB ? this.views.slice(indexA, indexB + 1) : this.views.slice(indexB, indexA + 1);\n },\n\n // ------------------------------------------------------------------------ searching\n /** render a search input for filtering datasets shown\n * (see SearchableMixin in base-mvc for implementation of the actual searching)\n * return will start the search\n * esc will clear the search\n * clicking the clear button will clear the search\n * uses searchInput in ui.js\n */\n _renderSearch: function($where) {\n $where.find(\".controls .search-input\").searchInput({\n placeholder: this.searchPlaceholder,\n initialVal: this.searchFor,\n onfirstsearch: _.bind(this._firstSearch, this),\n onsearch: _.bind(this.searchItems, this),\n onclear: _.bind(this.clearSearch, this)\n });\n return $where;\n },\n\n /** What to do on the first search entered */\n _firstSearch: function(searchFor) {\n // override to load model details if necc.\n this.log(\"onFirstSearch\", searchFor);\n return this.searchItems(searchFor);\n },\n\n /** filter view list to those that contain the searchFor terms */\n searchItems: function(searchFor, force) {\n this.log(\"searchItems\", searchFor, this.searchFor, force);\n if (!force && this.searchFor === searchFor) {\n return this;\n }\n this.searchFor = searchFor;\n this.renderItems();\n this.trigger(\"search:searching\", searchFor, this);\n var $search = this.$(\"> .controls .search-query\");\n if ($search.val() !== searchFor) {\n $search.val(searchFor);\n }\n return this;\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function(searchFor) {\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n this.renderItems();\n return this;\n },\n\n // ------------------------------------------------------------------------ selection\n /** @type Integer when the number of list item views is >= to this, don't animate selectors */\n THROTTLE_SELECTOR_FX_AT: 20,\n\n /** show selectors on all visible itemViews and associated controls */\n showSelectors: function(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = true;\n this.$(\".list-actions\").slideDown(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, view => {\n view.showSelector(speed);\n });\n //this.selected = [];\n //this.lastSelected = null;\n },\n\n /** hide selectors on all visible itemViews and associated controls */\n hideSelectors: function(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = false;\n this.$(\".list-actions\").slideUp(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, view => {\n view.hideSelector(speed);\n });\n this.selected = [];\n this.lastSelected = null;\n },\n\n /** show or hide selectors on all visible itemViews and associated controls */\n toggleSelectors: function() {\n if (!this.selecting) {\n this.showSelectors();\n } else {\n this.hideSelectors();\n }\n },\n\n /** select all visible items */\n selectAll: function(event) {\n _.each(this.views, view => {\n view.select(event);\n });\n },\n\n /** deselect all visible items */\n deselectAll: function(event) {\n this.lastSelected = null;\n _.each(this.views, view => {\n view.deselect(event);\n });\n },\n\n /** select a range of datasets between A and B */\n selectRange: function(viewA, viewB) {\n var range = this.viewRange(viewA, viewB);\n _.each(range, view => {\n view.select();\n });\n return range;\n },\n\n /** return an array of all currently selected itemViews */\n getSelectedViews: function() {\n return _.filter(this.views, v => v.selected);\n },\n\n /** return a collection of the models of all currenly selected items */\n getSelectedModels: function() {\n // console.log( '(getSelectedModels)' );\n return new this.collection.constructor(_.map(this.getSelectedViews(), view => view.model));\n },\n\n // ------------------------------------------------------------------------ loading indicator\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function(msg, speed, callback) {\n this.debug(\"_showLoadingIndicator\", this.indicator, msg, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (!this.indicator) {\n this.indicator = new LoadingIndicator(this.$el);\n this.debug(\"\\t created\", this.indicator);\n }\n if (!this.$el.is(\":visible\")) {\n this.indicator.show(0, callback);\n } else {\n this.$el.fadeOut(speed);\n this.indicator.show(msg, speed, callback);\n }\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function(speed, callback) {\n this.debug(\"_hideLoadingIndicator\", this.indicator, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (this.indicator) {\n this.indicator.hide(speed, callback);\n }\n },\n\n // ------------------------------------------------------------------------ scrolling\n /** get the current scroll position of the panel in its parent */\n scrollPosition: function() {\n return this.$scrollContainer().scrollTop();\n },\n\n /** set the current scroll position of the panel in its parent */\n scrollTo: function(pos, speed) {\n speed = speed || 0;\n this.$scrollContainer().animate({ scrollTop: pos }, speed);\n return this;\n },\n\n /** Scrolls the panel to the top. */\n scrollToTop: function(speed) {\n return this.scrollTo(0, speed);\n },\n\n /** scroll to the given view in list-items */\n scrollToItem: function(view, speed) {\n if (!view) {\n return this;\n }\n return this;\n },\n\n /** Scrolls the panel to show the content with the given id. */\n scrollToId: function(id, speed) {\n return this.scrollToItem(this.viewFromModelId(id), speed);\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .select-all\": \"selectAll\",\n \"click .deselect-all\": \"deselectAll\"\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function() {\n return `ListPanel(${this.collection})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListPanel.prototype.templates = (() => {\n var elTemplate = BASE_MVC.wrapTemplate([\n // temp container\n \"
\",\n '',\n '',\n '',\n \"
\"\n ]);\n\n var controlsTemplate = BASE_MVC.wrapTemplate([\n '
\"\n ]);\n\n return {\n el: elTemplate,\n controls: controlsTemplate\n };\n})();\n\n//=============================================================================\n/** View for a model that has a sub-collection (e.g. History, DatasetCollection)\n * Allows:\n * the model to be reset\n * auto assign panel.collection to panel.model[ panel.modelCollectionKey ]\n *\n */\nvar ModelListPanel = ListPanel.extend({\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n initialize: function(attributes) {\n ListPanel.prototype.initialize.call(this, attributes);\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : false;\n\n this.setModel(this.model, attributes);\n },\n\n /** release/free/shutdown old models and set up panel for new models\n * @fires new-model with the panel as parameter\n */\n setModel: function(model, attributes) {\n attributes = attributes || {};\n this.debug(`${this}.setModel:`, model, attributes);\n\n this.freeModel();\n this.freeViews();\n\n if (model) {\n var oldModelId = this.model ? this.model.get(\"id\") : null;\n\n // set up the new model with user, logger, storage, events\n this.model = model;\n if (this.logger) {\n this.model.logger = this.logger;\n }\n this._setUpModelListeners();\n\n //TODO: relation btwn model, collection becoming tangled here\n // free the collection, and assign the new collection to either\n // the model[ modelCollectionKey ], attributes.collection, or an empty vanilla collection\n this.stopListening(this.collection);\n this.collection =\n this.model[this.modelCollectionKey] || attributes.collection || this._createDefaultCollection();\n this._setUpCollectionListeners();\n\n if (oldModelId && model.get(\"id\") !== oldModelId) {\n this.trigger(\"new-model\", this);\n }\n }\n return this;\n },\n\n /** free the current model and all listeners for it, free any views for the model */\n freeModel: function() {\n // stop/release the previous model, and clear cache to sub-views\n if (this.model) {\n this.stopListening(this.model);\n //TODO: see base-mvc\n //this.model.free();\n //this.model = null;\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ listening\n /** listening for model events */\n _setUpModelListeners: function() {\n // override\n this.log(`${this}._setUpModelListeners`, this.model);\n // bounce model errors up to the panel\n this.listenTo(\n this.model,\n \"error\",\n function() {\n var args = Array.prototype.slice.call(arguments, 0);\n //args.unshift( 'model:error' );\n args.unshift(\"error\");\n this.trigger.apply(this, args);\n },\n this\n );\n\n // debugging\n if (this.logger) {\n this.listenTo(this.model, \"all\", function(event) {\n this.info(`${this}(model)`, event, arguments);\n });\n }\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n */\n _renderControls: function($newRender) {\n this.debug(`${this}(ModelListPanel)._renderControls`);\n var json = this.model ? this.model.toJSON() : {};\n var $controls = $(this.templates.controls(json, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function() {\n return `ModelListPanel(${this.model})`;\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nModelListPanel.prototype.templates = (() => {\n var controlsTemplate = BASE_MVC.wrapTemplate([\n '
',\n '
',\n //TODO: this is really the only difference - consider factoring titlebar out\n '
<%- model.name %>
',\n \"
\",\n '
<%- view.subtitle %>
',\n '',\n '',\n\n '
',\n '',\n \"
\",\n\n '
',\n '
',\n '\",\n '\",\n \"
\",\n '
',\n \"
\",\n \"
\",\n \"
\"\n ]);\n\n return _.extend(_.clone(ListPanel.prototype.templates), {\n controls: controlsTemplate\n });\n})();\n\n//=============================================================================\nexport default {\n ListPanel: ListPanel,\n ModelListPanel: ModelListPanel\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/list/list-view.js","import jQuery from \"jquery\";\n(\"use_strict\");\n\nvar $ = jQuery;\nvar _l = window._l || (s => s);\n\n//TODO: consolidate with tool menu functionality, use there\n\n/** searchInput: (jQuery plugin)\n * Creates a search input, a clear button, and loading indicator\n * within the selected node.\n *\n * When the user either presses return or enters some minimal number\n * of characters, a callback is called. Pressing ESC when the input\n * is focused will clear the input and call a separate callback.\n */\nfunction searchInput(parentNode, options) {\n var KEYCODE_ESC = 27;\n var KEYCODE_RETURN = 13;\n var $parentNode = $(parentNode);\n var firstSearch = true;\n\n var defaults = {\n initialVal: \"\",\n name: \"search\",\n placeholder: \"search\",\n classes: \"\",\n onclear: function() {},\n onfirstsearch: null,\n onsearch: function(inputVal) {},\n minSearchLen: 0,\n escWillClear: true,\n oninit: function() {}\n };\n\n // .................................................................... input rendering and events\n // visually clear the search, trigger an event, and call the callback\n function clearSearchInput(event) {\n var $input = $(this)\n .parent()\n .children(\"input\");\n $input\n .val(\"\")\n .trigger(\"searchInput.clear\")\n .blur();\n options.onclear();\n }\n\n // search for searchTerms, trigger an event, call the appropo callback (based on whether this is the first)\n function search(event, searchTerms) {\n if (!searchTerms) {\n return clearSearchInput();\n }\n $(this).trigger(\"search.search\", searchTerms);\n if (typeof options.onfirstsearch === \"function\" && firstSearch) {\n firstSearch = false;\n options.onfirstsearch(searchTerms);\n } else {\n options.onsearch(searchTerms);\n }\n }\n\n // .................................................................... input rendering and events\n function inputTemplate() {\n // class search-query is bootstrap 2.3 style that now lives in base.less\n return [\n '\"\n ].join(\"\");\n }\n\n // the search input that responds to keyboard events and displays the search value\n function $input() {\n return (\n $(inputTemplate())\n // select all text on a focus\n .focus(function(event) {\n $(this).select();\n })\n // attach behaviors to esc, return if desired, search on some min len string\n .keyup(function(event) {\n event.preventDefault();\n event.stopPropagation();\n\n // esc key will clear if desired\n if (event.which === KEYCODE_ESC && options.escWillClear) {\n clearSearchInput.call(this, event);\n } else {\n var searchTerms = $(this).val();\n // return key or the search string len > minSearchLen (if not 0) triggers search\n if (\n event.which === KEYCODE_RETURN ||\n (options.minSearchLen && searchTerms.length >= options.minSearchLen)\n ) {\n search.call(this, event, searchTerms);\n }\n }\n })\n .val(options.initialVal)\n );\n }\n\n // .................................................................... clear button rendering and events\n // a button for clearing the search bar, placed on the right hand side\n function $clearBtn() {\n return $(\n [''].join(\n \"\"\n )\n )\n .tooltip({ placement: \"bottom\" })\n .click(function(event) {\n clearSearchInput.call(this, event);\n });\n }\n\n // .................................................................... loadingIndicator rendering\n // a button for clearing the search bar, placed on the right hand side\n function $loadingIndicator() {\n return $(\n [''].join(\"\")\n )\n .hide()\n .tooltip({ placement: \"bottom\" });\n }\n\n // .................................................................... commands\n // visually swap the load, clear buttons\n function toggleLoadingIndicator() {\n $parentNode.find(\".search-loading\").toggle();\n $parentNode.find(\".search-clear\").toggle();\n }\n\n // .................................................................... init\n // string command (not constructor)\n if (jQuery.type(options) === \"string\") {\n if (options === \"toggle-loading\") {\n toggleLoadingIndicator();\n }\n return $parentNode;\n }\n\n // initial render\n if (jQuery.type(options) === \"object\") {\n options = jQuery.extend(true, {}, defaults, options);\n }\n //NOTE: prepended\n return $parentNode.addClass(\"search-input\").prepend([$input(), $clearBtn(), $loadingIndicator()]);\n}\n\n// as jq plugin\njQuery.fn.extend({\n searchInput: function $searchInput(options) {\n return this.each(function() {\n return searchInput(this, options);\n });\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/ui/search-input.js","import DATASET_LI from \"mvc/dataset/dataset-li\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DATASET_LI.DatasetListItemView;\n/** @class Read only view for HistoryDatasetAssociation.\n * Since there are no controls on the HDAView to hide the dataset,\n * the primary thing this class does (currently) is override templates\n * to render the HID.\n */\nvar HDAListItemView = _super.extend(\n /** @lends HDAListItemView.prototype */ {\n className: `${_super.prototype.className} history-content`,\n\n initialize: function(attributes, options) {\n _super.prototype.initialize.call(this, attributes, options);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDAListItemView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nHDAListItemView.prototype.templates = (() => {\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n // adding the hid display to the title\n '
',\n '',\n '
',\n //TODO: remove whitespace and use margin-right\n '<%- dataset.hid %> ',\n '<%- dataset.name %>',\n \"
\"\n ],\n \"dataset\"\n );\n\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: BASE_MVC.wrapTemplate(\n [\n // add a warning when hidden\n \"<% if( !dataset.visible ){ %>\",\n '
',\n _l(\"This dataset has been hidden\"),\n \"
\",\n \"<% } %>\"\n ],\n \"dataset\"\n )\n });\n\n return _.extend({}, _super.prototype.templates, {\n titleBar: titleBarTemplate,\n warnings: warnings\n });\n})();\n\n//==============================================================================\nexport default {\n HDAListItemView: HDAListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hda-li.js","import STATES from \"mvc/dataset/states\";\nimport DC_LI from \"mvc/collection/collection-li\";\nimport DC_VIEW from \"mvc/collection/collection-view\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DC_LI.DCListItemView;\n/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).\n */\nvar HDCAListItemView = _super.extend(\n /** @lends HDCAListItemView.prototype */ {\n className: `${_super.prototype.className} history-content`,\n\n /** event listeners */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n this.listenTo(this.model, {\n \"change:tags change:populated change:visible\": function(model, options) {\n this.render();\n }\n });\n },\n\n /** Override to provide the proper collections panels as the foldout */\n _getFoldoutPanelClass: function() {\n switch (this.model.get(\"collection_type\")) {\n case \"list\":\n return DC_VIEW.ListCollectionView;\n case \"paired\":\n return DC_VIEW.PairCollectionView;\n case \"list:paired\":\n return DC_VIEW.ListOfPairsCollectionView;\n case \"list:list\":\n return DC_VIEW.ListOfListsCollectionView;\n }\n throw new TypeError(`Uknown collection_type: ${this.model.get(\"collection_type\")}`);\n },\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n //TODO: model currently has no state\n var state = !this.model.get(\"populated\") ? STATES.RUNNING : STATES.OK;\n //if( this.model.has( 'state' ) ){\n this.$el.addClass(`state-${state}`);\n //}\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDCAListItemView(${modelString})`;\n }\n }\n);\n\n/** underscore templates */\nHDCAListItemView.prototype.templates = (() => {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: BASE_MVC.wrapTemplate(\n [\n // add a warning when hidden\n \"<% if( !collection.visible ){ %>\",\n '
',\n _l(\"This collection has been hidden\"),\n \"
\",\n \"<% } %>\"\n ],\n \"collection\"\n )\n });\n\n // could steal this from hda-base (or use mixed content)\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n // adding the hid display to the title\n '
',\n '',\n '
',\n //TODO: remove whitespace and use margin-right\n '<%- collection.hid %> ',\n '<%- collection.name %>',\n \"
\"\n ],\n \"collection\"\n );\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n HDCAListItemView: HDCAListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hdca-li.js","import LIST_VIEW from \"mvc/list/list-view\";\nimport DC_MODEL from \"mvc/collection/collection-model\";\nimport DC_LI from \"mvc/collection/collection-li\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"collections\";\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a dataset collection.\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar CollectionView = _super.extend(\n /** @lends CollectionView.prototype */ {\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n _logNamespace: logNamespace,\n\n className: `${_super.prototype.className} dataset-collection-panel`,\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"elements\",\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n this.hasUser = attributes.hasUser;\n /** A stack of panels that currently cover or hide this panel */\n this.panelStack = [];\n /** The text of the link to go back to the panel containing this one */\n this.parentName = attributes.parentName;\n /** foldout or drilldown */\n this.foldoutStyle = attributes.foldoutStyle || \"foldout\";\n this.downloadUrl = `${Galaxy.root}api/dataset_collections/${this.model.attributes.id}/download`;\n console.log(this);\n },\n\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n // TODO: jquery@1.12 doesn't change display when the elem has display: flex\n // this causes display: block for those elems after the use of show/hide animations\n // animations are removed from this view for now until fixed\n panel._swapNewRender($newRender);\n panel.trigger(\"rendered\", panel);\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, use model.getVisibleContents */\n _filterCollection: function() {\n //TODO: should *not* be model.getVisibleContents - visibility is not model related\n return this.model.getVisibleContents();\n },\n\n /** override to return proper view class based on element_type */\n _getItemViewClass: function(model) {\n //this.debug( this + '._getItemViewClass:', model );\n //TODO: subclasses use DCEViewClass - but are currently unused - decide\n switch (model.get(\"element_type\")) {\n case \"hda\":\n return this.DatasetDCEViewClass;\n case \"dataset_collection\":\n return this.NestedDCDCEViewClass;\n }\n throw new TypeError(\"Unknown element type:\", model.get(\"element_type\"));\n },\n\n /** override to add link target and anon */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n hasUser: this.hasUser,\n //TODO: could move to only nested: list:paired\n foldoutStyle: this.foldoutStyle\n });\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n\n // use pub-sub to: handle drilldown expansion and collapse\n panel.listenTo(view, {\n \"expanded:drilldown\": function(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n return this;\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$(\"> .controls\")\n .add(this.$list())\n .hide();\n drilldown.parentName = this.model.get(\"name\");\n this.$el.append(drilldown.render().$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function(drilldown) {\n this.panelStack.pop();\n this.render();\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .navigation .back\": \"close\"\n },\n\n /** close/remove this collection panel */\n close: function(event) {\n this.remove();\n this.trigger(\"close\");\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `CollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nCollectionView.prototype.templates = (() => {\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\"\n ],\n \"collection\"\n );\n\n return _.extend(_.clone(_super.prototype.templates), {\n controls: controlsTemplate\n });\n})();\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionView = CollectionView.extend(\n /** @lends ListCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionView = ListCollectionView.extend(\n /** @lends PairCollectionView.prototype */ {\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `PairCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListOfPairsCollectionView = CollectionView.extend(\n /** @lends ListOfPairsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfPairsCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionView = CollectionView.extend({\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n /** string rep */\n toString: function() {\n return `ListOfListsCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n});\n\n//==============================================================================\nexport default {\n CollectionView: CollectionView,\n ListCollectionView: ListCollectionView,\n PairCollectionView: PairCollectionView,\n ListOfPairsCollectionView: ListOfPairsCollectionView,\n ListOfListsCollectionView: ListOfListsCollectionView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-view.js","import STATES from \"mvc/dataset/states\";\nimport DATASET_LI from \"mvc/dataset/dataset-li\";\nimport TAGS from \"mvc/tag\";\nimport ANNOTATIONS from \"mvc/annotation\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DATASET_LI.DatasetListItemView;\n/** @class Editing view for DatasetAssociation.\n */\nvar DatasetListItemEdit = _super.extend(\n /** @lends DatasetListItemEdit.prototype */ {\n /** set up: options */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.hasUser = attributes.hasUser;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n //TODO: move to HiddenUntilActivatedViewMixin\n /** should the tags editor be shown or hidden initially? */\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n /** should the tags editor be shown or hidden initially? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n },\n\n // ......................................................................... titlebar actions\n /** In this override, add the other two primary actions: edit and delete */\n _renderPrimaryActions: function() {\n var actions = _super.prototype._renderPrimaryActions.call(this);\n if (this.model.get(\"state\") === STATES.NOT_VIEWABLE) {\n return actions;\n }\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions\n .call(this)\n .concat([this._renderEditButton(), this._renderDeleteButton()]);\n },\n\n //TODO: move titleButtons into state renderers, remove state checks in the buttons\n\n /** Render icon-button to edit the attributes (format, permissions, etc.) this dataset. */\n _renderEditButton: function() {\n var self = this;\n // don't show edit while uploading, in-accessible\n // DO show if in error (ala previous history panel)\n if (this.model.get(\"state\") === STATES.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n var purged = this.model.get(\"purged\");\n var deleted = this.model.get(\"deleted\");\n\n var editBtnData = {\n title: _l(\"Edit attributes\"),\n href: `${Galaxy.root}datasets/edit?dataset_id=${this.model.attributes.id}`,\n faIcon: \"fa-pencil\",\n classes: \"edit-btn\",\n onclick: function(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/edit\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n };\n\n // disable if purged or deleted and explain why in the tooltip\n if (deleted || purged) {\n editBtnData.disabled = true;\n if (purged) {\n editBtnData.title = _l(\"Cannot edit attributes of datasets removed from disk\");\n } else if (deleted) {\n editBtnData.title = _l(\"Undelete dataset to edit attributes\");\n }\n\n // disable if still uploading or new\n } else if (_.contains([STATES.UPLOAD, STATES.NEW], this.model.get(\"state\"))) {\n editBtnData.disabled = true;\n editBtnData.title = _l(\"This dataset is not yet editable\");\n }\n return faIconButton(editBtnData);\n },\n\n /** Render icon-button to delete this hda. */\n _renderDeleteButton: function() {\n // don't show delete if...\n if (!this.model.get(\"accessible\")) {\n return null;\n }\n\n var self = this;\n var deletedAlready = this.model.isDeletedOrPurged();\n return faIconButton({\n title: !deletedAlready ? _l(\"Delete\") : _l(\"Dataset is already deleted\"),\n disabled: deletedAlready,\n faIcon: \"fa-times\",\n classes: \"delete-btn\",\n onclick: function() {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n self.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n self.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... details\n /** In this override, add tags and annotations controls, make the ? dbkey a link to editing page */\n _renderDetails: function() {\n //TODO: generalize to be allow different details for each state\n var $details = _super.prototype._renderDetails.call(this);\n\n var state = this.model.get(\"state\");\n\n if (!this.model.isDeletedOrPurged() && _.contains([STATES.OK, STATES.FAILED_METADATA], state)) {\n this._renderTags($details);\n this._renderAnnotation($details);\n this._makeDbkeyEditLink($details);\n }\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /**************************************************************************\n * Render help button to show tool help text without rerunning the tool.\n * Issue #2100\n */\n _renderToolHelpButton: function() {\n var datasetID = this.model.attributes.dataset_id;\n var jobID = this.model.attributes.creating_job;\n var self = this;\n\n var parseToolBuild = data => {\n var helpString = `
`;\n if (data.name && data.help) {\n helpString += `Tool help for ${data.name}`;\n helpString += data.help;\n } else {\n helpString += \"Tool help is unavailable for this dataset.\";\n }\n helpString += \"
\";\n self.$el.find(\".details\").append($.parseHTML(helpString));\n };\n var parseToolID = data => {\n $.ajax({\n url: `${Galaxy.root}api/tools/${data.tool_id}/build`\n })\n .done(data => {\n parseToolBuild(data);\n })\n .fail(() => {\n parseToolBuild({});\n });\n };\n if (Galaxy.user.id === null) {\n return null;\n }\n return faIconButton({\n title: _l(\"Tool Help\"),\n classes: \"icon-btn\",\n href: \"#\",\n faIcon: \"fa-question\",\n onclick: function() {\n var divString = `thdiv-${datasetID}`;\n if (self.$el.find(\".toolhelp\").length > 0) {\n self.$el.find(\".toolhelp\").toggle();\n } else {\n $.ajax({\n url: `${Galaxy.root}api/jobs/${jobID}`\n })\n .done(data => {\n parseToolID(data);\n })\n .fail(() => {\n console.log(\n `Failed at recovering job information from the Galaxy API for job id \"${jobID}\".`\n );\n });\n }\n }\n });\n },\n //*************************************************************************\n\n /** Add less commonly used actions in the details section based on state */\n _renderSecondaryActions: function() {\n var actions = _super.prototype._renderSecondaryActions.call(this);\n switch (this.model.get(\"state\")) {\n case STATES.UPLOAD:\n case STATES.NOT_VIEWABLE:\n return actions;\n case STATES.ERROR:\n // error button comes first\n actions.unshift(this._renderErrButton());\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n case STATES.OK:\n case STATES.FAILED_METADATA:\n return actions.concat([\n this._renderRerunButton(),\n this._renderVisualizationsButton(),\n this._renderToolHelpButton()\n ]);\n }\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n },\n\n /** Render icon-button to report an error on this dataset to the galaxy admin. */\n _renderErrButton: function() {\n var self = this;\n return faIconButton({\n title: _l(\"View or report this error\"),\n href: `${Galaxy.root}datasets/error?dataset_id=${this.model.attributes.id}`,\n classes: \"report-error-btn\",\n faIcon: \"fa-bug\",\n onclick: function(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/error\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n });\n },\n\n /** Render icon-button to re-run the job that created this dataset. */\n _renderRerunButton: function() {\n var creating_job = this.model.get(\"creating_job\");\n if (this.model.get(\"rerunnable\")) {\n return faIconButton({\n title: _l(\"Run this job again\"),\n href: this.model.urls.rerun,\n classes: \"rerun-btn\",\n target: this.linkTarget,\n faIcon: \"fa-refresh\",\n onclick: function(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"/\", {\n job_id: creating_job\n });\n }\n }\n });\n }\n },\n\n /** Render an icon-button or popupmenu of links based on the applicable visualizations */\n _renderVisualizationsButton: function() {\n //TODO: someday - lazyload visualizations\n var visualizations = this.model.get(\"visualizations\");\n if (this.model.isDeletedOrPurged() || !this.hasUser || !this.model.hasData() || _.isEmpty(visualizations)) {\n return null;\n }\n if (!_.isObject(visualizations[0])) {\n this.warn(\"Visualizations have been switched off\");\n return null;\n }\n\n var $visualizations = $(this.templates.visualizations(visualizations, this));\n //HACK: need to re-write those directed at galaxy_main with linkTarget\n $visualizations.find('[target=\"galaxy_main\"]').attr(\"target\", this.linkTarget);\n // use addBack here to include the root $visualizations elem (for the case of 1 visualization)\n this._addScratchBookFn($visualizations.find(\".visualization-link\").addBack(\".visualization-link\"));\n return $visualizations;\n },\n\n /** add scratchbook functionality to visualization links */\n _addScratchBookFn: function($links) {\n var li = this;\n $links.click(function(ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Visualization\",\n url: $(this).attr(\"href\")\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n });\n },\n\n //TODO: if possible move these to readonly view - but display the owner's tags/annotation (no edit)\n /** Render the tags list/control */\n _renderTags: function($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.tagsEditor = new TAGS.TagsEditor({\n model: this.model,\n el: $where.find(\".tags-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function() {\n view.tagsEditorShown = true;\n },\n onhide: function() {\n view.tagsEditorShown = false;\n },\n $activator: faIconButton({\n title: _l(\"Edit dataset tags\"),\n classes: \"tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.tagsEditorShown) {\n this.tagsEditor.toggle(true);\n }\n },\n\n /** Render the annotation display/control */\n _renderAnnotation: function($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.annotationEditor = new ANNOTATIONS.AnnotationEditor({\n model: this.model,\n el: $where.find(\".annotation-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function() {\n view.annotationEditorShown = true;\n },\n onhide: function() {\n view.annotationEditorShown = false;\n },\n $activator: faIconButton({\n title: _l(\"Edit dataset annotation\"),\n classes: \"annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.annotationEditorShown) {\n this.annotationEditor.toggle(true);\n }\n },\n\n /** If the format/dbkey/genome_build isn't set, make the display a link to the edit page */\n _makeDbkeyEditLink: function($details) {\n // make the dbkey a link to editing\n if (this.model.get(\"metadata_dbkey\") === \"?\" && !this.model.isDeletedOrPurged()) {\n var editableDbkey = $('?')\n .attr(\"href\", this.model.urls.edit)\n .attr(\"target\", \"_top\");\n $details.find(\".dbkey .value\").replaceWith(editableDbkey);\n }\n },\n\n // ......................................................................... events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .undelete-link\": \"_clickUndeleteLink\",\n \"click .purge-link\": \"_clickPurgeLink\",\n\n \"click .edit-btn\": function(ev) {\n this.trigger(\"edit\", this, ev);\n },\n \"click .delete-btn\": function(ev) {\n this.trigger(\"delete\", this, ev);\n },\n \"click .rerun-btn\": function(ev) {\n this.trigger(\"rerun\", this, ev);\n },\n \"click .report-err-btn\": function(ev) {\n this.trigger(\"report-err\", this, ev);\n },\n \"click .visualization-btn\": function(ev) {\n this.trigger(\"visualize\", this, ev);\n },\n \"click .dbkey a\": function(ev) {\n this.trigger(\"edit\", this, ev);\n }\n }),\n\n /** listener for item undelete (in the messages section) */\n _clickUndeleteLink: function(ev) {\n this.model.undelete();\n return false;\n },\n\n /** listener for item purge (in the messages section) */\n _clickPurgeLink: function(ev) {\n if (confirm(_l(\"This will permanently remove the data in your dataset. Are you sure?\"))) {\n this.model.purge();\n }\n return false;\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDAEditView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetListItemEdit.prototype.templates = (() => {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n failed_metadata: BASE_MVC.wrapTemplate(\n [\n // in this override, provide a link to the edit page\n '<% if( dataset.state === \"failed_metadata\" ){ %>',\n '
\",\n \"<% } %>\"\n ],\n \"dataset\"\n ),\n\n deleted: BASE_MVC.wrapTemplate(\n [\n // in this override, provide links to undelete or purge the dataset\n \"<% if( dataset.deleted && !dataset.purged ){ %>\",\n // deleted not purged\n '
\",\n \"<% } %>\"\n ],\n \"visualizations\"\n );\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n visualizations: visualizationsTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n DatasetListItemEdit: DatasetListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/dataset-li-edit.js","import baseMVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/editable-text\";\n// =============================================================================\n/** A view on any model that has a 'annotation' attribute\n */\nvar AnnotationEditor = Backbone.View.extend(baseMVC.LoggableMixin)\n .extend(baseMVC.HiddenUntilActivatedViewMixin)\n .extend({\n tagName: \"div\",\n className: \"annotation-display\",\n\n /** Set up listeners, parse options */\n initialize: function(options) {\n options = options || {};\n this.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n //console.debug( this, options );\n // only listen to the model only for changes to annotations\n this.listenTo(this.model, \"change:annotation\", function() {\n this.render();\n });\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function() {\n var view = this;\n this.$el.html(this._template());\n\n //TODO: handle empties better\n this.$annotation().make_text_editable({\n use_textarea: true,\n on_finish: function(newAnnotation) {\n view.$annotation().text(newAnnotation);\n view.model.save({ annotation: newAnnotation }, { silent: true }).fail(() => {\n view.$annotation().text(view.model.previous(\"annotation\"));\n });\n }\n });\n return this;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _template: function() {\n var annotation = this.model.get(\"annotation\");\n return [\n //TODO: make prompt optional\n '\",\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n '
',\n _.escape(annotation),\n \"
\"\n ].join(\"\");\n },\n\n /** @returns {jQuery} the main element for this view */\n $annotation: function() {\n return this.$el.find(\".annotation\");\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function() {\n this.$annotation.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function() {\n return [\"AnnotationEditor(\", `${this.model}`, \")\"].join(\"\");\n }\n });\n// =============================================================================\nexport default {\n AnnotationEditor: AnnotationEditor\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/annotation.js","import jQuery from \"jquery\";\nvar $ = jQuery;\nimport GalaxyApp from \"galaxy\";\nimport Router from \"layout/router\";\nimport ToolPanel from \"./panels/tool-panel\";\nimport HistoryPanel from \"./panels/history-panel\";\nimport Page from \"layout/page\";\nimport ToolForm from \"mvc/tool/tool-form\";\nimport FormWrapper from \"mvc/form/form-wrapper\";\nimport UserPreferences from \"mvc/user/user-preferences\";\nimport CustomBuilds from \"mvc/user/user-custom-builds\";\nimport Tours from \"mvc/tours\";\nimport GridView from \"mvc/grid/grid-view\";\nimport GridShared from \"mvc/grid/grid-shared\";\nimport Workflows from \"mvc/workflow/workflow\";\nimport HistoryList from \"mvc/history/history-list\";\nimport ToolFormComposite from \"mvc/tool/tool-form-composite\";\nimport QueryStringParsing from \"utils/query-string-parsing\";\nimport Utils from \"utils/utils\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport DatasetError from \"mvc/dataset/dataset-error\";\nimport DatasetEditAttributes from \"mvc/dataset/dataset-edit-attributes\";\n\n/** define the 'Analyze Data'/analysis/main/home page for Galaxy\n * * has a masthead\n * * a left tool menu to allow the user to load tools in the center panel\n * * a right history menu that shows the user's current data\n * * a center panel\n * Both panels (generally) persist while the center panel shows any\n * UI needed for the current step of an analysis, like:\n * * tool forms to set tool parameters,\n * * tables showing the contents of datasets\n * * etc.\n */\nwindow.app = function app(options, bootstrapped) {\n window.Galaxy = new GalaxyApp.GalaxyApp(options, bootstrapped);\n Galaxy.debug(\"analysis app\");\n\n /** Routes */\n var AnalysisRouter = Router.extend({\n routes: {\n \"(/)\": \"home\",\n \"(/)root*\": \"home\",\n \"(/)tours(/)(:tour_id)\": \"show_tours\",\n \"(/)user(/)\": \"show_user\",\n \"(/)user(/)(:form_id)\": \"show_user_form\",\n \"(/)workflow(/)\": \"show_workflows\",\n \"(/)workflow/run(/)\": \"show_run\",\n \"(/)pages(/)create(/)\": \"show_pages_create\",\n \"(/)pages(/)edit(/)\": \"show_pages_edit\",\n \"(/)pages(/)(:action_id)\": \"show_pages\",\n \"(/)visualizations(/)edit(/)\": \"show_visualizations_edit\",\n \"(/)visualizations/(:action_id)\": \"show_visualizations\",\n \"(/)workflows/list_published(/)\": \"show_workflows_published\",\n \"(/)histories(/)rename(/)\": \"show_histories_rename\",\n \"(/)histories(/)permissions(/)\": \"show_histories_permissions\",\n \"(/)histories(/)(:action_id)\": \"show_histories\",\n \"(/)datasets(/)list(/)\": \"show_datasets\",\n \"(/)workflow/import_workflow\": \"show_import_workflow\",\n \"(/)custom_builds\": \"show_custom_builds\",\n \"(/)datasets/edit\": \"show_dataset_edit_attributes\",\n \"(/)datasets/error\": \"show_dataset_error\"\n },\n\n require_login: [\"show_user\", \"show_user_form\", \"show_workflows\"],\n\n authenticate: function(args, name) {\n return (Galaxy.user && Galaxy.user.id) || this.require_login.indexOf(name) == -1;\n },\n\n show_tours: function(tour_id) {\n if (tour_id) {\n Tours.giveTour(tour_id);\n } else {\n this.page.display(new Tours.ToursView());\n }\n },\n\n show_user: function() {\n this.page.display(new UserPreferences.View());\n },\n\n show_user_form: function(form_id) {\n var model = new UserPreferences.Model({\n user_id: Galaxy.params.id\n });\n this.page.display(new FormWrapper.View(model.get(form_id)));\n },\n\n show_visualizations: function(action_id) {\n this.page.display(\n new GridShared.View({\n action_id: action_id,\n plural: \"Visualizations\",\n item: \"visualization\"\n })\n );\n },\n\n show_visualizations_edit: function() {\n this.page.display(\n new FormWrapper.View({\n url: `visualization/edit?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"visualizations/list\"\n })\n );\n },\n\n show_workflows_published: function() {\n this.page.display(\n new GridView({\n url_base: `${Galaxy.root}workflow/list_published`,\n dict_format: true\n })\n );\n },\n\n show_histories: function(action_id) {\n this.page.display(new HistoryList.View({ action_id: action_id }));\n },\n\n show_histories_rename: function() {\n this.page.display(\n new FormWrapper.View({\n url: `history/rename?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"histories/list\"\n })\n );\n },\n\n show_histories_permissions: function() {\n this.page.display(\n new FormWrapper.View({\n url: `history/permissions?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"histories/list\"\n })\n );\n },\n\n show_datasets: function() {\n this.page.display(\n new GridView({\n url_base: `${Galaxy.root}dataset/list`,\n dict_format: true\n })\n );\n },\n\n show_pages: function(action_id) {\n this.page.display(\n new GridShared.View({\n action_id: action_id,\n plural: \"Pages\",\n item: \"page\"\n })\n );\n },\n\n show_pages_create: function() {\n this.page.display(\n new FormWrapper.View({\n url: \"page/create\",\n redirect: \"pages/list\"\n })\n );\n },\n\n show_pages_edit: function() {\n this.page.display(\n new FormWrapper.View({\n url: `page/edit?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"pages/list\"\n })\n );\n },\n\n show_workflows: function() {\n this.page.display(new Workflows.View());\n },\n\n show_run: function() {\n this._loadWorkflow();\n },\n\n show_import_workflow: function() {\n this.page.display(new Workflows.ImportWorkflowView());\n },\n\n show_custom_builds: function() {\n var self = this;\n var historyPanel = this.page.historyPanel.historyView;\n if (!historyPanel || !historyPanel.model || !historyPanel.model.id) {\n window.setTimeout(() => {\n self.show_custom_builds();\n }, 500);\n return;\n }\n this.page.display(new CustomBuilds.View());\n },\n\n show_dataset_edit_attributes: function() {\n this.page.display(new DatasetEditAttributes.View());\n },\n\n show_dataset_error: function() {\n this.page.display(new DatasetError.View());\n },\n\n /** */\n home: function(params) {\n // TODO: to router, remove Globals\n // load a tool by id (tool_id) or rerun a previous tool execution (job_id)\n if (params.tool_id || params.job_id) {\n if (params.tool_id === \"upload1\") {\n this.page.toolPanel.upload.show();\n this._loadCenterIframe(\"welcome\");\n } else {\n this._loadToolForm(params);\n }\n } else {\n // show the workflow run form\n if (params.workflow_id) {\n this._loadWorkflow();\n // load the center iframe with controller.action: galaxy.org/?m_c=history&m_a=list -> history/list\n } else if (params.m_c) {\n this._loadCenterIframe(`${params.m_c}/${params.m_a}`);\n // show the workflow run form\n } else {\n this._loadCenterIframe(\"welcome\");\n }\n }\n },\n\n /** load the center panel with a tool form described by the given params obj */\n _loadToolForm: function(params) {\n //TODO: load tool form code async\n params.id = decodeURIComponent(params.tool_id);\n this.page.display(new ToolForm.View(params));\n },\n\n /** load the center panel iframe using the given url */\n _loadCenterIframe: function(url, root) {\n root = root || Galaxy.root;\n url = root + url;\n this.page.$(\"#galaxy_main\").prop(\"src\", url);\n },\n\n /** load workflow by its url in run mode */\n _loadWorkflow: function() {\n var self = this;\n Utils.get({\n url: `${Galaxy.root}api/workflows/${Utils.getQueryString(\"id\")}/download?style=run`,\n success: function(response) {\n self.page.display(new ToolFormComposite.View(response));\n },\n error: function(response) {\n var error_msg = response.err_msg || \"Error occurred while loading the resource.\";\n var options = {\n message: error_msg,\n status: \"danger\",\n persistent: true\n };\n self.page.display(new Ui.Message(options));\n }\n });\n }\n });\n\n // render and start the router\n $(() => {\n Galaxy.page = new Page.View(\n _.extend(options, {\n Left: ToolPanel,\n Right: HistoryPanel,\n Router: AnalysisRouter\n })\n );\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/apps/analysis.js","import Tools from \"mvc/tool/tools\";\nimport Upload from \"mvc/upload/upload-view\";\nimport _l from \"utils/localization\";\nimport ToolForm from \"mvc/tool/tool-form-composite\";\n\nvar ToolPanel = Backbone.View.extend({\n initialize: function(page, options) {\n // access configuration options\n var config = options.config;\n this.root = options.root;\n\n /** @type {Object[]} descriptions of user's workflows to be shown in the tool menu */\n this.stored_workflow_menu_entries = config.stored_workflow_menu_entries || [];\n\n // create tool search, tool panel, and tool panel view.\n var tool_search = new Tools.ToolSearch({\n hidden: false\n });\n var tools = new Tools.ToolCollection(config.toolbox);\n this.tool_panel = new Tools.ToolPanel({\n tool_search: tool_search,\n tools: tools,\n layout: config.toolbox_in_panel\n });\n this.tool_panel_view = new Tools.ToolPanelView({\n model: this.tool_panel\n });\n\n // add upload modal\n this.upload_button = new Upload({\n nginx_upload_path: config.nginx_upload_path,\n ftp_upload_site: config.ftp_upload_site,\n default_genome: config.default_genome,\n default_extension: config.default_extension\n });\n\n // add uploader button to Galaxy object\n Galaxy.upload = this.upload_button;\n\n // components for panel definition\n this.model = new Backbone.Model({\n title: _l(\"Tools\"),\n buttons: [this.upload_button]\n });\n\n // build body template\n this.setElement(this._template());\n },\n\n render: function() {\n // if there are tools, render panel and display everything\n var self = this;\n if (this.tool_panel.get(\"layout\").size() > 0) {\n this.$el.prepend(this.tool_panel_view.$el);\n this.tool_panel_view.render();\n }\n // build the dom for the workflow portion of the tool menu\n // add internal workflow list\n self.$(\"#internal-workflows\").append(\n self._templateAllWorkflow({\n title: _l(\"All workflows\"),\n href: \"workflow\"\n })\n );\n _.each(this.stored_workflow_menu_entries, menu_entry => {\n self.$(\"#internal-workflows\").append(\n self._templateWorkflowLink({\n title: menu_entry.stored_workflow.name,\n href: `workflow/run?id=${menu_entry.encoded_stored_workflow_id}`\n })\n );\n });\n },\n\n /** build a link to one tool */\n _templateTool: function(tool) {\n return [\n '
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
' +\n '' +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n '
' +\n \"
\" +\n \"
\" +\n '' +\n \"
\" +\n \"
\" +\n '' +\n \"
\" +\n \"
\" +\n '' +\n \"
\" +\n '
' +\n \"
\" +\n '
' +\n '
' +\n '
' +\n '' +\n '
0%
' +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\"\n );\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/composite/composite-row.js","/** Renders contents of the collection uploader */\nimport Utils from \"utils/utils\";\nimport UploadModel from \"mvc/upload/upload-model\";\nimport UploadRow from \"mvc/upload/collection/collection-row\";\nimport UploadFtp from \"mvc/upload/upload-ftp\";\nimport UploadExtension from \"mvc/upload/upload-extension\";\nimport Popover from \"mvc/ui/ui-popover\";\nimport Select from \"mvc/ui/ui-select\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport LIST_COLLECTION_CREATOR from \"mvc/collection/list-collection-creator\";\nimport \"utils/uploadbox\";\nexport default Backbone.View.extend({\n // current upload size in bytes\n upload_size: 0,\n\n // contains upload row models\n collection: new UploadModel.Collection(),\n\n // keeps track of the current uploader state\n counter: {\n announce: 0,\n success: 0,\n error: 0,\n running: 0,\n reset: function() {\n this.announce = this.success = this.error = this.running = 0;\n }\n },\n\n initialize: function(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ui_button = app.ui_button;\n this.ftp_upload_site = app.currentFtp();\n this.setElement(this._template());\n\n // append buttons to dom\n this.btnLocal = new Ui.Button({\n id: \"btn-local\",\n title: \"Choose local files\",\n onclick: function() {\n self.uploadbox.select();\n },\n icon: \"fa fa-laptop\"\n });\n this.btnFtp = new Ui.Button({\n id: \"btn-ftp\",\n title: \"Choose FTP files\",\n onclick: function() {\n self._eventFtp();\n },\n icon: \"fa fa-folder-open-o\"\n });\n this.btnCreate = new Ui.Button({\n id: \"btn-new\",\n title: \"Paste/Fetch data\",\n onclick: function() {\n self._eventCreate();\n },\n icon: \"fa fa-edit\"\n });\n this.btnStart = new Ui.Button({\n id: \"btn-start\",\n title: \"Start\",\n onclick: function() {\n self._eventStart();\n }\n });\n this.btnBuild = new Ui.Button({\n id: \"btn-build\",\n title: \"Build\",\n onclick: function() {\n self._eventBuild();\n }\n });\n this.btnStop = new Ui.Button({\n id: \"btn-stop\",\n title: \"Pause\",\n onclick: function() {\n self._eventStop();\n }\n });\n this.btnReset = new Ui.Button({\n id: \"btn-reset\",\n title: \"Reset\",\n onclick: function() {\n self._eventReset();\n }\n });\n this.btnClose = new Ui.Button({\n id: \"btn-close\",\n title: \"Close\",\n onclick: function() {\n self.app.modal.hide();\n }\n });\n _.each(\n [\n this.btnLocal,\n this.btnFtp,\n this.btnCreate,\n this.btnStop,\n this.btnReset,\n this.btnStart,\n this.btnBuild,\n this.btnClose\n ],\n button => {\n self.$(\".upload-buttons\").prepend(button.$el);\n }\n );\n\n // file upload\n this.uploadbox = this.$(\".upload-box\").uploadbox({\n url: this.app.options.nginx_upload_path,\n announce: function(index, file) {\n self._eventAnnounce(index, file);\n },\n initialize: function(index) {\n return self.app.toData([self.collection.get(index)], self.history_id);\n },\n progress: function(index, percentage) {\n self._eventProgress(index, percentage);\n },\n success: function(index, message) {\n self._eventSuccess(index, message);\n },\n error: function(index, message) {\n self._eventError(index, message);\n },\n complete: function() {\n self._eventComplete();\n },\n ondragover: function() {\n self.$(\".upload-box\").addClass(\"highlight\");\n },\n ondragleave: function() {\n self.$(\".upload-box\").removeClass(\"highlight\");\n }\n });\n\n // add ftp file viewer\n this.ftp = new Popover.View({\n title: \"FTP files\",\n container: this.btnFtp.$el\n });\n\n // select extension\n this.select_extension = new Select.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, ext => !ext.composite_files),\n value: this.options.default_extension,\n onchange: function(extension) {\n self.updateExtension(extension);\n }\n });\n\n this.collectionType = \"list\";\n this.select_collection = new Select.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-collection-type\"),\n data: [\n { id: \"list\", text: \"List\" },\n { id: \"paired\", text: \"Paired\" },\n { id: \"list:paired\", text: \"List of Pairs\" }\n ],\n value: \"list\",\n onchange: function(collectionType) {\n self.updateCollectionType(collectionType);\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\")\n .on(\"click\", e => {\n new UploadExtension({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n })\n .on(\"mousedown\", e => {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new Select.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome,\n onchange: function(genome) {\n self.updateGenome(genome);\n }\n });\n\n // events\n this.collection.on(\"remove\", model => {\n self._eventRemove(model);\n });\n this._updateScreen();\n },\n\n /** A new file has been dropped/selected through the uploadbox plugin */\n _eventAnnounce: function(index, file) {\n this.counter.announce++;\n var new_model = new UploadModel.Model({\n id: index,\n file_name: file.name,\n file_size: file.size,\n file_mode: file.mode || \"local\",\n file_path: file.path,\n file_data: file,\n extension: this.select_extension.value(),\n genome: this.select_genome.value()\n });\n this.collection.add(new_model);\n var upload_row = new UploadRow(this, { model: new_model });\n this.$(\".upload-table > tbody:first\").append(upload_row.$el);\n this._updateScreen();\n upload_row.render();\n },\n\n /** Progress */\n _eventProgress: function(index, percentage) {\n var it = this.collection.get(index);\n it.set(\"percentage\", percentage);\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(percentage, it.get(\"file_size\")));\n },\n\n /** Success */\n _eventSuccess: function(index, message) {\n // var hdaId = message[\"outputs\"][0][\"id\"];\n var hids = _.pluck(message[\"outputs\"], \"hid\");\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"success\", hids: hids });\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(100, it.get(\"file_size\")));\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.success++;\n this._updateScreen();\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Error */\n _eventError: function(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"error\", info: message });\n this.ui_button.model.set({\n percentage: this._uploadPercentage(100, it.get(\"file_size\")),\n status: \"danger\"\n });\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.error++;\n this._updateScreen();\n },\n\n /** Queue is done */\n _eventComplete: function() {\n this.collection.each(model => {\n model.get(\"status\") == \"queued\" && model.set(\"status\", \"init\");\n });\n this.counter.running = 0;\n this._updateScreen();\n },\n\n _eventBuild: function() {\n var allHids = [];\n _.forEach(this.collection.models, upload => {\n allHids.push.apply(allHids, upload.get(\"hids\"));\n });\n var models = _.map(allHids, hid => Galaxy.currHistoryPanel.collection.getByHid(hid));\n var selection = new Galaxy.currHistoryPanel.collection.constructor(models);\n // I'm building the selection wrong because I need to set this historyId directly.\n selection.historyId = Galaxy.currHistoryPanel.collection.historyId;\n Galaxy.currHistoryPanel.buildCollection(this.collectionType, selection, true);\n this.counter.running = 0;\n this._updateScreen();\n this._eventReset();\n this.app.modal.hide();\n },\n\n /** Remove model from upload list */\n _eventRemove: function(model) {\n var status = model.get(\"status\");\n if (status == \"success\") {\n this.counter.success--;\n } else if (status == \"error\") {\n this.counter.error--;\n } else {\n this.counter.announce--;\n }\n this.uploadbox.remove(model.id);\n this._updateScreen();\n },\n\n //\n // events triggered by this view\n //\n\n /** Show/hide ftp popup */\n _eventFtp: function() {\n if (!this.ftp.visible) {\n this.ftp.empty();\n var self = this;\n this.ftp.append(\n new UploadFtp({\n collection: this.collection,\n ftp_upload_site: this.ftp_upload_site,\n onadd: function(ftp_file) {\n return self.uploadbox.add([\n {\n mode: \"ftp\",\n name: ftp_file.path,\n size: ftp_file.size,\n path: ftp_file.path\n }\n ]);\n },\n onremove: function(model_index) {\n self.collection.remove(model_index);\n }\n }).$el\n );\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Create a new file */\n _eventCreate: function() {\n this.uploadbox.add([{ name: \"New File\", size: 0, mode: \"new\" }]);\n },\n\n /** Start upload process */\n _eventStart: function() {\n if (this.counter.announce == 0 || this.counter.running > 0) {\n return;\n }\n var self = this;\n this.upload_size = 0;\n this.upload_completed = 0;\n this.collection.each(model => {\n if (model.get(\"status\") == \"init\") {\n model.set(\"status\", \"queued\");\n self.upload_size += model.get(\"file_size\");\n }\n });\n this.ui_button.model.set({ percentage: 0, status: \"success\" });\n this.counter.running = this.counter.announce;\n this.history_id = this.app.currentHistory();\n this.uploadbox.start();\n this._updateScreen();\n },\n\n /** Pause upload process */\n _eventStop: function() {\n if (this.counter.running > 0) {\n this.ui_button.model.set(\"status\", \"info\");\n $(\".upload-top-info\").html(\"Queue will pause after completing the current file...\");\n this.uploadbox.stop();\n }\n },\n\n /** Remove all */\n _eventReset: function() {\n if (this.counter.running == 0) {\n this.collection.reset();\n this.counter.reset();\n this.uploadbox.reset();\n this.select_extension.value(this.options.default_extension);\n this.select_genome.value(this.options.default_genome);\n this.ui_button.model.set(\"percentage\", 0);\n this._updateScreen();\n }\n },\n\n /** Update extension for all models */\n updateExtension: function(extension, defaults_only) {\n var self = this;\n this.collection.each(model => {\n if (\n model.get(\"status\") == \"init\" &&\n (model.get(\"extension\") == self.options.default_extension || !defaults_only)\n ) {\n model.set(\"extension\", extension);\n }\n });\n },\n\n /** Update collection type */\n updateCollectionType: function(collectionType) {\n var self = this;\n this.collectionType = collectionType;\n },\n\n /** Update genome for all models */\n updateGenome: function(genome, defaults_only) {\n var self = this;\n this.collection.each(model => {\n if (\n model.get(\"status\") == \"init\" &&\n (model.get(\"genome\") == self.options.default_genome || !defaults_only)\n ) {\n model.set(\"genome\", genome);\n }\n });\n },\n\n /** Set screen */\n _updateScreen: function() {\n var message = \"\";\n if (this.counter.announce == 0) {\n if (this.uploadbox.compatible()) {\n message = \" \";\n } else {\n message =\n \"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.\";\n }\n } else {\n if (this.counter.running == 0) {\n message = `You added ${\n this.counter.announce\n } file(s) to the queue. Add more files or click 'Start' to proceed.`;\n } else {\n message = `Please wait...${this.counter.announce} out of ${this.counter.running} remaining.`;\n }\n }\n this.$(\".upload-top-info\").html(message);\n var enable_reset =\n this.counter.running == 0 && this.counter.announce + this.counter.success + this.counter.error > 0;\n var enable_start = this.counter.running == 0 && this.counter.announce > 0;\n var enable_build =\n this.counter.running == 0 &&\n this.counter.announce == 0 &&\n this.counter.success > 0 &&\n this.counter.error == 0;\n var enable_sources = this.counter.running == 0;\n var show_table = this.counter.announce + this.counter.success + this.counter.error > 0;\n this.btnReset[enable_reset ? \"enable\" : \"disable\"]();\n this.btnStart[enable_start ? \"enable\" : \"disable\"]();\n this.btnStart.$el[enable_start ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnBuild[enable_build ? \"enable\" : \"disable\"]();\n this.btnBuild.$el[enable_build ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnStop[this.counter.running > 0 ? \"enable\" : \"disable\"]();\n this.btnLocal[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp[enable_sources ? \"enable\" : \"disable\"]();\n this.btnCreate[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp.$el[this.ftp_upload_site ? \"show\" : \"hide\"]();\n this.$(\".upload-table\")[show_table ? \"show\" : \"hide\"]();\n this.$(\".upload-helper\")[show_table ? \"hide\" : \"show\"]();\n },\n\n /** Calculate percentage of all queued uploads */\n _uploadPercentage: function(percentage, size) {\n return (this.upload_completed + percentage * size) / this.upload_size;\n },\n\n /** Template */\n _template: function() {\n return (\n '
' +\n '
' +\n '
' +\n \"
\" +\n '
' +\n '
Drop files here
' +\n '
' +\n \"\" +\n \"
\" +\n \"
Name
\" +\n \"
Size
\" +\n \"
Status
\" +\n \"
\" +\n \"
\" +\n \"\" +\n \"\" +\n \"
\" +\n \"
\" +\n '\" +\n '
' +\n \"
\"\n );\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/collection/collection-view.js","/** Renders the collection uploader rows */\nimport Utils from \"utils/utils\";\nimport UploadModel from \"mvc/upload/upload-model\";\nimport UploadSettings from \"mvc/upload/upload-settings\";\nimport Popover from \"mvc/ui/ui-popover\";\nimport Select from \"mvc/ui/ui-select\";\nexport default Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-icon-button fa fa-trash-o\",\n queued: \"upload-icon fa fa-spinner fa-spin\",\n running: \"upload-icon fa fa-spinner fa-spin\",\n success: \"upload-icon-button fa fa-check\",\n error: \"upload-icon-button fa fa-exclamation-triangle\"\n },\n\n initialize: function(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template(options.model));\n this.$mode = this.$(\".upload-mode\");\n this.$title = this.$(\".upload-title-extended\");\n this.$text = this.$(\".upload-text\");\n this.$size = this.$(\".upload-size\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$symbol = this.$(\".upload-symbol\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // append popup to settings icon\n this.settings = new Popover.View({\n title: \"Upload configuration\",\n container: this.$(\".upload-settings\"),\n placement: \"bottom\"\n });\n\n // identify default genome and extension values\n var default_genome = this.app.select_genome.value();\n var default_extension = this.app.select_extension.value();\n\n // handle click event\n this.$symbol.on(\"click\", () => {\n self._removeRow();\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", e => {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", () => {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", () => {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", () => {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:file_size\", () => {\n self._refreshFileSize();\n });\n this.listenTo(this.model, \"remove\", () => {\n self.remove();\n });\n this.app.collection.on(\"reset\", () => {\n self.remove();\n });\n },\n\n render: function() {\n var options = this.model.attributes;\n this.$title.html(_.escape(options.file_name));\n this.$size.html(Utils.bytesToString(options.file_size));\n this.$mode\n .removeClass()\n .addClass(\"upload-mode\")\n .addClass(\"text-primary\");\n if (options.file_mode == \"new\") {\n this.$text\n .css({\n width: `${this.$el.width() - 16}px`,\n top: `${this.$el.height() - 8}px`\n })\n .show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$mode.addClass(\"fa fa-edit\");\n } else if (options.file_mode == \"local\") {\n this.$mode.addClass(\"fa fa-laptop\");\n } else if (options.file_mode == \"ftp\") {\n this.$mode.addClass(\"fa fa-folder-open-o\");\n }\n },\n\n /** Refresh info text */\n _refreshInfo: function() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(`Failed: ${info}`).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage status */\n _refreshPercentage: function() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n this.$progress_bar.css({ width: `${percentage}%` });\n this.$percentage.html(percentage != 100 ? `${percentage}%` : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function() {\n var status = this.model.get(\"status\");\n this.$symbol\n .removeClass()\n .addClass(\"upload-symbol\")\n .addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status == \"init\");\n var enabled = this.model.get(\"enabled\");\n this.$text_content.attr(\"disabled\", !enabled);\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.$info_progress.hide();\n }\n },\n\n /** Refresh file size */\n _refreshFileSize: function() {\n this.$size.html(Utils.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Remove row */\n _removeRow: function() {\n if ([\"init\", \"success\", \"error\"].indexOf(this.model.get(\"status\")) !== -1) {\n this.app.collection.remove(this.model);\n }\n },\n\n /** Attach file info popup */\n _showSettings: function() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new UploadSettings(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** View template */\n _template: function(options) {\n return `
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
`;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/collection/collection-row.js","export default {\n tool: \"fa-wrench\",\n data_input: \"fa-file-o\",\n data_collection_input: \"fa-folder-o\",\n subworkflow: \"fa-sitemap fa-rotate-270\",\n pause: \"fa-pause\"\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/workflow/workflow-icons.js","import Ui from \"mvc/ui/ui-misc\";\nimport historyOptionsMenu from \"mvc/history/options-menu\";\nimport CurrentHistoryView from \"mvc/history/history-view-edit-current\";\nimport _l from \"utils/localization\";\n\n/** the right hand panel in the analysis page that shows the current history */\nvar HistoryPanel = Backbone.View.extend({\n initialize: function(page, options) {\n var self = this;\n this.userIsAnonymous = Galaxy.user.isAnonymous();\n this.allow_user_dataset_purge = options.config.allow_user_dataset_purge;\n this.root = options.root;\n\n // view of the current history\n this.historyView = new CurrentHistoryView.CurrentHistoryView({\n className: `${CurrentHistoryView.CurrentHistoryView.prototype.className} middle`,\n purgeAllowed: this.allow_user_dataset_purge,\n linkTarget: \"galaxy_main\"\n });\n\n // add history panel to Galaxy object\n Galaxy.currHistoryPanel = this.historyView;\n Galaxy.currHistoryPanel.listenToGalaxy(Galaxy);\n\n // build buttons\n this.buttonRefresh = new Ui.ButtonLink({\n id: \"history-refresh-button\",\n title: \"Refresh history\",\n cls: \"panel-header-button\",\n icon: \"fa fa-refresh\",\n onclick: function() {\n self.historyView.loadCurrentHistory();\n }\n });\n this.buttonOptions = new Ui.ButtonLink({\n id: \"history-options-button\",\n title: \"History options\",\n cls: \"panel-header-button\",\n target: \"galaxy_main\",\n icon: \"fa fa-cog\",\n href: `${this.root}root/history_options`\n });\n this.buttonViewMulti = new Ui.ButtonLink({\n id: \"history-view-multi-button\",\n title: \"View all histories\",\n cls: \"panel-header-button\",\n icon: \"fa fa-columns\",\n href: `${this.root}history/view_multiple`\n });\n\n // define components\n this.model = new Backbone.Model({\n cls: \"history-right-panel\",\n title: _l(\"History\"),\n buttons: [this.buttonRefresh, this.buttonOptions, this.buttonViewMulti]\n });\n\n // build body template and connect history view\n this.setElement(this._template());\n this.historyView.setElement(this.$el);\n this.historyView.connectToQuotaMeter(Galaxy.quotaMeter);\n this.historyView.loadCurrentHistory();\n\n // fetch to update the quota meter adding 'current' for any anon-user's id\n Galaxy.listenTo(this.historyView, \"history-size-change\", () => {\n Galaxy.user.fetch({\n url: `${Galaxy.user.urlRoot()}/${Galaxy.user.id || \"current\"}`\n });\n });\n },\n\n render: function() {\n this.optionsMenu = historyOptionsMenu(this.buttonOptions.$el, {\n anonymous: this.userIsAnonymous,\n purgeAllowed: this.allow_user_dataset_purge,\n root: this.root\n });\n this.buttonViewMulti.$el[!this.userIsAnonymous ? \"show\" : \"hide\"]();\n },\n\n /** add history view div */\n _template: function(data) {\n return [''].join(\"\");\n },\n\n toString: function() {\n return \"historyPanel\";\n }\n});\n\nexport default HistoryPanel;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/apps/panels/history-panel.js","import PopupMenu from \"mvc/ui/popup-menu\";\nimport historyCopyDialog from \"mvc/history/copy-dialog\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport Webhooks from \"mvc/webhooks\";\n\n// ============================================================================\nvar menu = [\n {\n html: _l(\"History Lists\"),\n header: true\n },\n {\n html: _l(\"Saved Histories\"),\n href: \"histories/list\",\n target: \"_top\"\n },\n {\n html: _l(\"Histories Shared with Me\"),\n href: \"histories/list_shared\",\n target: \"_top\"\n },\n {\n html: _l(\"Current History\"),\n header: true,\n anon: true\n },\n {\n html: _l(\"Create New\"),\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.createNewHistory();\n }\n }\n },\n {\n html: _l(\"Copy History\"),\n func: function() {\n historyCopyDialog(Galaxy.currHistoryPanel.model).done(() => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n },\n {\n html: _l(\"Share or Publish\"),\n href: \"history/sharing\"\n },\n {\n html: _l(\"Show Structure\"),\n href: \"history/display_structured\",\n anon: true\n },\n {\n html: _l(\"Extract Workflow\"),\n href: \"workflow/build_from_current_history\"\n },\n {\n html: _l(\"Delete\"),\n anon: true,\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel && confirm(_l(\"Really delete the current history?\"))) {\n Galaxy.currHistoryPanel.model._delete().done(() => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n {\n html: _l(\"Delete Permanently\"),\n purge: true,\n anon: true,\n func: function() {\n if (\n Galaxy &&\n Galaxy.currHistoryPanel &&\n confirm(_l(\"Really delete the current history permanently? This cannot be undone.\"))\n ) {\n Galaxy.currHistoryPanel.model.purge().done(() => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n\n {\n html: _l(\"Dataset Actions\"),\n header: true,\n anon: true\n },\n {\n html: _l(\"Copy Datasets\"),\n href: \"dataset/copy_datasets\"\n },\n {\n html: _l(\"Dataset Security\"),\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel && Galaxy.router) {\n Galaxy.router.push(`/histories/permissions?id=${Galaxy.currHistoryPanel.model.id}`);\n }\n }\n },\n {\n html: _l(\"Resume Paused Jobs\"),\n href: \"history/resume_paused_jobs?current=True\",\n anon: true\n },\n {\n html: _l(\"Collapse Expanded Datasets\"),\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.collapseAll();\n }\n }\n },\n {\n html: _l(\"Unhide Hidden Datasets\"),\n anon: true,\n func: function() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm(_l(\"Really unhide all hidden datasets?\"))) {\n $.post(`${Galaxy.root}history/adjust_hidden`, { user_action: \"unhide\" }, () => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n {\n html: _l(\"Delete Hidden Datasets\"),\n anon: true,\n func: function() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm(_l(\"Really delete all hidden datasets?\"))) {\n $.post(`${Galaxy.root}history/adjust_hidden`, { user_action: \"delete\" }, () => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n {\n html: _l(\"Purge Deleted Datasets\"),\n confirm: _l(\"Really delete all deleted datasets permanently? This cannot be undone.\"),\n href: \"history/purge_deleted_datasets\",\n purge: true,\n anon: true\n },\n\n {\n html: _l(\"Downloads\"),\n header: true\n },\n {\n html: _l(\"Export Tool Citations\"),\n href: \"history/citations\",\n anon: true\n },\n {\n html: _l(\"Export History to File\"),\n href: \"history/export_archive?preview=True\",\n anon: true\n },\n\n {\n html: _l(\"Other Actions\"),\n header: true\n },\n {\n html: _l(\"Import from File\"),\n href: \"history/import_archive\"\n }\n];\n\n// Webhooks\nWebhooks.add({\n url: \"api/webhooks/history-menu/all\",\n async: false, // (hypothetically) slows down the performance\n callback: function(webhooks) {\n var webhooks_menu = [];\n\n $.each(webhooks.models, (index, model) => {\n var webhook = model.toJSON();\n if (webhook.activate) {\n webhooks_menu.push({\n html: _l(webhook.config.title),\n // func: function() {},\n anon: true\n });\n }\n });\n\n if (webhooks_menu.length > 0) {\n webhooks_menu.unshift({\n html: _l(\"Webhooks\"),\n header: true\n });\n $.merge(menu, webhooks_menu);\n }\n }\n});\n\nfunction buildMenu(isAnon, purgeAllowed, urlRoot) {\n return _.clone(menu).filter(menuOption => {\n if (isAnon && !menuOption.anon) {\n return false;\n }\n if (!purgeAllowed && menuOption.purge) {\n return false;\n }\n\n //TODO:?? hard-coded galaxy_main\n if (menuOption.href) {\n menuOption.href = urlRoot + menuOption.href;\n menuOption.target = menuOption.target || \"galaxy_main\";\n }\n\n if (menuOption.confirm) {\n menuOption.func = () => {\n if (confirm(menuOption.confirm)) {\n galaxy_main.location = menuOption.href;\n }\n };\n }\n return true;\n });\n}\n\nvar create = ($button, options) => {\n options = options || {};\n var isAnon = options.anonymous === undefined ? true : options.anonymous;\n var purgeAllowed = options.purgeAllowed || false;\n var menu = buildMenu(isAnon, purgeAllowed, Galaxy.root);\n //console.debug( 'menu:', menu );\n return new PopupMenu($button, menu);\n};\n\n// ============================================================================\nexport default create;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/options-menu.js","import HISTORY_MODEL from \"mvc/history/history-model\";\nimport HISTORY_VIEW_EDIT from \"mvc/history/history-view-edit\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n// ============================================================================\n/** session storage for history panel preferences (and to maintain state)\n */\nvar HistoryViewPrefs = BASE_MVC.SessionStorageModel.extend(\n /** @lends HistoryViewPrefs.prototype */ {\n defaults: {\n /** should the tags editor be shown or hidden initially? */\n tagsEditorShown: false,\n /** should the annotation editor be shown or hidden initially? */\n annotationEditorShown: false,\n ///** what is the currently focused content (dataset or collection) in the current history?\n // * (the history panel will highlight and scroll to the focused content view)\n // */\n //focusedContentId : null\n /** Current scroll position */\n scrollPosition: 0\n },\n toString: function() {\n return `HistoryViewPrefs(${JSON.stringify(this.toJSON())})`;\n }\n }\n);\n\n/** key string to store panel prefs (made accessible on class so you can access sessionStorage directly) */\nHistoryViewPrefs.storageKey = function storageKey() {\n return \"history-panel\";\n};\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = HISTORY_VIEW_EDIT.HistoryViewEdit;\n// used in root/index.mako\n/** @class View/Controller for the user's current history model as used in the history\n * panel (current right hand panel) of the analysis page.\n *\n * The only history panel that:\n * will poll for updates.\n * displays datasets in reverse hid order.\n */\nvar CurrentHistoryView = _super.extend(\n /** @lends CurrentHistoryView.prototype */ {\n className: `${_super.prototype.className} current-history-panel`,\n\n /** override to use drilldown (and not foldout) for how collections are displayed */\n HDCAViewClass: _super.prototype.HDCAViewClass.extend({\n foldoutStyle: \"drilldown\"\n }),\n\n emptyMsg: [\n _l(\"This history is empty\"),\n \". \",\n _l(\"You can \"),\n '',\n _l(\"load your own data\"),\n \"\",\n _l(\" or \"),\n '',\n _l(\"get data from an external source\"),\n \"\"\n ].join(\"\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events */\n initialize: function(attributes) {\n attributes = attributes || {};\n\n // ---- persistent preferences\n /** maintain state / preferences over page loads */\n this.preferences = new HistoryViewPrefs(\n _.extend(\n {\n id: HistoryViewPrefs.storageKey()\n },\n _.pick(attributes, _.keys(HistoryViewPrefs.prototype.defaults))\n )\n );\n\n _super.prototype.initialize.call(this, attributes);\n\n /** sub-views that will overlay this panel (collections) */\n this.panelStack = [];\n\n /** id of currently focused content */\n this.currentContentId = attributes.currentContentId || null;\n //NOTE: purposely not sent to localstorage since panel recreation roughly lines up with a reset of this value\n },\n\n /** Override to cache the current scroll position with a listener */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n\n var panel = this;\n // reset scroll position when there's a new history\n this.on(\"new-model\", () => {\n panel.preferences.set(\"scrollPosition\", 0);\n });\n },\n\n // ------------------------------------------------------------------------ loading history/item models\n // TODO: next three more appropriate moved to the app level\n /** (re-)loads the user's current history & contents w/ details */\n loadCurrentHistory: function() {\n return this.loadHistory(null, {\n url: `${Galaxy.root}history/current_history_json`\n });\n },\n\n /** loads a history & contents w/ details and makes them the current history */\n switchToHistory: function(historyId, attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", _l(\"You must be logged in to switch histories\"), _l(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(historyId, {\n url: `${Galaxy.root}history/set_as_current?id=${historyId}`\n });\n },\n\n /** creates a new history on the server and sets it as the user's current history */\n createNewHistory: function(attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", _l(\"You must be logged in to create histories\"), _l(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(null, {\n url: `${Galaxy.root}history/create_new_current`\n });\n },\n\n /** release/free/shutdown old models and set up panel for new models */\n setModel: function(model, attributes, render) {\n _super.prototype.setModel.call(this, model, attributes, render);\n if (this.model && this.model.id) {\n this.log(\"checking for updates\");\n this.model.checkForUpdates();\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ history/content event listening\n /** listening for history events */\n _setUpModelListeners: function() {\n _super.prototype._setUpModelListeners.call(this);\n // re-broadcast any model change events so that listeners don't have to re-bind to each history\n return this.listenTo(this.model, {\n \"change:nice_size change:size\": function() {\n this.trigger(\"history-size-change\", this, this.model, arguments);\n },\n \"change:id\": function() {\n this.once(\"loading-done\", function() {\n this.model.checkForUpdates();\n });\n }\n });\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n // if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,\n // then: remove it from the collection if the panel is set to NOT show hidden datasets\n this.listenTo(this.collection, \"state:ready\", function(model, newState, oldState) {\n if (!model.get(\"visible\") && !this.collection.storage.includeHidden()) {\n this.removeItemView(model);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** override to add a handler to capture the scroll position when the parent scrolls */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n // console.log( '_setUpBehaviors', this.$scrollContainer( $where ).get(0), this.$list( $where ) );\n // we need to call this in _setUpBehaviors which is called after render since the $el\n // may not be attached to $el.parent and $scrollContainer() may not work\n var panel = this;\n _super.prototype._setUpBehaviors.call(panel, $where);\n\n // cache the handler to remove and re-add so we don't pile up the handlers\n if (!this._debouncedScrollCaptureHandler) {\n this._debouncedScrollCaptureHandler = _.debounce(function scrollCapture() {\n // cache the scroll position (only if visible)\n if (panel.$el.is(\":visible\")) {\n panel.preferences.set(\"scrollPosition\", $(this).scrollTop());\n }\n }, 40);\n }\n\n panel\n .$scrollContainer($where)\n .off(\"scroll\", this._debouncedScrollCaptureHandler)\n .on(\"scroll\", this._debouncedScrollCaptureHandler);\n return panel;\n },\n\n /** In this override, handle null models and move the search input to the top */\n _buildNewRender: function() {\n if (!this.model) {\n return $();\n }\n var $newRender = _super.prototype._buildNewRender.call(this);\n $newRender.find(\".search\").prependTo($newRender.find(\"> .controls\"));\n this._renderQuotaMessage($newRender);\n return $newRender;\n },\n\n /** render the message displayed when a user is over quota and can't run jobs */\n _renderQuotaMessage: function($whereTo) {\n $whereTo = $whereTo || this.$el;\n return $(this.templates.quotaMsg({}, this)).prependTo($whereTo.find(\".messages\"));\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderTags: function($where) {\n var panel = this;\n // render tags and show/hide based on preferences\n _super.prototype._renderTags.call(panel, $where);\n if (panel.preferences.get(\"tagsEditorShown\")) {\n panel.tagsEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(panel.tagsEditor, \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\", tagsEditor => {\n panel.preferences.set(\"tagsEditorShown\", tagsEditor.hidden);\n });\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderAnnotation: function($where) {\n var panel = this;\n // render annotation and show/hide based on preferences\n _super.prototype._renderAnnotation.call(panel, $where);\n if (panel.preferences.get(\"annotationEditorShown\")) {\n panel.annotationEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(\n panel.annotationEditor,\n \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\",\n annotationEditor => {\n panel.preferences.set(\"annotationEditorShown\", annotationEditor.hidden);\n }\n );\n },\n\n /** Override to scroll to cached position (in prefs) after swapping */\n _swapNewRender: function($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n var panel = this;\n _.delay(() => {\n var pos = panel.preferences.get(\"scrollPosition\");\n if (pos) {\n panel.scrollTo(pos, 0);\n }\n }, 10);\n //TODO: is this enough of a delay on larger histories?\n\n return this;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** Override to add the current-content highlight class to currentContentId's view */\n _attachItems: function($whereTo) {\n _super.prototype._attachItems.call(this, $whereTo);\n var panel = this;\n if (panel.currentContentId) {\n panel._setCurrentContentById(panel.currentContentId);\n }\n return this;\n },\n\n /** Override to remove any drill down panels */\n addItemView: function(model, collection, options) {\n var view = _super.prototype.addItemView.call(this, model, collection, options);\n if (!view) {\n return view;\n }\n if (this.panelStack.length) {\n return this._collapseDrilldownPanel();\n }\n return view;\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n // use pub-sub to: handle drilldown expansion and collapse\n return panel.listenTo(view, {\n \"expanded:drilldown\": function(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n },\n\n /** display 'current content': add a visible highlight and store the id of a content item */\n setCurrentContent: function(view) {\n this.$(\".history-content.current-content\").removeClass(\"current-content\");\n if (view) {\n view.$el.addClass(\"current-content\");\n this.currentContentId = view.model.id;\n } else {\n this.currentContentId = null;\n }\n },\n\n /** find the view with the id and then call setCurrentContent on it */\n _setCurrentContentById: function(id) {\n var view = this.viewFromModelId(id) || null;\n this.setCurrentContent(view);\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$controls()\n .add(this.$list())\n .hide();\n drilldown.parentName = this.model.get(\"name\");\n drilldown\n .delegateEvents()\n .render()\n .$el.appendTo(this.$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function(drilldown) {\n this.panelStack.pop();\n //TODO: MEM: free the panel\n this.$controls()\n .add(this.$list())\n .show();\n },\n\n // ........................................................................ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n // the two links in the empty message\n \"click .uploader-link\": function(ev) {\n Galaxy.upload.show(ev);\n },\n \"click .get-data-link\": function(ev) {\n var $toolMenu = $(\".toolMenuContainer\");\n $toolMenu.parent().scrollTop(0);\n $toolMenu.find('span:contains(\"Get Data\")').click();\n }\n }),\n\n // ........................................................................ external objects/MVC\n listenToGalaxy: function(galaxy) {\n this.listenTo(galaxy, {\n // when the galaxy_main iframe is loaded with a new page,\n // compare the url to the following list and if there's a match\n // pull the id from url and indicate in the history view that\n // the dataset with that id is the 'current'ly active dataset\n \"center-frame:load\": function(data) {\n var pathToMatch = data.fullpath;\n var hdaId = null;\n var useToURLRegexMap = {\n display: /datasets\\/([a-f0-9]+)\\/display/,\n edit: /datasets\\/([a-f0-9]+)\\/edit/,\n report_error: /dataset\\/errors\\?id=([a-f0-9]+)/,\n rerun: /tool_runner\\/rerun\\?id=([a-f0-9]+)/,\n show_params: /datasets\\/([a-f0-9]+)\\/show_params/\n // no great way to do this here? (leave it in the dataset event handlers above?)\n // 'visualization' : 'visualization',\n };\n _.find(useToURLRegexMap, (regex, use) => {\n // grab the more specific match result (1), save, and use it as the find flag\n hdaId = _.result(pathToMatch.match(regex), 1);\n return hdaId;\n });\n // need to type mangle to go from web route to history contents\n this._setCurrentContentById(hdaId ? `dataset-${hdaId}` : null);\n },\n // when the center panel is given a new view, clear the current indicator\n \"center-panel:load\": function(view) {\n this._setCurrentContentById();\n }\n });\n },\n\n //TODO: remove quota meter from panel and remove this\n /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */\n connectToQuotaMeter: function(quotaMeter) {\n if (!quotaMeter) {\n return this;\n }\n // show/hide the 'over quota message' in the history when the meter tells it to\n this.listenTo(quotaMeter, \"quota:over\", this.showQuotaMessage);\n this.listenTo(quotaMeter, \"quota:under\", this.hideQuotaMessage);\n\n // having to add this to handle re-render of hview while overquota (the above do not fire)\n this.on(\"rendered rendered:initial\", function() {\n if (quotaMeter && quotaMeter.isOverQuota()) {\n this.showQuotaMessage();\n }\n });\n return this;\n },\n\n /** Override to preserve the quota message */\n clearMessages: function(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target = $target.not(\".quota-message\");\n $target.fadeOut(this.fxSpeed, function() {\n $(this).remove();\n });\n return this;\n },\n\n /** Show the over quota message (which happens to be in the history panel).\n */\n showQuotaMessage: function() {\n var $msg = this.$(\".quota-message\");\n if ($msg.is(\":hidden\")) {\n $msg.slideDown(this.fxSpeed);\n }\n },\n\n /** Hide the over quota message (which happens to be in the history panel).\n */\n hideQuotaMessage: function() {\n var $msg = this.$(\".quota-message\");\n if (!$msg.is(\":hidden\")) {\n $msg.slideUp(this.fxSpeed);\n }\n },\n\n // ........................................................................ options menu\n //TODO: remove to batch\n /** unhide any hidden datasets */\n unhideHidden: function() {\n var self = this;\n if (confirm(_l(\"Really unhide all hidden datasets?\"))) {\n // get all hidden, regardless of deleted/purged\n return self.model.contents\n ._filterAndUpdate({ visible: false, deleted: \"\", purged: \"\" }, { visible: true })\n .done(() => {\n // TODO: would be better to render these as they're unhidden instead of all at once\n if (!self.model.contents.includeHidden) {\n self.renderItems();\n }\n });\n }\n return jQuery.when();\n },\n\n /** delete any hidden datasets */\n deleteHidden: function() {\n var self = this;\n if (confirm(_l(\"Really delete all hidden datasets?\"))) {\n return self.model.contents._filterAndUpdate(\n // get all hidden, regardless of deleted/purged\n { visible: false, deleted: \"\", purged: \"\" },\n // both delete *and* unhide them\n { deleted: true, visible: true }\n );\n }\n return jQuery.when();\n },\n\n /** Return a string rep of the history */\n toString: function() {\n return `CurrentHistoryView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nCurrentHistoryView.prototype.templates = (() => {\n var quotaMsgTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n _l(\"You are over your disk quota\"),\n \". \",\n _l(\"Tool execution is on hold until your disk usage drops below your allocated quota\"),\n \".\",\n \"
\"\n ],\n \"history\"\n );\n return _.extend(_.clone(_super.prototype.templates), {\n quotaMsg: quotaMsgTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n CurrentHistoryView: CurrentHistoryView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-view-edit-current.js","//ASSUMES: jquery\n//=============================================================================\n/** @class AjaxQueue\n * Class that allows queueing functions that return jQuery promises (such\n * as ajax calls). Each function waits for the previous to complete before\n * being called\n *\n * @constructor accepts a list of functions and automatically begins\n * processing them\n */\nclass AjaxQueue {\n constructor(initialFunctions) {\n /** the main deferred for the entire queue - note: also sends notifications of progress */\n this.deferred = jQuery.Deferred();\n /** the queue array of functions */\n this.queue = [];\n /** cache the response from each deferred call - error or success */\n this.responses = [];\n /** total number of fn's to process */\n this.numToProcess = 0;\n /** is the queue processing/waiting for any calls to return? */\n this.running = false;\n\n this.init(initialFunctions || []);\n this.start();\n }\n\n /** add all fns in initialFunctions (if any) to the queue */\n init(initialFunctions) {\n initialFunctions.forEach(fn => {\n this.add(fn);\n });\n }\n\n add(fn) {\n var index = this.queue.length;\n this.numToProcess += 1;\n\n this.queue.push(() => {\n var fnIndex = index;\n var xhr = fn();\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(response => {\n this.deferred.notify({\n curr: fnIndex,\n total: this.numToProcess,\n response: response\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(response => {\n this.responses.push(response);\n if (this.queue.length) {\n this.queue.shift()();\n } else {\n this.stop();\n }\n });\n });\n return this;\n }\n\n start() {\n if (this.queue.length) {\n this.running = true;\n this.queue.shift()();\n }\n return this;\n }\n\n /** stop the queue\n * @param {boolean} causeFail cause an error/fail on the main deferred\n * @param {String} msg message to send when rejecting the main deferred\n */\n stop(causeFail, msg) {\n //TODO: doesn't abort current call\n this.running = false;\n this.queue = [];\n if (causeFail) {\n //TODO: spliced args instead\n this.deferred.reject(msg);\n } else {\n this.deferred.resolve(this.responses);\n }\n this.numToProcess = 0;\n this.deferred = jQuery.Deferred();\n return this;\n }\n\n // only a handful of the deferred interface for now - possible YAGNI\n /** implement done from the jq deferred interface */\n done(fn) {\n return this.deferred.done(fn);\n }\n\n /** implement fail from the jq deferred interface */\n fail(fn) {\n return this.deferred.fail(fn);\n }\n\n /** implement always from the jq deferred interface */\n always(fn) {\n return this.deferred.always(fn);\n }\n\n /** implement progress from the jq deferred interface */\n progress(fn) {\n return this.deferred.progress(fn);\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n static create(initialFunctions) {\n return new AjaxQueue(initialFunctions).deferred;\n }\n}\n\n//=============================================================================\n/** @class NamedAjaxQueue\n * @augments AjaxQueue\n * Allows associating a name with a deferring fn and prevents adding deferring\n * fns if the name has already been used. Useful to prevent build up of duplicate\n * async calls.\n * Both the array initialFunctions sent to constructor and any added later with\n * add() should be objects (NOT functions) of the form:\n * { name: some unique id,\n * fn: the deferring fn or ajax call }\n */\nclass NamedAjaxQueue extends AjaxQueue {\n constructor(initialFunctions) {\n super(initialFunctions);\n this.names = {};\n }\n\n /** add the obj.fn to the queue if obj.name hasn't been used before */\n add(obj) {\n if (!(obj.hasOwnProperty(\"name\") && obj.hasOwnProperty(\"fn\"))) {\n throw new Error(`NamedAjaxQueue.add requires an object with both \"name\" and \"fn\": ${JSON.stringify(obj)}`);\n }\n if (this.names.hasOwnProperty(obj.name)) {\n //console.warn( 'name has been used:', obj.name );\n return;\n }\n this.names[obj.name] = true;\n return super.add(obj.fn);\n }\n\n clear() {\n this.names = {};\n return this;\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n static create(initialFunctions) {\n return new NamedAjaxQueue(initialFunctions).deferred;\n }\n}\n\n//=============================================================================\nexport default {\n AjaxQueue: AjaxQueue,\n NamedAjaxQueue: NamedAjaxQueue\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/ajax-queue.js","import HISTORY_VIEW from \"mvc/history/history-view\";\nimport HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport STATES from \"mvc/dataset/states\";\nimport HDA_MODEL from \"mvc/history/hda-model\";\nimport HDA_LI_EDIT from \"mvc/history/hda-li-edit\";\nimport HDCA_LI_EDIT from \"mvc/history/hdca-li-edit\";\nimport TAGS from \"mvc/tag\";\nimport ANNOTATIONS from \"mvc/annotation\";\nimport LIST_COLLECTION_CREATOR from \"mvc/collection/list-collection-creator\";\nimport PAIR_COLLECTION_CREATOR from \"mvc/collection/pair-collection-creator\";\nimport LIST_OF_PAIRS_COLLECTION_CREATOR from \"mvc/collection/list-of-pairs-collection-creator\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport PopupMenu from \"mvc/ui/popup-menu\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/editable-text\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = HISTORY_VIEW.HistoryView;\n// base class for history-view-edit-current and used as-is in history/view.mako\n/** @class Editable View/Controller for the history model.\n *\n * Allows:\n * (everything HistoryView allows)\n * changing the name\n * displaying and editing tags and annotations\n * multi-selection and operations on mulitple content items\n */\nvar HistoryViewEdit = _super.extend(\n /** @lends HistoryViewEdit.prototype */ {\n /** class to use for constructing the HistoryDatasetAssociation views */\n HDAViewClass: HDA_LI_EDIT.HDAListItemEdit,\n /** class to use for constructing the HistoryDatasetCollectionAssociation views */\n HDCAViewClass: HDCA_LI_EDIT.HDCAListItemEdit,\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes\n */\n initialize: function(attributes) {\n attributes = attributes || {};\n _super.prototype.initialize.call(this, attributes);\n\n // ---- set up instance vars\n /** editor for tags - sub-view */\n this.tagsEditor = null;\n\n /** enable drag and drop - sub-view */\n this.dragItems = true;\n\n /** editor for annotations - sub-view */\n this.annotationEditor = null;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n // states/modes the panel can be in\n /** is the panel currently showing the dataset selection controls? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n },\n\n /** Override to handle history as drag-drop target */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n return this.on({\n \"droptarget:drop\": function(ev, data) {\n // process whatever was dropped and re-hide the drop target\n this.dataDropped(data);\n this.dropTargetOff();\n },\n \"view:attached view:removed\": function() {\n this._renderCounts();\n },\n \"search:loading-progress\": this._renderSearchProgress,\n \"search:searching\": this._renderSearchFindings\n });\n },\n\n // ------------------------------------------------------------------------ listeners\n /** listening for history and HDA events */\n _setUpModelListeners: function() {\n _super.prototype._setUpModelListeners.call(this);\n this.listenTo(this.model, \"change:size\", this.updateHistoryDiskSize);\n return this;\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n this.listenTo(this.collection, {\n \"change:deleted\": this._handleItemDeletedChange,\n \"change:visible\": this._handleItemVisibleChange,\n \"change:purged\": function(model) {\n // hafta get the new nice-size w/o the purged model\n this.model.fetch();\n },\n // loading indicators for deleted/hidden\n \"fetching-deleted\": function(collection) {\n this.$(\"> .controls .deleted-count\").html(`${_l(\"loading...\")}`);\n },\n \"fetching-hidden\": function(collection) {\n this.$(\"> .controls .hidden-count\").html(`${_l(\"loading...\")}`);\n },\n \"fetching-deleted-done fetching-hidden-done\": this._renderCounts\n });\n return this;\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** In this override, add tag and annotation editors and a btn to toggle the selectors */\n _buildNewRender: function() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = _super.prototype._buildNewRender.call(this);\n if (!this.model) {\n return $newRender;\n }\n\n if (Galaxy && Galaxy.user && Galaxy.user.id && Galaxy.user.id === this.model.get(\"user_id\")) {\n this._renderTags($newRender);\n this._renderAnnotation($newRender);\n }\n return $newRender;\n },\n\n /** Update the history size display (curr. upper right of panel). */\n updateHistoryDiskSize: function() {\n this.$(\".history-size\").text(this.model.get(\"nice_size\"));\n },\n\n /** override to render counts when the items are rendered */\n renderItems: function($whereTo) {\n var views = _super.prototype.renderItems.call(this, $whereTo);\n if (!this.searchFor) {\n this._renderCounts($whereTo);\n } else {\n this._renderSearchFindings($whereTo);\n }\n return views;\n },\n\n /** override to show counts, what's deleted/hidden, and links to toggle those */\n _renderCounts: function($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.counts(this.model.toJSON(), this);\n return $whereTo.find(\"> .controls .subtitle\").html(html);\n },\n\n /** render the tags sub-view controller */\n _renderTags: function($where) {\n var panel = this;\n this.tagsEditor = new TAGS.TagsEditor({\n model: this.model,\n el: $where.find(\".controls .tags-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // show hide sub-view tag editors when this is shown/hidden\n onshow: function() {\n panel.toggleHDATagEditors(true, panel.fxSpeed);\n },\n onhide: function() {\n panel.toggleHDATagEditors(false, panel.fxSpeed);\n },\n $activator: faIconButton({\n title: _l(\"Edit history tags\"),\n classes: \"history-tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n /** render the annotation sub-view controller */\n _renderAnnotation: function($where) {\n var panel = this;\n this.annotationEditor = new ANNOTATIONS.AnnotationEditor({\n model: this.model,\n el: $where.find(\".controls .annotation-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // show hide sub-view view annotation editors when this is shown/hidden\n onshow: function() {\n panel.toggleHDAAnnotationEditors(true, panel.fxSpeed);\n },\n onhide: function() {\n panel.toggleHDAAnnotationEditors(false, panel.fxSpeed);\n },\n $activator: faIconButton({\n title: _l(\"Edit history annotation\"),\n classes: \"history-annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n\n /** Set up HistoryViewEdit js/widget behaviours\n * In this override, make the name editable\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n _super.prototype._setUpBehaviors.call(this, $where);\n if (!this.model) {\n return;\n }\n\n // anon users shouldn't have access to any of the following\n if (!Galaxy.user || Galaxy.user.isAnonymous() || Galaxy.user.id !== this.model.get(\"user_id\")) {\n return;\n }\n\n var panel = this;\n var nameSelector = \"> .controls .name\";\n $where\n .find(nameSelector)\n .attr(\"title\", _l(\"Click to rename history\"))\n .tooltip({ placement: \"bottom\" })\n .make_text_editable({\n on_finish: function(newName) {\n var previousName = panel.model.get(\"name\");\n if (newName && newName !== previousName) {\n panel.$el.find(nameSelector).text(newName);\n panel.model.save({ name: newName }).fail(() => {\n panel.$el.find(nameSelector).text(panel.model.previous(\"name\"));\n });\n } else {\n panel.$el.find(nameSelector).text(previousName);\n }\n }\n });\n },\n\n /** return a new popup menu for choosing a multi selection action\n * ajax calls made for multiple datasets are queued\n */\n multiselectActions: function() {\n var panel = this;\n\n var actions = [\n {\n html: _l(\"Hide datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.hide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n },\n {\n html: _l(\"Unhide datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.unhide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n },\n {\n html: _l(\"Delete datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype[\"delete\"];\n panel.getSelectedModels().ajaxQueue(action);\n }\n },\n {\n html: _l(\"Undelete datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.undelete;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }\n ];\n\n if (panel.purgeAllowed) {\n actions.push({\n html: _l(\"Permanently delete datasets\"),\n func: function() {\n if (confirm(_l(\"This will permanently remove the data in your datasets. Are you sure?\"))) {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.purge;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }\n });\n }\n actions = actions.concat(panel._collectionActions());\n return actions;\n },\n\n /** */\n _collectionActions: function() {\n var panel = this;\n return [\n {\n html: _l(\"Build Dataset List\"),\n func: function() {\n panel.buildCollection(\"list\");\n }\n },\n // TODO: Only show quick pair if two things selected.\n {\n html: _l(\"Build Dataset Pair\"),\n func: function() {\n panel.buildCollection(\"paired\");\n }\n },\n {\n html: _l(\"Build List of Dataset Pairs\"),\n func: function() {\n panel.buildCollection(\"list:paired\");\n }\n }\n ];\n },\n\n buildCollection: function(collectionType, selection, hideSourceItems) {\n var panel = this;\n var selection = selection || panel.getSelectedModels();\n var hideSourceItems = hideSourceItems || false;\n var createFunc;\n if (collectionType == \"list\") {\n createFunc = LIST_COLLECTION_CREATOR.createListCollection;\n } else if (collectionType == \"paired\") {\n createFunc = PAIR_COLLECTION_CREATOR.createPairCollection;\n } else if (collectionType == \"list:paired\") {\n createFunc = LIST_OF_PAIRS_COLLECTION_CREATOR.createListOfPairsCollection;\n } else {\n console.warn(`Unknown collectionType encountered ${collectionType}`);\n }\n createFunc(selection, hideSourceItems).done(() => {\n panel.model.refresh();\n });\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, add purgeAllowed and whether tags/annotation editors should be shown */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n _.extend(options, {\n purgeAllowed: this.purgeAllowed,\n tagsEditorShown: this.tagsEditor && !this.tagsEditor.hidden,\n annotationEditorShown: this.annotationEditor && !this.annotationEditor.hidden\n });\n return options;\n },\n\n /** If this item is deleted and we're not showing deleted items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemDeletedChange: function(itemModel) {\n if (itemModel.get(\"deleted\")) {\n this._handleItemDeletion(itemModel);\n } else {\n this._handleItemUndeletion(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemDeletion: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeDeleted) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUndeletion: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted -= 1;\n if (!this.model.contents.includeDeleted) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** If this item is hidden and we're not showing hidden items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemVisibleChange: function(itemModel) {\n if (itemModel.hidden()) {\n this._handleItemHidden(itemModel);\n } else {\n this._handleItemUnhidden(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemHidden: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeHidden) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUnhidden: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden -= 1;\n if (!this.model.contents.includeHidden) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** toggle the visibility of each content's tagsEditor applying all the args sent to this function */\n toggleHDATagEditors: function(showOrHide, speed) {\n _.each(this.views, view => {\n if (view.tagsEditor) {\n view.tagsEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n /** toggle the visibility of each content's annotationEditor applying all the args sent to this function */\n toggleHDAAnnotationEditors: function(showOrHide, speed) {\n _.each(this.views, view => {\n if (view.annotationEditor) {\n view.annotationEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click .toggle-deleted-link\": function(ev) {\n this.toggleShowDeleted();\n },\n \"click .toggle-hidden-link\": function(ev) {\n this.toggleShowHidden();\n }\n }),\n\n // ------------------------------------------------------------------------ search\n _renderSearchProgress: function(limit, offset) {\n var stop = limit + offset;\n return this.$(\"> .controls .subtitle\").html(\n [\"\", _l(\"Searching \"), stop, \"/\", this.model.contentsShown(), \"\"].join(\"\")\n );\n },\n\n /** override to display number found in subtitle */\n _renderSearchFindings: function($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.found(this.model.toJSON(), this);\n $whereTo.find(\"> .controls .subtitle\").html(html);\n return this;\n },\n\n // ------------------------------------------------------------------------ as drop target\n /** turn all the drag and drop handlers on and add some help text above the drop area */\n dropTargetOn: function() {\n if (this.dropTarget) {\n return this;\n }\n this.dropTarget = true;\n\n //TODO: to init\n var dropHandlers = {\n dragenter: _.bind(this.dragenter, this),\n dragover: _.bind(this.dragover, this),\n dragleave: _.bind(this.dragleave, this),\n drop: _.bind(this.drop, this)\n };\n\n var $dropTarget = this._renderDropTarget();\n this.$list().before([this._renderDropTargetHelp(), $dropTarget]);\n for (var evName in dropHandlers) {\n if (dropHandlers.hasOwnProperty(evName)) {\n //console.debug( evName, dropHandlers[ evName ] );\n $dropTarget.on(evName, dropHandlers[evName]);\n }\n }\n return this;\n },\n\n /** render a box to serve as a 'drop here' area on the history */\n _renderDropTarget: function() {\n this.$(\".history-drop-target\").remove();\n return $(\"\").addClass(\"history-drop-target\");\n },\n\n /** tell the user how it works */\n _renderDropTargetHelp: function() {\n this.$(\".history-drop-target-help\").remove();\n return $(\"\")\n .addClass(\"history-drop-target-help\")\n .text(_l(\"Drag datasets here to copy them to the current history\"));\n },\n\n /** shut down drag and drop event handlers and remove drop target */\n dropTargetOff: function() {\n if (!this.dropTarget) {\n return this;\n }\n //this.log( 'dropTargetOff' );\n this.dropTarget = false;\n var dropTarget = this.$(\".history-drop-target\").get(0);\n for (var evName in this._dropHandlers) {\n if (this._dropHandlers.hasOwnProperty(evName)) {\n dropTarget.off(evName, this._dropHandlers[evName]);\n }\n }\n this.$(\".history-drop-target\").remove();\n this.$(\".history-drop-target-help\").remove();\n return this;\n },\n /** toggle the target on/off */\n dropTargetToggle: function() {\n if (this.dropTarget) {\n this.dropTargetOff();\n } else {\n this.dropTargetOn();\n }\n return this;\n },\n\n dragenter: function(ev) {\n //console.debug( 'dragenter:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"2px solid black\");\n },\n dragover: function(ev) {\n ev.preventDefault();\n ev.stopPropagation();\n },\n dragleave: function(ev) {\n //console.debug( 'dragleave:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"1px dashed black\");\n },\n /** when (text) is dropped try to parse as json and trigger an event */\n drop: function(ev) {\n ev.preventDefault();\n //ev.stopPropagation();\n\n var self = this;\n var dataTransfer = ev.originalEvent.dataTransfer;\n var data = dataTransfer.getData(\"text\");\n\n dataTransfer.dropEffect = \"move\";\n try {\n data = JSON.parse(data);\n } catch (err) {\n self.warn(\"error parsing JSON from drop:\", data);\n }\n\n self.trigger(\"droptarget:drop\", ev, data, self);\n return false;\n },\n\n /** handler that copies data into the contents */\n dataDropped: function(data) {\n var self = this;\n // HDA: dropping will copy it to the history\n if (_.isObject(data) && data.model_class === \"HistoryDatasetAssociation\" && data.id) {\n if (self.contents.currentPage !== 0) {\n return self.contents.fetchPage(0).then(() => self.model.contents.copy(data.id));\n }\n return self.model.contents.copy(data.id);\n }\n return jQuery.when();\n },\n\n // ........................................................................ misc\n /** Return a string rep of the history */\n toString: function() {\n return `HistoryViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryViewEdit.prototype.templates = (() => {\n var countsTemplate = BASE_MVC.wrapTemplate(\n [\n \"<% var shown = Math.max( view.views.length, history.contents_active.active ) %>\",\n \"<% if( shown ){ %>\",\n '',\n \"<%- shown %> \",\n _l(\"shown\"),\n \"\",\n \"<% } %>\",\n\n \"<% if( history.contents_active.deleted ){ %>\",\n '',\n \"<% if( view.model.contents.includeDeleted ){ %>\",\n '',\n _l(\"hide deleted\"),\n \"\",\n \"<% } else { %>\",\n \"<%- history.contents_active.deleted %> \",\n '',\n _l(\"deleted\"),\n \"\",\n \"<% } %>\",\n \"\",\n \"<% } %>\",\n\n \"<% if( history.contents_active.hidden ){ %>\",\n '',\n \"<% if( view.model.contents.includeHidden ){ %>\",\n '',\n _l(\"hide hidden\"),\n \"\",\n \"<% } else { %>\",\n \"<%- history.contents_active.hidden %> \",\n '',\n _l(\"hidden\"),\n \"\",\n \"<% } %>\",\n \"\",\n \"<% } %>\"\n ],\n \"history\"\n );\n\n var foundTemplate = BASE_MVC.wrapTemplate(\n [\n _l(\"Found\"),\n \" <%- view.views.length %>, \",\n\n \"<% if( history.contents_active.deleted ){ %>\",\n \"<% if( view.model.contents.includeDeleted ){ %>\",\n '',\n _l(\"hide deleted\"),\n \", \",\n \"<% } else { %>\",\n '',\n _l(\"show deleted\"),\n \", \",\n \"<% } %>\",\n \"<% } %>\",\n\n \"<% if( history.contents_active.hidden ){ %>\",\n \"<% if( view.model.contents.includeHidden ){ %>\",\n '',\n _l(\"hide hidden\"),\n \"\",\n \"<% } else { %>\",\n '',\n _l(\"show hidden\"),\n \"\",\n \"<% } %>\",\n \"<% } %>\"\n ],\n \"history\"\n );\n\n return _.extend(_.clone(_super.prototype.templates), {\n counts: countsTemplate,\n found: foundTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n HistoryViewEdit: HistoryViewEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-view-edit.js","import LIST_VIEW from \"mvc/list/list-view\";\nimport HISTORY_MODEL from \"mvc/history/history-model\";\nimport HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport HDA_LI from \"mvc/history/hda-li\";\nimport HDCA_LI from \"mvc/history/hdca-li\";\nimport USER from \"mvc/user/user-model\";\nimport ERROR_MODAL from \"mvc/ui/error-modal\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/search-input\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a history model.\n * Allows:\n * changing the loaded history\n * displaying data, info, and download\n * tracking history attrs: size, tags, annotations, name, etc.\n * Does not allow:\n * changing the name\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar HistoryView = _super.extend(\n /** @lends HistoryView.prototype */ {\n _logNamespace: \"history\",\n\n /** class to use for constructing the HDA views */\n HDAViewClass: HDA_LI.HDAListItemView,\n /** class to use for constructing the HDCA views */\n HDCAViewClass: HDCA_LI.HDCAListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: HISTORY_CONTENTS.HistoryContents,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n tagName: \"div\",\n className: `${_super.prototype.className} history-panel`,\n\n /** string to display when the collection is empty */\n emptyMsg: _l(\"This history is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: _l(\"No matching datasets found\"),\n /** string used for search placeholder */\n searchPlaceholder: _l(\"search datasets\"),\n\n /** @type {Number} ms to wait after history load to fetch/decorate hdcas with element_count */\n FETCH_COLLECTION_COUNTS_DELAY: 2000,\n\n // ......................................................................... SET UP\n /** Set up the view, bind listeners.\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n // ---- instance vars\n // control contents/behavior based on where (and in what context) the panel is being used\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n /** timeout id for detailed fetch of collection counts, etc... */\n this.detailedFetchTimeoutId = null;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function() {\n // override\n return new this.collectionClass([], {\n history: this.model\n });\n },\n\n /** In this override, clear the update timer on the model */\n freeModel: function() {\n _super.prototype.freeModel.call(this);\n if (this.model) {\n this.model.clearUpdateTimeout();\n }\n this._clearDetailedFetchTimeout();\n return this;\n },\n\n /** clear the timeout and the cached timeout id */\n _clearDetailedFetchTimeout: function() {\n if (this.detailedFetchTimeoutId) {\n clearTimeout(this.detailedFetchTimeoutId);\n this.detailedFetchTimeoutId = null;\n }\n },\n\n /** create any event listeners for the panel\n * @fires: rendered:initial on the first render\n * @fires: empty-history when switching to a history with no contents or creating a new history\n */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n this.on({\n error: function(model, xhr, options, msg, details) {\n this.errorHandler(model, xhr, options, msg, details);\n },\n \"loading-done\": function() {\n var self = this;\n // after the initial load, decorate with more time consuming fields (like HDCA element_counts)\n self.detailedFetchTimeoutId = _.delay(() => {\n self.detailedFetchTimeoutId = null;\n self.model.contents.fetchCollectionCounts();\n }, self.FETCH_COLLECTION_COUNTS_DELAY);\n },\n \"views:ready view:attached view:removed\": function(view) {\n this._renderSelectButton();\n },\n \"view:attached\": function(view) {\n this.scrollTo(0);\n }\n });\n // this.on( 'all', function(){ console.debug( arguments ); });\n },\n\n // ------------------------------------------------------------------------ loading history/hda models\n /** load the history with the given id then it's contents, sending ajax options to both */\n loadHistory: function(historyId, options, contentsOptions) {\n contentsOptions = _.extend(contentsOptions || { silent: true });\n this.info(\"loadHistory:\", historyId, options, contentsOptions);\n var self = this;\n self.setModel(new HISTORY_MODEL.History({ id: historyId }));\n\n contentsOptions.silent = true;\n self.trigger(\"loading\");\n return self.model.fetchWithContents(options, contentsOptions).always(() => {\n self.render();\n self.trigger(\"loading-done\");\n });\n },\n\n /** convenience alias to the model. Updates the item list only (not the history) */\n refreshContents: function(options) {\n if (this.model) {\n return this.model.refresh(options);\n }\n // may have callbacks - so return an empty promise\n return $.when();\n },\n\n /** Override to reset web storage when the id changes (since it needs the id) */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n return this.listenTo(this.collection, {\n // 'all' : function(){ console.log( this.collection + ':', arguments ); },\n \"fetching-more\": function() {\n this._toggleContentsLoadingIndicator(true);\n this.$emptyMessage().hide();\n },\n \"fetching-more-done\": function() {\n this._toggleContentsLoadingIndicator(false);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function(msg, speed, callback) {\n var $indicator = $('
');\n this.$el.html($indicator.text(msg).slideDown(!_.isUndefined(speed) ? speed : this.fxSpeed));\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function(speed) {\n // make speed a bit slower to compensate for slow rendering of up to 500 contents\n this.$(\".loading-indicator\").slideUp(!_.isUndefined(speed) ? speed : this.fxSpeed + 200, function() {\n $(this).remove();\n });\n },\n\n /** In this override, add a btn to toggle the selectors */\n _buildNewRender: function() {\n var $newRender = _super.prototype._buildNewRender.call(this);\n this._renderSelectButton($newRender);\n return $newRender;\n },\n\n /** button for starting select mode */\n _renderSelectButton: function($where) {\n $where = $where || this.$el;\n // do not render selector option if no actions\n if (!this.multiselectActions().length) {\n return null;\n }\n // do not render (and remove even) if nothing to select\n if (!this.views.length) {\n this.hideSelectors();\n $where.find(\".controls .actions .show-selectors-btn\").remove();\n return null;\n }\n // don't bother rendering if there's one already\n var $existing = $where.find(\".controls .actions .show-selectors-btn\");\n if ($existing.length) {\n return $existing;\n }\n\n return faIconButton({\n title: _l(\"Operations on multiple datasets\"),\n classes: \"show-selectors-btn\",\n faIcon: \"fa-check-square-o\"\n }).prependTo($where.find(\".controls .actions\"));\n },\n\n /** override to avoid showing intial empty message using contents_active */\n _renderEmptyMessage: function($whereTo) {\n var self = this;\n var $emptyMsg = self.$emptyMessage($whereTo);\n\n var empty = self.model.get(\"contents_active\").active <= 0;\n if (empty) {\n return $emptyMsg\n .empty()\n .append(self.emptyMsg)\n .show();\n } else if (self.searchFor && self.model.contents.haveSearchDetails() && !self.views.length) {\n return $emptyMsg\n .empty()\n .append(self.noneFoundMsg)\n .show();\n }\n $emptyMsg.hide();\n return $();\n },\n\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function($where) {\n // override or set via attributes.$scrollContainer\n return this.$list($where);\n },\n\n // ------------------------------------------------------------------------ subviews\n _toggleContentsLoadingIndicator: function(show) {\n if (!show) {\n this.$list()\n .find(\".contents-loading-indicator\")\n .remove();\n } else {\n this.$list().html(\n '
' + '
'\n );\n }\n },\n\n /** override to render pagination also */\n renderItems: function($whereTo) {\n // console.log( this + '.renderItems-----------------', new Date() );\n $whereTo = $whereTo || this.$el;\n var self = this;\n var $list = self.$list($whereTo);\n\n // TODO: bootstrap hack to remove orphaned tooltips\n $(\".tooltip\").remove();\n\n $list.empty();\n self.views = [];\n\n var models = self._filterCollection();\n if (models.length) {\n self._renderPagination($whereTo);\n self.views = self._renderSomeItems(models, $list);\n } else {\n // TODO: consolidate with _renderPagination above by (???) passing in models/length?\n $whereTo.find(\"> .controls .list-pagination\").empty();\n }\n self._renderEmptyMessage($whereTo).toggle(!models.length);\n\n self.trigger(\"views:ready\", self.views);\n return self.views;\n },\n\n /** render pagination controls if not searching and contents says we're paginating */\n _renderPagination: function($whereTo) {\n var $paginationControls = $whereTo.find(\"> .controls .list-pagination\");\n if (this.searchFor || !this.model.contents.shouldPaginate()) return $paginationControls.empty();\n\n $paginationControls.html(\n this.templates.pagination(\n {\n // pagination is 1-based for the user\n current: this.model.contents.currentPage + 1,\n last: this.model.contents.getLastPage() + 1\n },\n this\n )\n );\n $paginationControls.find(\"select.pages\").tooltip();\n return $paginationControls;\n },\n\n /** render a subset of the entire collection (client-side pagination) */\n _renderSomeItems: function(models, $list) {\n var self = this;\n var views = [];\n $list.append(\n models.map(m => {\n var view = self._createItemView(m);\n views.push(view);\n return self._renderItemView$el(view);\n })\n );\n return views;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** in this override, check if the contents would also display based on includeDeleted/hidden */\n _filterItem: function(model) {\n var self = this;\n var contents = self.model.contents;\n return (\n (contents.includeHidden || !model.hidden()) &&\n (contents.includeDeleted || !model.isDeletedOrPurged()) &&\n _super.prototype._filterItem.call(self, model)\n );\n },\n\n /** In this override, since history contents are mixed,\n * get the appropo view class based on history_content_type\n */\n _getItemViewClass: function(model) {\n var contentType = model.get(\"history_content_type\");\n switch (contentType) {\n case \"dataset\":\n return this.HDAViewClass;\n case \"dataset_collection\":\n return this.HDCAViewClass;\n }\n throw new TypeError(`Unknown history_content_type: ${contentType}`);\n },\n\n /** in this override, add a linktarget, and expand if id is in web storage */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n expanded: this.model.contents.storage.isExpanded(model.id),\n hasUser: this.model.ownedByCurrUser()\n });\n },\n\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n //TODO: send from content view: this.model.collection.storage.addExpanded\n // maintain a list of items whose bodies are expanded\n return panel.listenTo(view, {\n expanded: function(v) {\n panel.model.contents.storage.addExpanded(v.model);\n },\n collapsed: function(v) {\n panel.model.contents.storage.removeExpanded(v.model);\n }\n });\n },\n\n /** override to remove expandedIds from webstorage */\n collapseAll: function() {\n this.model.contents.storage.clearExpanded();\n _super.prototype.collapseAll.call(this);\n },\n\n // ------------------------------------------------------------------------ selection\n /** Override to correctly set the historyId of the new collection */\n getSelectedModels: function() {\n var collection = _super.prototype.getSelectedModels.call(this);\n collection.historyId = this.collection.historyId;\n return collection;\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click > .controls .prev\": \"_clickPrevPage\",\n \"click > .controls .next\": \"_clickNextPage\",\n \"change > .controls .pages\": \"_changePageSelect\",\n // allow (error) messages to be clicked away\n \"click .messages [class$=message]\": \"clearMessages\"\n }),\n\n _clickPrevPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchPrevPage();\n },\n\n _clickNextPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchNextPage();\n },\n\n _changePageSelect: function(ev) {\n this.model.clearUpdateTimeout();\n var page = $(ev.currentTarget).val();\n this.model.contents.fetchPage(page);\n },\n\n /** Toggle and store the deleted visibility and re-render items\n * @returns {Boolean} new setting\n */\n toggleShowDeleted: function(show, options) {\n show = show !== undefined ? show : !this.model.contents.includeDeleted;\n var self = this;\n var contents = self.model.contents;\n contents.setIncludeDeleted(show, options);\n self.trigger(\"show-deleted\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** Toggle and store whether to render explicity hidden contents\n * @returns {Boolean} new setting\n */\n toggleShowHidden: function(show, store, options) {\n // console.log( 'toggleShowHidden', show, store );\n show = show !== undefined ? show : !this.model.contents.includeHidden;\n var self = this;\n var contents = self.model.contents;\n contents.setIncludeHidden(show, options);\n self.trigger(\"show-hidden\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** On the first search, if there are no details - load them, then search */\n _firstSearch: function(searchFor) {\n var self = this;\n var inputSelector = \"> .controls .search-input\";\n this.log(\"onFirstSearch\", searchFor);\n\n // if the contents already have enough details to search, search and return now\n if (self.model.contents.haveSearchDetails()) {\n self.searchItems(searchFor);\n return;\n }\n\n // otherwise, load the details progressively here\n self.$(inputSelector).searchInput(\"toggle-loading\");\n // set this now so that only results will show during progress\n self.searchFor = searchFor;\n var xhr = self.model.contents\n .progressivelyFetchDetails({ silent: true })\n .progress((response, limit, offset) => {\n self.renderItems();\n self.trigger(\"search:loading-progress\", limit, offset);\n })\n .always(() => {\n self.$el.find(inputSelector).searchInput(\"toggle-loading\");\n })\n .done(() => {\n self.searchItems(searchFor, \"force\");\n });\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function(searchFor) {\n var self = this;\n if (!self.searchFor) return self;\n //self.log( 'onSearchClear', self );\n self.searchFor = \"\";\n self.trigger(\"search:clear\", self);\n self.$(\"> .controls .search-query\").val(\"\");\n // NOTE: silent + render prevents collection update event with merge only\n // - which causes an empty page due to event handler above\n self.model.contents.fetchCurrentPage({ silent: true }).done(() => {\n self.renderItems();\n });\n return self;\n },\n\n // ........................................................................ error handling\n /** Event handler for errors (from the panel, the history, or the history's contents)\n * Alternately use two strings for model and xhr to use custom message and title (respectively)\n * @param {Model or View} model the (Backbone) source of the error\n * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error\n * @param {Object} options the options map commonly used with bbone ajax\n */\n errorHandler: function(model, xhr, options) {\n //TODO: to mixin or base model\n // interrupted ajax or no connection\n if (xhr && xhr.status === 0 && xhr.readyState === 0) {\n // return ERROR_MODAL.offlineErrorModal();\n // fail silently\n return;\n }\n // otherwise, leave something to report in the console\n this.error(model, xhr, options);\n // and feedback to a modal\n // if sent two strings (and possibly details as 'options'), use those as message and title\n if (_.isString(model) && _.isString(xhr)) {\n var message = model;\n var title = xhr;\n return ERROR_MODAL.errorModal(message, title, options);\n }\n // bad gateway\n // TODO: possibly to global handler\n if (xhr && xhr.status === 502) {\n return ERROR_MODAL.badGatewayErrorModal();\n }\n return ERROR_MODAL.ajaxErrorModal(model, xhr, options);\n },\n\n /** Remove all messages from the panel. */\n clearMessages: function(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target.fadeOut(this.fxSpeed, function() {\n $(this).remove();\n });\n return this;\n },\n\n // ........................................................................ scrolling\n /** Scrolls the panel to show the content sub-view with the given hid.\n * @param {Integer} hid the hid of item to scroll into view\n * @returns {HistoryView} the panel\n */\n scrollToHid: function(hid) {\n return this.scrollToItem(_.first(this.viewsWhereModel({ hid: hid })));\n },\n\n // ........................................................................ misc\n /** utility for adding -st, -nd, -rd, -th to numbers */\n ordinalIndicator: function(number) {\n var numStr = `${number}`;\n switch (numStr.charAt(numStr.length - 1)) {\n case \"1\":\n return `${numStr}st`;\n case \"2\":\n return `${numStr}nd`;\n case \"3\":\n return `${numStr}rd`;\n default:\n return `${numStr}th`;\n }\n },\n\n /** Return a string rep of the history */\n toString: function() {\n return `HistoryView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryView.prototype.templates = (() => {\n var mainTemplate = BASE_MVC.wrapTemplate([\n // temp container\n \"
\",\n '',\n '
',\n '',\n \"
\"\n ]);\n\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\",\n \"<% } %>\"\n ],\n \"dataset\"\n )\n });\n\n return _.extend({}, _super.prototype.templates, {\n //NOTE: *steal* the HDAListItemView titleBar\n titleBar: HDA_LI.HDAListItemView.prototype.templates.titleBar,\n warnings: warnings\n });\n})();\n\n//==============================================================================\nexport default {\n HDAListItemEdit: HDAListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hda-li-edit.js","import HDCA_LI from \"mvc/history/hdca-li\";\nimport DC_VIEW_EDIT from \"mvc/collection/collection-view-edit\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = HDCA_LI.HDCAListItemView;\n/** @class Editing view for HistoryDatasetCollectionAssociation.\n */\nvar HDCAListItemEdit = _super.extend(\n /** @lends HDCAListItemEdit.prototype */ {\n /** logger used to record this.log messages, commonly set to console */\n //logger : console,\n\n /** Override to return editable versions of the collection panels */\n _getFoldoutPanelClass: function() {\n switch (this.model.get(\"collection_type\")) {\n case \"list\":\n return DC_VIEW_EDIT.ListCollectionViewEdit;\n case \"paired\":\n return DC_VIEW_EDIT.PairCollectionViewEdit;\n case \"list:paired\":\n return DC_VIEW_EDIT.ListOfPairsCollectionViewEdit;\n case \"list:list\":\n return DC_VIEW_EDIT.ListOfListsCollectionViewEdit;\n }\n throw new TypeError(`Uknown collection_type: ${this.model.get(\"collection_type\")}`);\n },\n\n // ......................................................................... delete\n /** In this override, add the delete button. */\n _renderPrimaryActions: function() {\n this.log(`${this}._renderPrimaryActions`);\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions.call(this).concat([this._renderDeleteButton()]);\n },\n\n /** Render icon-button to delete this collection. */\n _renderDeleteButton: function() {\n var self = this;\n var deleted = this.model.get(\"deleted\");\n return faIconButton({\n title: deleted ? _l(\"Dataset collection is already deleted\") : _l(\"Delete\"),\n classes: \"delete-btn\",\n faIcon: \"fa-times\",\n disabled: deleted,\n onclick: function() {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n self.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n self.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDCAListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n HDCAListItemEdit: HDCAListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hdca-li-edit.js","import DC_VIEW from \"mvc/collection/collection-view\";\nimport DC_MODEL from \"mvc/collection/collection-model\";\nimport DC_EDIT from \"mvc/collection/collection-li-edit\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport TAGS from \"mvc/tag\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport _l from \"utils/localization\";\nimport \"ui/editable-text\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class editable View/Controller for a dataset collection.\n */\nvar _super = DC_VIEW.CollectionView;\nvar CollectionViewEdit = _super.extend(\n /** @lends CollectionView.prototype */ {\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n\n /** logger used to record this.log messages, commonly set to console */\n //logger : console,\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_EDIT.DatasetDCEListItemEdit,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit,\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n },\n\n /** In this override, make the collection name editable\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n _super.prototype._setUpBehaviors.call(this, $where);\n if (!this.model) {\n return;\n }\n\n // anon users shouldn't have access to any of the following\n if (!Galaxy.user || Galaxy.user.isAnonymous()) {\n return;\n }\n\n this.tagsEditorShown = true;\n\n //TODO: extract\n var panel = this;\n\n var nameSelector = \"> .controls .name\";\n $where\n .find(nameSelector)\n .attr(\"title\", _l(\"Click to rename collection\"))\n .tooltip({ placement: \"bottom\" })\n .make_text_editable({\n on_finish: function(newName) {\n var previousName = panel.model.get(\"name\");\n if (newName && newName !== previousName) {\n panel.$el.find(nameSelector).text(newName);\n panel.model.save({ name: newName }).fail(() => {\n panel.$el.find(nameSelector).text(panel.model.previous(\"name\"));\n });\n } else {\n panel.$el.find(nameSelector).text(previousName);\n }\n }\n });\n this.tagsEditor = new TAGS.TagsEditor({\n model: this.model,\n el: $where.find(\".tags-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n usePrompt: false\n });\n this.tagsEditor.toggle(true);\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `CollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionViewEdit = CollectionViewEdit.extend(\n /** @lends ListCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_EDIT.DatasetDCEListItemEdit,\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class Editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionViewEdit = ListCollectionViewEdit.extend(\n /** @lends PairCollectionViewEdit.prototype */ {\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `PairCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class Editable (roughly since these collections are immutable),\n * View/Controller for a dataset collection.\n */\nvar NestedPairCollectionViewEdit = PairCollectionViewEdit.extend(\n /** @lends NestedPairCollectionViewEdit.prototype */ {\n /** Override to remove the editable text from the name/identifier - these collections are considered immutable */\n _setUpBehaviors: function($where) {\n _super.prototype._setUpBehaviors.call(this, $where);\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `NestedPairCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class editable, View/Controller for a list of pairs dataset collection. */\nvar ListOfPairsCollectionViewEdit = CollectionViewEdit.extend(\n /** @lends ListOfPairsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit.extend({\n foldoutPanelClass: NestedPairCollectionViewEdit\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfPairsCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionViewEdit = CollectionViewEdit.extend(\n /** @lends ListOfListsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit.extend({\n foldoutPanelClass: NestedPairCollectionViewEdit\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfListsCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n CollectionViewEdit: CollectionViewEdit,\n ListCollectionViewEdit: ListCollectionViewEdit,\n PairCollectionViewEdit: PairCollectionViewEdit,\n ListOfPairsCollectionViewEdit: ListOfPairsCollectionViewEdit,\n ListOfListsCollectionViewEdit: ListOfListsCollectionViewEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-view-edit.js","import DC_LI from \"mvc/collection/collection-li\";\nimport DATASET_LI_EDIT from \"mvc/dataset/dataset-li-edit\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar DCListItemView = DC_LI.DCListItemView;\n/** @class Edit view for DatasetCollection.\n */\nvar DCListItemEdit = DCListItemView.extend(\n /** @lends DCListItemEdit.prototype */ {\n /** override to add linkTarget */\n initialize: function(attributes) {\n DCListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DCListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nvar DCEListItemView = DC_LI.DCEListItemView;\n/** @class Read only view for DatasetCollectionElement.\n */\nvar DCEListItemEdit = DCEListItemView.extend(\n /** @lends DCEListItemEdit.prototype */ {\n //TODO: this might be expendable - compacted with HDAListItemView\n\n /** set up */\n initialize: function(attributes) {\n DCEListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DCEListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\n// NOTE: this does not inherit from DatasetDCEListItemView as you would expect\n//TODO: but should - if we can find something simpler than using diamond\n/** @class Editable view for a DatasetCollectionElement that is also an DatasetAssociation\n * (a dataset contained in a dataset collection).\n */\nvar DatasetDCEListItemEdit = DATASET_LI_EDIT.DatasetListItemEdit.extend(\n /** @lends DatasetDCEListItemEdit.prototype */ {\n /** set up */\n initialize: function(attributes) {\n DATASET_LI_EDIT.DatasetListItemEdit.prototype.initialize.call(this, attributes);\n },\n\n // NOTE: this does not inherit from DatasetDCEListItemView - so we duplicate this here\n //TODO: fix\n /** In this override, only get details if in the ready state.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n /** Override to remove delete button */\n _renderDeleteButton: function() {\n return null;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DatasetDCEListItemEdit(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetDCEListItemEdit.prototype.templates = (() =>\n _.extend({}, DATASET_LI_EDIT.DatasetListItemEdit.prototype.templates, {\n titleBar: DC_LI.DatasetDCEListItemView.prototype.templates.titleBar\n }))();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection\n * (a nested DC).\n */\nvar NestedDCDCEListItemEdit = DC_LI.NestedDCDCEListItemView.extend(\n /** @lends NestedDCDCEListItemEdit.prototype */ {\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `NestedDCDCEListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n DCListItemEdit: DCListItemEdit,\n DCEListItemEdit: DCEListItemEdit,\n DatasetDCEListItemEdit: DatasetDCEListItemEdit,\n NestedDCDCEListItemEdit: NestedDCDCEListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-li-edit.js","import LIST_CREATOR from \"mvc/collection/list-collection-creator\";\nimport HDCA from \"mvc/history/hdca-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"collections\";\n/*==============================================================================\nTODO:\n the paired creator doesn't really mesh with the list creator as parent\n it may be better to make an abstract super class for both\n composites may inherit from this (or vis-versa)\n PairedDatasetCollectionElementView doesn't make a lot of sense\n\n==============================================================================*/\n/** */\nvar PairedDatasetCollectionElementView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))\n tagName: \"li\",\n className: \"collection-element\",\n\n initialize: function(attributes) {\n this.element = attributes.element || {};\n this.identifier = attributes.identifier;\n },\n\n render: function() {\n this.$el.attr(\"data-element-id\", this.element.id).html(\n this.template({\n identifier: this.identifier,\n element: this.element\n })\n );\n return this;\n },\n\n //TODO: lots of unused space in the element - possibly load details and display them horiz.\n template: _.template(\n ['<%- identifier %>', '<%- element.name %>'].join(\"\")\n ),\n\n /** remove the DOM and any listeners */\n destroy: function() {\n this.off();\n this.$el.remove();\n },\n\n /** string rep */\n toString: function() {\n return \"DatasetCollectionElementView()\";\n }\n});\n\n// ============================================================================\nvar _super = LIST_CREATOR.ListCollectionCreator;\n\n/** An interface for building collections.\n */\nvar PairCollectionCreator = _super.extend({\n /** the class used to display individual elements */\n elementViewClass: PairedDatasetCollectionElementView,\n /** the class this creator will create and save */\n collectionClass: HDCA.HistoryPairDatasetCollection,\n className: \"pair-collection-creator collection-creator flex-row-container\",\n\n /** override to no-op */\n _mangleDuplicateNames: function() {},\n\n // TODO: this whole pattern sucks. There needs to be two classes of problem area:\n // bad inital choices and\n // when the user has painted his/her self into a corner during creation/use-of-the-creator\n /** render the entire interface */\n render: function(speed, callback) {\n if (this.workingElements.length === 2) {\n return _super.prototype.render.call(this, speed, callback);\n }\n return this._renderInvalid(speed, callback);\n },\n\n // ------------------------------------------------------------------------ rendering elements\n /** render forward/reverse */\n _renderList: function(speed, callback) {\n //this.debug( '-- _renderList' );\n //precondition: there are two valid elements in workingElements\n var creator = this;\n\n var $tmp = jQuery(\"\");\n var $list = creator.$list();\n\n // lose the original views, create the new, append all at once, then call their renders\n _.each(this.elementViews, view => {\n view.destroy();\n creator.removeElementView(view);\n });\n $tmp.append(creator._createForwardElementView().$el);\n $tmp.append(creator._createReverseElementView().$el);\n $list.empty().append($tmp.children());\n _.invoke(creator.elementViews, \"render\");\n },\n\n /** create the forward element view */\n _createForwardElementView: function() {\n return this._createElementView(this.workingElements[0], {\n identifier: \"forward\"\n });\n },\n\n /** create the forward element view */\n _createReverseElementView: function() {\n return this._createElementView(this.workingElements[1], {\n identifier: \"reverse\"\n });\n },\n\n /** create an element view, cache in elementViews, and return */\n _createElementView: function(element, options) {\n var elementView = new this.elementViewClass(\n _.extend(options, {\n element: element\n })\n );\n this.elementViews.push(elementView);\n return elementView;\n },\n\n /** swap the forward, reverse elements and re-render */\n swap: function() {\n this.workingElements = [this.workingElements[1], this.workingElements[0]];\n this._renderList();\n },\n\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .swap\": \"swap\"\n }),\n\n // ------------------------------------------------------------------------ templates\n //TODO: move to require text plugin and load these as text\n //TODO: underscore currently unnecc. bc no vars are used\n //TODO: better way of localizing text-nodes in long strings\n /** underscore template fns attached to class */\n templates: _.extend(_.clone(_super.prototype.templates), {\n /** the middle: element list */\n middle: _.template(\n [\n '
\",\n _l(\n [\n \"Pair collections are permanent collections containing two datasets: one forward and one reverse. \",\n \"Often these are forward and reverse reads. The pair collections can be passed to tools and \",\n \"workflows in order to have analyses done on both datasets. This interface allows \",\n \"you to create a pair, name it, and swap which is forward and which reverse.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n 'Click the \"Swap\" link to make your forward dataset the reverse ',\n \"and the reverse dataset forward.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(['Click the \"Cancel\" button to exit the interface.'].join(\"\")),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n 'Once your collection is complete, enter a name and ',\n 'click \"Create list\".'\n ].join(\"\")\n ),\n \"
\"\n ].join(\"\")\n ),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(\n [\n '
',\n '
',\n '',\n \"<% if( _.size( problems ) ){ %>\",\n _l(\"The following selections could not be included due to problems\"),\n \"
<% _.each( problems, function( problem ){ %>\",\n \"
<%- problem.element.name %>: <%- problem.text %>
\",\n \"<% }); %>
\",\n \"<% } else if( _.size( elements ) === 0 ){ %>\",\n _l(\"No datasets were selected\"),\n \".\",\n \"<% } else if( _.size( elements ) === 1 ){ %>\",\n _l(\"Only one dataset was selected\"),\n \": <%- elements[0].name %>\",\n \"<% } else if( _.size( elements ) > 2 ){ %>\",\n _l(\"Too many datasets were selected\"),\n ': <%- _.pluck( elements, \"name\" ).join( \", \") %>',\n \"<% } %>\",\n \" \",\n _l(\"Two (and only two) elements are needed for the pair\"),\n \". \",\n _l(\"You may need to \"),\n '',\n _l(\"cancel\"),\n \" \",\n _l(\"and reselect new elements\"),\n \".\",\n \"\",\n \"
\",\n \"
\",\n '\"\n ].join(\"\")\n )\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function() {\n return \"PairCollectionCreator\";\n }\n});\n\n//==============================================================================\n/** List collection flavor of collectionCreatorModal. */\nvar pairCollectionCreatorModal = function _pairCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = _l(\"Create a collection from a pair of datasets\");\n return LIST_CREATOR.collectionCreatorModal(elements, options, PairCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a pair collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createPairCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = pairCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function(elements, name, hideSourceItems) {\n elements = [\n { name: \"forward\", src: \"hda\", id: elements[0].id },\n { name: \"reverse\", src: \"hda\", id: elements[1].id }\n ];\n return contents.createHDCA(elements, \"paired\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexport default {\n PairCollectionCreator: PairCollectionCreator,\n pairCollectionCreatorModal: pairCollectionCreatorModal,\n createPairCollection: createPairCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/pair-collection-creator.js","import levenshteinDistance from \"utils/levenshtein\";\nimport naturalSort from \"utils/natural-sort\";\nimport baseCreator from \"mvc/collection/base-creator\";\nimport baseMVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/hoverhighlight\";\n\nvar logNamespace = \"collections\";\n/* ============================================================================\nTODO:\n\n\nPROGRAMMATICALLY:\ncurrPanel.once( 'rendered', function(){\n currPanel.showSelectors();\n currPanel.selectAll();\n _.last( currPanel.actionsPopup.options ).func();\n});\n\n============================================================================ */\n/** A view for paired datasets in the collections creator.\n */\nvar PairView = Backbone.View.extend(baseMVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n tagName: \"li\",\n className: \"dataset paired\",\n\n initialize: function(attributes) {\n this.pair = attributes.pair || {};\n },\n\n template: _.template(\n [\n '<%- pair.forward.name %>',\n '',\n '<%- pair.name %>',\n \"\",\n '<%- pair.reverse.name %>'\n ].join(\"\")\n ),\n\n render: function() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el\n .attr(\"draggable\", true)\n .data(\"pair\", this.pair)\n .html(this.template({ pair: this.pair }))\n .addClass(\"flex-column-container\")\n .get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n return this;\n },\n\n events: {\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function(ev) {\n ev.currentTarget.style.opacity = \"0.4\";\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.pair));\n\n this.$el.parent().trigger(\"pair.dragstart\", [this]);\n },\n\n /** dragging pairs for re-ordering */\n _dragend: function(ev) {\n ev.currentTarget.style.opacity = \"1.0\";\n this.$el.parent().trigger(\"pair.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function() {\n return `PairView(${this.pair.name})`;\n }\n});\n\n// ============================================================================\n/** returns an autopair function that uses the provided options.match function */\nfunction autoPairFnBuilder(options) {\n options = options || {};\n options.createPair =\n options.createPair ||\n function _defaultCreatePair(params) {\n params = params || {};\n var a = params.listA.splice(params.indexA, 1)[0];\n var b = params.listB.splice(params.indexB, 1)[0];\n var aInBIndex = params.listB.indexOf(a);\n var bInAIndex = params.listA.indexOf(b);\n if (aInBIndex !== -1) {\n params.listB.splice(aInBIndex, 1);\n }\n if (bInAIndex !== -1) {\n params.listA.splice(bInAIndex, 1);\n }\n return this._pair(a, b, { silent: true });\n };\n // compile these here outside of the loop\n var _regexps = [];\n function getRegExps() {\n if (!_regexps.length) {\n _regexps = [new RegExp(this.filters[0]), new RegExp(this.filters[1])];\n }\n return _regexps;\n }\n // mangle params as needed\n options.preprocessMatch =\n options.preprocessMatch ||\n function _defaultPreprocessMatch(params) {\n var regexps = getRegExps.call(this);\n return _.extend(params, {\n matchTo: params.matchTo.name.replace(regexps[0], \"\"),\n possible: params.possible.name.replace(regexps[1], \"\")\n });\n };\n\n return function _strategy(params) {\n this.debug(\"autopair _strategy ---------------------------\");\n params = params || {};\n var listA = params.listA;\n var listB = params.listB;\n var indexA = 0;\n var indexB;\n\n var bestMatch = {\n score: 0.0,\n index: null\n };\n\n var paired = [];\n //console.debug( 'params:', JSON.stringify( params, null, ' ' ) );\n this.debug(\"starting list lens:\", listA.length, listB.length);\n this.debug(\"bestMatch (starting):\", JSON.stringify(bestMatch, null, \" \"));\n\n while (indexA < listA.length) {\n var matchTo = listA[indexA];\n bestMatch.score = 0.0;\n\n for (indexB = 0; indexB < listB.length; indexB++) {\n var possible = listB[indexB];\n this.debug(`${indexA}:${matchTo.name}`);\n this.debug(`${indexB}:${possible.name}`);\n\n // no matching with self\n if (listA[indexA] !== listB[indexB]) {\n bestMatch = options.match.call(\n this,\n options.preprocessMatch.call(this, {\n matchTo: matchTo,\n possible: possible,\n index: indexB,\n bestMatch: bestMatch\n })\n );\n this.debug(\"bestMatch:\", JSON.stringify(bestMatch, null, \" \"));\n if (bestMatch.score === 1.0) {\n this.debug(\"breaking early due to perfect match\");\n break;\n }\n }\n }\n var scoreThreshold = options.scoreThreshold.call(this);\n this.debug(\"scoreThreshold:\", scoreThreshold);\n this.debug(\"bestMatch.score:\", bestMatch.score);\n\n if (bestMatch.score >= scoreThreshold) {\n //console.debug( 'autoPairFnBuilder.strategy', listA[ indexA ].name, listB[ bestMatch.index ].name );\n paired.push(\n options.createPair.call(this, {\n listA: listA,\n indexA: indexA,\n listB: listB,\n indexB: bestMatch.index\n })\n );\n //console.debug( 'list lens now:', listA.length, listB.length );\n } else {\n indexA += 1;\n }\n if (!listA.length || !listB.length) {\n return paired;\n }\n }\n this.debug(\"paired:\", JSON.stringify(paired, null, \" \"));\n this.debug(\"autopair _strategy ---------------------------\");\n return paired;\n };\n}\n\n// ============================================================================\n/** An interface for building collections of paired datasets.\n */\nvar PairedCollectionCreator = Backbone.View.extend(baseMVC.LoggableMixin)\n .extend(baseCreator.CollectionCreatorMixin)\n .extend({\n _logNamespace: logNamespace,\n\n className: \"list-of-pairs-collection-creator collection-creator flex-row-container\",\n\n /** set up initial options, instance vars, behaviors, and autopair (if set to do so) */\n initialize: function(attributes) {\n this.metric(\"PairedCollectionCreator.initialize\", attributes);\n //this.debug( '-- PairedCollectionCreator:', attributes );\n\n attributes = _.defaults(attributes, {\n datasets: [],\n filters: this.DEFAULT_FILTERS,\n automaticallyPair: true,\n strategy: \"lcs\",\n matchPercentage: 0.9,\n twoPassAutopairing: true\n });\n\n /** unordered, original list */\n this.initialList = attributes.datasets;\n\n /** is this from a history? if so, what's its id? */\n this.historyId = attributes.historyId;\n\n /** which filters should be used initially? (String[2] or name in commonFilters) */\n this.filters = this.commonFilters[attributes.filters] || this.commonFilters[this.DEFAULT_FILTERS];\n if (_.isArray(attributes.filters)) {\n this.filters = attributes.filters;\n }\n\n /** try to auto pair the unpaired datasets on load? */\n this.automaticallyPair = attributes.automaticallyPair;\n\n /** what method to use for auto pairing (will be passed aggression level) */\n this.strategy = this.strategies[attributes.strategy] || this.strategies[this.DEFAULT_STRATEGY];\n if (_.isFunction(attributes.strategy)) {\n this.strategy = attributes.strategy;\n }\n\n /** distance/mismatch level allowed for autopairing */\n this.matchPercentage = attributes.matchPercentage;\n\n /** try to autopair using simple first, then this.strategy on the remainder */\n this.twoPassAutopairing = attributes.twoPassAutopairing;\n\n /** remove file extensions (\\.*) from created pair names? */\n this.removeExtensions = true;\n //this.removeExtensions = false;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.oncancel = attributes.oncancel;\n /** fn to call when the collection is created (scoped to this) */\n this.oncreate = attributes.oncreate;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.autoscrollDist = attributes.autoscrollDist || 24;\n\n /** is the unpaired panel shown? */\n this.unpairedPanelHidden = false;\n /** is the paired panel shown? */\n this.pairedPanelHidden = false;\n\n /** DOM elements currently being dragged */\n this.$dragging = null;\n\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n\n this._setUpCommonSettings(attributes);\n this._setUpBehaviors();\n this._dataSetUp();\n },\n\n /** map of common filter pairs by name */\n commonFilters: {\n illumina: [\"_1\", \"_2\"],\n Rs: [\"_R1\", \"_R2\"]\n },\n /** which commonFilter to use by default */\n DEFAULT_FILTERS: \"illumina\",\n\n /** map of name->fn for autopairing */\n strategies: {\n simple: \"autopairSimple\",\n lcs: \"autopairLCS\",\n levenshtein: \"autopairLevenshtein\"\n },\n /** default autopair strategy name */\n DEFAULT_STRATEGY: \"lcs\",\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data: cache initialList, sort, and autopair */\n _dataSetUp: function() {\n //this.debug( '-- _dataSetUp' );\n\n this.paired = [];\n this.unpaired = [];\n\n this.selectedIds = [];\n\n // sort initial list, add ids if needed, and save new working copy to unpaired\n this._sortInitialList();\n this._ensureIds();\n this.unpaired = this.initialList.slice(0);\n\n if (this.automaticallyPair) {\n this.autoPair();\n this.once(\"rendered:initial\", function() {\n this.trigger(\"autopair\");\n });\n }\n },\n\n /** sort initial list */\n _sortInitialList: function() {\n //this.debug( '-- _sortInitialList' );\n this._sortDatasetList(this.initialList);\n },\n\n /** sort a list of datasets */\n _sortDatasetList: function(list) {\n // currently only natural sort by name\n list.sort((a, b) => naturalSort(a.name, b.name));\n return list;\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureIds: function() {\n this.initialList.forEach(dataset => {\n if (!dataset.hasOwnProperty(\"id\")) {\n dataset.id = _.uniqueId();\n }\n });\n return this.initialList;\n },\n\n /** split initial list into two lists, those that pass forward filters & those passing reverse */\n _splitByFilters: function() {\n var regexFilters = this.filters.map(stringFilter => new RegExp(stringFilter));\n\n var split = [[], []];\n\n function _filter(unpaired, filter) {\n return filter.test(unpaired.name);\n //return dataset.name.indexOf( filter ) >= 0;\n }\n this.unpaired.forEach(function _filterEach(unpaired) {\n // 90% of the time this seems to work, but:\n //TODO: this treats *all* strings as regex which may confuse people - possibly check for // surrounding?\n // would need explanation in help as well\n regexFilters.forEach((filter, i) => {\n if (_filter(unpaired, filter)) {\n split[i].push(unpaired);\n }\n });\n });\n return split;\n },\n\n /** add a dataset to the unpaired list in it's proper order */\n _addToUnpaired: function(dataset) {\n // currently, unpaired is natural sorted by name, use binary search to find insertion point\n var binSearchSortedIndex = (low, hi) => {\n if (low === hi) {\n return low;\n }\n\n var mid = Math.floor((hi - low) / 2) + low;\n\n var compared = naturalSort(dataset.name, this.unpaired[mid].name);\n\n if (compared < 0) {\n return binSearchSortedIndex(low, mid);\n } else if (compared > 0) {\n return binSearchSortedIndex(mid + 1, hi);\n }\n // walk the equal to find the last\n while (this.unpaired[mid] && this.unpaired[mid].name === dataset.name) {\n mid++;\n }\n return mid;\n };\n\n this.unpaired.splice(binSearchSortedIndex(0, this.unpaired.length), 0, dataset);\n },\n\n // ------------------------------------------------------------------------ auto pairing\n /** two passes to automatically create pairs:\n * use both simpleAutoPair, then the fn mentioned in strategy\n */\n autoPair: function(strategy) {\n // split first using exact matching\n var split = this._splitByFilters();\n\n var paired = [];\n if (this.twoPassAutopairing) {\n paired = this.autopairSimple({\n listA: split[0],\n listB: split[1]\n });\n split = this._splitByFilters();\n }\n\n // uncomment to see printlns while running tests\n //this.debug = function(){ console.log.apply( console, arguments ); };\n\n // then try the remainder with something less strict\n strategy = strategy || this.strategy;\n split = this._splitByFilters();\n paired = paired.concat(\n this[strategy].call(this, {\n listA: split[0],\n listB: split[1]\n })\n );\n return paired;\n },\n\n /** autopair by exact match */\n autopairSimple: autoPairFnBuilder({\n scoreThreshold: function() {\n return 0.6;\n },\n match: function _match(params) {\n params = params || {};\n if (params.matchTo === params.possible) {\n return {\n index: params.index,\n score: 1.0\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by levenshtein edit distance scoring */\n autopairLevenshtein: autoPairFnBuilder({\n scoreThreshold: function() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var distance = levenshteinDistance(params.matchTo, params.possible);\n\n var score = 1.0 - distance / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by longest common substrings scoring */\n autopairLCS: autoPairFnBuilder({\n scoreThreshold: function() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var match = this._naiveStartingAndEndingLCS(params.matchTo, params.possible).length;\n\n var score = match / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** return the concat'd longest common prefix and suffix from two strings */\n _naiveStartingAndEndingLCS: function(s1, s2) {\n var fwdLCS = \"\";\n var revLCS = \"\";\n var i = 0;\n var j = 0;\n while (i < s1.length && i < s2.length) {\n if (s1[i] !== s2[i]) {\n break;\n }\n fwdLCS += s1[i];\n i += 1;\n }\n if (i === s1.length) {\n return s1;\n }\n if (i === s2.length) {\n return s2;\n }\n\n i = s1.length - 1;\n j = s2.length - 1;\n while (i >= 0 && j >= 0) {\n if (s1[i] !== s2[j]) {\n break;\n }\n revLCS = [s1[i], revLCS].join(\"\");\n i -= 1;\n j -= 1;\n }\n return fwdLCS + revLCS;\n },\n\n // ------------------------------------------------------------------------ pairing / unpairing\n /** create a pair from fwd and rev, removing them from unpaired, and placing the new pair in paired */\n _pair: function(fwd, rev, options) {\n options = options || {};\n this.debug(\"_pair:\", fwd, rev);\n var pair = this._createPair(fwd, rev, options.name);\n this.paired.push(pair);\n this.unpaired = _.without(this.unpaired, fwd, rev);\n if (!options.silent) {\n this.trigger(\"pair:new\", pair);\n }\n return pair;\n },\n\n /** create a pair Object from fwd and rev, adding the name attribute (will guess if not given) */\n _createPair: function(fwd, rev, name) {\n // ensure existance and don't pair something with itself\n if (!(fwd && rev) || fwd === rev) {\n throw new Error(`Bad pairing: ${[JSON.stringify(fwd), JSON.stringify(rev)]}`);\n }\n name = name || this._guessNameForPair(fwd, rev);\n return { forward: fwd, name: name, reverse: rev };\n },\n\n /** try to find a good pair name for the given fwd and rev datasets */\n _guessNameForPair: function(fwd, rev, removeExtensions) {\n removeExtensions = removeExtensions !== undefined ? removeExtensions : this.removeExtensions;\n var fwdName = fwd.name;\n var revName = rev.name;\n\n var lcs = this._naiveStartingAndEndingLCS(\n fwdName.replace(new RegExp(this.filters[0]), \"\"),\n revName.replace(new RegExp(this.filters[1]), \"\")\n );\n\n if (removeExtensions) {\n var lastDotIndex = lcs.lastIndexOf(\".\");\n if (lastDotIndex > 0) {\n var extension = lcs.slice(lastDotIndex, lcs.length);\n lcs = lcs.replace(extension, \"\");\n fwdName = fwdName.replace(extension, \"\");\n revName = revName.replace(extension, \"\");\n }\n }\n return lcs || `${fwdName} & ${revName}`;\n },\n\n /** unpair a pair, removing it from paired, and adding the fwd,rev datasets back into unpaired */\n _unpair: function(pair, options) {\n options = options || {};\n if (!pair) {\n throw new Error(`Bad pair: ${JSON.stringify(pair)}`);\n }\n this.paired = _.without(this.paired, pair);\n this._addToUnpaired(pair.forward);\n this._addToUnpaired(pair.reverse);\n\n if (!options.silent) {\n this.trigger(\"pair:unpair\", [pair]);\n }\n return pair;\n },\n\n /** unpair all paired datasets */\n unpairAll: function() {\n var pairs = [];\n while (this.paired.length) {\n pairs.push(this._unpair(this.paired[0], { silent: true }));\n }\n this.trigger(\"pair:unpair\", pairs);\n },\n\n // ------------------------------------------------------------------------ API\n /** convert a pair into JSON compatible with the collections API */\n _pairToJSON: function(pair, src) {\n src = src || \"hda\";\n //TODO: consider making this the pair structure when created instead\n return {\n collection_type: \"paired\",\n src: \"new_collection\",\n name: pair.name,\n element_identifiers: [\n {\n name: \"forward\",\n id: pair.forward.id,\n src: src\n },\n {\n name: \"reverse\",\n id: pair.reverse.id,\n src: src\n }\n ]\n };\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function(name) {\n var self = this;\n\n var url = `${Galaxy.root}api/histories/${this.historyId}/contents/dataset_collections`;\n\n //TODO: use ListPairedCollection.create()\n var ajaxData = {\n type: \"dataset_collection\",\n collection_type: \"list:paired\",\n hide_source_items: self.hideOriginals || false,\n name: _.escape(name || self.$(\".collection-name\").val()),\n element_identifiers: self.paired.map(pair => self._pairToJSON(pair))\n };\n //this.debug( JSON.stringify( ajaxData ) );\n self.blocking = true;\n return jQuery\n .ajax(url, {\n type: \"POST\",\n contentType: \"application/json\",\n dataType: \"json\",\n data: JSON.stringify(ajaxData)\n })\n .always(() => {\n self.blocking = false;\n })\n .fail((xhr, status, message) => {\n self._ajaxErrHandler(xhr, status, message);\n })\n .done(function(response, message, xhr) {\n //this.info( 'ok', response, message, xhr );\n self.trigger(\"collection:created\", response, message, xhr);\n self.metric(\"collection:created\", response);\n if (typeof self.oncreate === \"function\") {\n self.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n /** handle ajax errors with feedback and details to the user (if available) */\n _ajaxErrHandler: function(xhr, status, message) {\n this.error(xhr, status, message);\n var self = this;\n var content = _l(\"An error occurred while creating this collection\");\n if (xhr) {\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += `: ${_l(\"Galaxy could not be reached and may be updating.\")}${_l(\n \" Try again in a few minutes.\"\n )}`;\n } else if (xhr.responseJSON) {\n content += `
${JSON.stringify(xhr.responseJSON)}
`;\n } else {\n content += `: ${message}`;\n }\n }\n self._showAlert(content, \"alert-danger\");\n },\n\n // ------------------------------------------------------------------------ rendering\n /** render the entire interface */\n render: function(speed, callback) {\n //this.debug( '-- _render' );\n //this.$el.empty().html( this.templates.main() );\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function(speed, callback) {\n //this.debug( '-- _renderHeader' );\n var $header = this.$(\".header\")\n .empty()\n .html(this.templates.header())\n .find(\".help-content\")\n .prepend($(this.templates.helpContent()));\n\n this._renderFilters();\n return $header;\n },\n /** fill the filter inputs with the filter values */\n _renderFilters: function() {\n return this.$(\".forward-column .column-header input\")\n .val(this.filters[0])\n .add(this.$(\".reverse-column .column-header input\").val(this.filters[1]));\n },\n\n /** render the middle including unpaired and paired sections (which may be hidden) */\n _renderMiddle: function(speed, callback) {\n var $middle = this.$(\".middle\")\n .empty()\n .html(this.templates.middle());\n\n // (re-) hide the un/paired panels based on instance vars\n if (this.unpairedPanelHidden) {\n this.$(\".unpaired-columns\").hide();\n } else if (this.pairedPanelHidden) {\n this.$(\".paired-columns\").hide();\n }\n\n this._renderUnpaired();\n this._renderPaired();\n return $middle;\n },\n /** render the unpaired section, showing datasets accrd. to filters, update the unpaired counts */\n _renderUnpaired: function(speed, callback) {\n //this.debug( '-- _renderUnpaired' );\n var self = this;\n\n var $fwd;\n var $rev;\n var $prd = [];\n var split = this._splitByFilters();\n // update unpaired counts\n this.$(\".forward-column .title\").text([split[0].length, _l(\"unpaired forward\")].join(\" \"));\n this.$(\".forward-column .unpaired-info\").text(\n this._renderUnpairedDisplayStr(this.unpaired.length - split[0].length)\n );\n this.$(\".reverse-column .title\").text([split[1].length, _l(\"unpaired reverse\")].join(\" \"));\n this.$(\".reverse-column .unpaired-info\").text(\n this._renderUnpairedDisplayStr(this.unpaired.length - split[1].length)\n );\n\n this.$(\".unpaired-columns .column-datasets\").empty();\n\n // show/hide the auto pair button if any unpaired are left\n this.$(\".autopair-link\").toggle(this.unpaired.length !== 0);\n if (this.unpaired.length === 0) {\n this._renderUnpairedEmpty();\n return;\n }\n\n // create the dataset dom arrays\n $rev = split[1].map((dataset, i) => {\n // if there'll be a fwd dataset across the way, add a button to pair the row\n if (split[0][i] !== undefined && split[0][i] !== dataset) {\n $prd.push(self._renderPairButton());\n }\n return self._renderUnpairedDataset(dataset);\n });\n $fwd = split[0].map(dataset => self._renderUnpairedDataset(dataset));\n\n if (!$fwd.length && !$rev.length) {\n this._renderUnpairedNotShown();\n return;\n }\n // add to appropo cols\n //TODO: not the best way to render - consider rendering the entire unpaired-columns section in a fragment\n // and swapping out that\n this.$(\".unpaired-columns .forward-column .column-datasets\")\n .append($fwd)\n .add(this.$(\".unpaired-columns .paired-column .column-datasets\").append($prd))\n .add(this.$(\".unpaired-columns .reverse-column .column-datasets\").append($rev));\n this._adjUnpairedOnScrollbar();\n },\n /** return a string to display the count of filtered out datasets */\n _renderUnpairedDisplayStr: function(numFiltered) {\n return [\"(\", numFiltered, \" \", _l(\"filtered out\"), \")\"].join(\"\");\n },\n /** return an unattached jQuery DOM element to represent an unpaired dataset */\n _renderUnpairedDataset: function(dataset) {\n //TODO: to underscore template\n return (\n $(\"\")\n .attr(\"id\", `dataset-${dataset.id}`)\n .addClass(\"dataset unpaired\")\n .attr(\"draggable\", true)\n .addClass(dataset.selected ? \"selected\" : \"\")\n .append(\n $(\"\")\n .addClass(\"dataset-name\")\n .text(dataset.name)\n )\n //??\n .data(\"dataset\", dataset)\n );\n },\n /** render the button that may go between unpaired datasets, allowing the user to pair a row */\n _renderPairButton: function() {\n //TODO: *not* a dataset - don't pretend like it is\n return $(\"\")\n .addClass(\"dataset unpaired\")\n .append(\n $(\"\")\n .addClass(\"dataset-name\")\n .text(_l(\"Pair these datasets\"))\n );\n },\n /** a message to display when no unpaired left */\n _renderUnpairedEmpty: function() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(`(${_l(\"no remaining unpaired datasets\")})`);\n this.$(\".unpaired-columns .paired-column .column-datasets\")\n .empty()\n .prepend($msg);\n return $msg;\n },\n /** a message to display when no unpaired can be shown with the current filters */\n _renderUnpairedNotShown: function() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(\n `(${_l(\"no datasets were found matching the current filters\")})`\n );\n this.$(\".unpaired-columns .paired-column .column-datasets\")\n .empty()\n .prepend($msg);\n return $msg;\n },\n /** try to detect if the unpaired section has a scrollbar and adjust left column for better centering of all */\n _adjUnpairedOnScrollbar: function() {\n var $unpairedColumns = this.$(\".unpaired-columns\").last();\n\n var $firstDataset = this.$(\".unpaired-columns .reverse-column .dataset\").first();\n\n if (!$firstDataset.length) {\n return;\n }\n\n var ucRight = $unpairedColumns.offset().left + $unpairedColumns.outerWidth();\n\n var dsRight = $firstDataset.offset().left + $firstDataset.outerWidth();\n\n var rightDiff = Math.floor(ucRight) - Math.floor(dsRight);\n //this.debug( 'rightDiff:', ucRight, '-', dsRight, '=', rightDiff );\n this.$(\".unpaired-columns .forward-column\").css(\"margin-left\", rightDiff > 0 ? rightDiff : 0);\n },\n\n /** render the paired section and update counts of paired datasets */\n _renderPaired: function(speed, callback) {\n //this.debug( '-- _renderPaired' );\n this.$(\".paired-column-title .title\").text([this.paired.length, _l(\"paired\")].join(\" \"));\n // show/hide the unpair all link\n this.$(\".unpair-all-link\").toggle(this.paired.length !== 0);\n if (this.paired.length === 0) {\n this._renderPairedEmpty();\n return;\n //TODO: would be best to return here (the $columns)\n } else {\n // show/hide 'remove extensions link' when any paired and they seem to have extensions\n this.$(\".remove-extensions-link\").show();\n }\n\n this.$(\".paired-columns .column-datasets\").empty();\n var self = this;\n this.paired.forEach((pair, i) => {\n //TODO: cache these?\n var pairView = new PairView({ pair: pair });\n self\n .$(\".paired-columns .column-datasets\")\n .append(pairView.render().$el)\n .append(\n [\n '\"\n ].join(\"\")\n );\n });\n },\n /** a message to display when none paired */\n _renderPairedEmpty: function() {\n var $msg = $('').text(`(${_l(\"no paired datasets yet\")})`);\n this.$(\".paired-columns .column-datasets\")\n .empty()\n .prepend($msg);\n return $msg;\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\",\n \".remove-extensions\": \"removeExtensions\"\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function() {\n this._chooseFiltersPopover(\".choose-filters-link\");\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", \"rgba( 64, 255, 255, 1.0 )\");\n },\n\n /** build a filter selection popover allowing selection of common filter pairs */\n _chooseFiltersPopover: function(selector) {\n function filterChoice(val1, val2) {\n return [\n '\"\n ].join(\"\");\n }\n var $popoverContent = $(\n _.template(\n [\n '
',\n '
',\n _l(\"Choose from the following filters to change which unpaired reads are shown in the display\"),\n \":
\"\n ].join(\"\")\n ),\n\n /** the middle: unpaired, divider, and paired */\n middle: _.template(\n [\n // contains two flex rows (rows that fill available space) and a divider btwn\n '
\",\n _l(\n [\n \"Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). \",\n \"These collections can be passed to tools and workflows in order to have analyses done on each member of \",\n \"the entire group. This interface allows you to create a collection, choose which datasets are paired, \",\n \"and re-order the final collection.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'Unpaired datasets are shown in the unpaired section ',\n \"(hover over the underlined words to highlight below). \",\n 'Paired datasets are shown in the paired section.',\n \"
To pair datasets, you can:\",\n \"
Click a dataset in the \",\n 'forward column ',\n \"to select it then click a dataset in the \",\n 'reverse column.',\n \"
\",\n '
Click one of the \"Pair these datasets\" buttons in the ',\n 'middle column ',\n \"to pair the datasets in a particular row.\",\n \"
\",\n '
Click \"Auto-pair\" ',\n \"to have your datasets automatically paired based on name.\",\n \"
\",\n \"
\"\n ].join(\"\")\n ),\n \"\",\n \"
\",\n _l(\n [\n \"
You can filter what is shown in the unpaired sections by:\",\n \"
Entering partial dataset names in either the \",\n 'forward filter or ',\n 'reverse filter.',\n \"
\",\n \"
Choosing from a list of preset filters by clicking the \",\n '\"Choose filters\" link.',\n \"
Clearing the filters by clicking the \",\n '\"Clear filters\" link.',\n \"
\",\n \"
\"\n ].join(\"\")\n ),\n \"\",\n \"
\",\n _l(\n [\n \"To unpair individual dataset pairs, click the \",\n 'unpair buttons ( ). ',\n 'Click the \"Unpair all\" link to unpair all pairs.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'You can include or remove the file extensions (e.g. \".fastq\") from your pair names by toggling the ',\n '\"Remove file extensions from pair names?\" control.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'Once your collection is complete, enter a name and ',\n 'click \"Create list\". ',\n \"(Note: you do not have to pair all unpaired datasets to finish.)\"\n ].join(\"\")\n ),\n \"
\"\n ].join(\"\")\n )\n })\n });\n\n//=============================================================================\n/** a modal version of the paired collection creator */\nvar pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(datasets, options) {\n var deferred = jQuery.Deferred();\n var creator;\n\n options = _.defaults(options || {}, {\n datasets: datasets,\n oncancel: function() {\n Galaxy.modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function(creator, response) {\n Galaxy.modal.hide();\n deferred.resolve(response);\n }\n });\n\n if (!window.Galaxy || !Galaxy.modal) {\n throw new Error(\"Galaxy or Galaxy.modal not found\");\n }\n\n creator = new PairedCollectionCreator(options);\n Galaxy.modal.show({\n title: \"Create a collection of paired datasets\",\n body: creator.$el,\n width: \"80%\",\n height: \"800px\",\n closing_events: true\n });\n creator.render();\n window.creator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n//=============================================================================\nfunction createListOfPairsCollection(collection, defaultHideSourceItems) {\n var elements = collection.toJSON();\n //TODO: validate elements\n return pairedCollectionCreatorModal(elements, {\n historyId: collection.historyId,\n defaultHideSourceItems: defaultHideSourceItems\n });\n}\n\n//=============================================================================\nexport default {\n PairedCollectionCreator: PairedCollectionCreator,\n pairedCollectionCreatorModal: pairedCollectionCreatorModal,\n createListOfPairsCollection: createListOfPairsCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js","//=============================================================================\n/**\n(Imported for edit distance algorith. From: https://gist.github.com/andrei-m/982927)\nCopyright (c) 2011 Andrei Mackenzie\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the\nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n// Compute the edit distance between the two given strings\n//exports.getEditDistance = function(a, b){\nfunction levenshteinDistance(a, b) {\n if (a.length === 0) {\n return b.length;\n }\n if (b.length === 0) {\n return a.length;\n }\n\n var matrix = [];\n\n // increment along the first column of each row\n var i;\n for (i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n\n // increment each column in the first row\n var j;\n for (j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n\n // Fill in the rest of the matrix\n for (i = 1; i <= b.length; i++) {\n for (j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1, // substitution\n Math.min(\n matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j] + 1\n )\n ); // deletion\n }\n }\n }\n\n //console.debug( '\\t\\t levenshteinDistance', a, b, matrix[b.length][a.length] );\n return matrix[b.length][a.length];\n}\n\n//=============================================================================\nexport default levenshteinDistance;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/levenshtein.js","/** User Preferences view */\nimport Form from \"mvc/form/form-view\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport QueryStringParsing from \"utils/query-string-parsing\";\n/** Contains descriptive dictionaries describing user forms */\nvar Model = Backbone.Model.extend({\n initialize: function(options) {\n options = options || {};\n options.user_id = options.user_id || Galaxy.user.id;\n this.set({\n user_id: options.user_id,\n information: {\n title: \"Manage information\",\n description: \"Edit your email, addresses and custom parameters or change your username.\",\n url: `api/users/${options.user_id}/information/inputs`,\n icon: \"fa-user\",\n redirect: \"user\"\n },\n password: {\n title: \"Change password\",\n description: \"Allows you to change your login credentials.\",\n icon: \"fa-unlock-alt\",\n url: `api/users/${options.user_id}/password/inputs`,\n submit_title: \"Save password\",\n redirect: \"user\"\n },\n communication: {\n title: \"Change communication settings\",\n description: \"Enable or disable the communication feature to chat with other users.\",\n url: `api/users/${options.user_id}/communication/inputs`,\n icon: \"fa-comments-o\",\n redirect: \"user\"\n },\n permissions: {\n title: \"Set dataset permissions for new histories\",\n description:\n \"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.\",\n url: `api/users/${options.user_id}/permissions/inputs`,\n icon: \"fa-users\",\n submit_title: \"Save permissions\",\n redirect: \"user\"\n },\n api_key: {\n title: \"Manage API key\",\n description: \"Access your current API key or create a new one.\",\n url: `api/users/${options.user_id}/api_key/inputs`,\n icon: \"fa-key\",\n submit_title: \"Create a new key\",\n submit_icon: \"fa-check\"\n },\n toolbox_filters: {\n title: \"Manage Toolbox filters\",\n description: \"Customize your Toolbox by displaying or omitting sets of Tools.\",\n url: `api/users/${options.user_id}/toolbox_filters/inputs`,\n icon: \"fa-filter\",\n submit_title: \"Save filters\",\n redirect: \"user\"\n },\n openids: {\n title: \"Manage OpenIDs\",\n description: \"Associate OpenIDs with your account.\",\n icon: \"fa-openid\",\n onclick: function() {\n window.location.href = `${Galaxy.root}user/openid_manage?cntrller=user&use_panels=True`;\n }\n },\n custom_builds: {\n title: \"Manage custom builds\",\n description: \"Add or remove custom builds using history datasets.\",\n icon: \"fa-cubes\",\n onclick: function() {\n window.location.href = `${Galaxy.root}custom_builds`;\n }\n },\n logout: {\n title: \"Sign out\",\n description: \"Click here to sign out of all sessions.\",\n icon: \"fa-sign-out\",\n onclick: function() {\n Galaxy.modal.show({\n title: \"Sign out\",\n body: \"Do you want to continue and sign out of all active sessions?\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n },\n \"Sign out\": function() {\n window.location.href = `${Galaxy.root}user/logout?session_csrf_token=${\n Galaxy.session_csrf_token\n }`;\n }\n }\n });\n }\n }\n });\n }\n});\n\n/** View of the main user preference panel with links to individual user forms */\nvar View = Backbone.View.extend({\n title: \"User Preferences\",\n initialize: function() {\n this.model = new Model();\n this.setElement(\"\");\n this.render();\n },\n\n render: function() {\n var self = this;\n var config = Galaxy.config;\n $.getJSON(`${Galaxy.root}api/users/${Galaxy.user.id}`, data => {\n self.$preferences = $(\"\")\n .addClass(\"ui-panel\")\n .append($(\"\").append(\"User preferences\"))\n .append($(\"\").append(`You are logged in as ${_.escape(data.email)}.`))\n .append((self.$table = $(\"
\").addClass(\"ui-panel-table\")));\n var message = QueryStringParsing.get(\"message\");\n var status = QueryStringParsing.get(\"status\");\n if (message && status) {\n self.$preferences.prepend(new Ui.Message({ message: message, status: status }).$el);\n }\n if (!config.use_remote_user) {\n self._addLink(\"information\");\n self._addLink(\"password\");\n }\n if (config.enable_communication_server) {\n self._addLink(\"communication\");\n }\n self._addLink(\"custom_builds\");\n self._addLink(\"permissions\");\n self._addLink(\"api_key\");\n if (config.has_user_tool_filters) {\n self._addLink(\"toolbox_filters\");\n }\n if (config.enable_openid && !config.use_remote_user) {\n self._addLink(\"openids\");\n }\n if (Galaxy.session_csrf_token) {\n self._addLink(\"logout\");\n }\n self.$preferences.append(self._templateFooter(data));\n self.$el.empty().append(self.$preferences);\n });\n },\n\n _addLink: function(action) {\n var options = this.model.get(action);\n var $row = $(this._templateLink(options));\n var $a = $row.find(\"a\");\n if (options.onclick) {\n $a.on(\"click\", () => {\n options.onclick();\n });\n } else {\n $a.attr(\"href\", `${Galaxy.root}user/${action}`);\n }\n this.$table.append($row);\n },\n\n _templateLink: function(options) {\n return `
You are using ${\n options.nice_total_disk_usage\n } of disk space in this Galaxy instance. ${\n Galaxy.config.enable_quotas ? `Your disk quota is: ${options.quota}. ` : \"\"\n }Is your usage more than expected? See the documentation for tips on how to find all of the data in your account.
`;\n }\n});\n\nexport default {\n View: View,\n Model: Model\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/user/user-preferences.js","/** This class renders the chart configuration form. */\nimport Utils from \"utils/utils\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\nimport Table from \"mvc/ui/ui-table\";\nvar Collection = Backbone.Collection.extend({\n comparator: function(a, b) {\n a = a.get(\"name\");\n b = b.get(\"name\");\n return a > b ? 1 : a < b ? -1 : 0;\n }\n});\n\nvar View = Backbone.View.extend({\n initialize: function(options) {\n var self = this;\n var history_id = Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.model.id;\n this.model = new Backbone.Model();\n this.model.url = `${Galaxy.root}api/histories/${history_id}/custom_builds_metadata`;\n this.collection = new Collection();\n this.collection.url = `${Galaxy.root}api/users/${Galaxy.user.id}/custom_builds`;\n this.message = new Ui.Message({});\n this.installed_builds = new Ui.Select.View({\n optional: true,\n onchange: function() {\n self.installed_builds.value(null);\n },\n empty_text: \"List of available builds:\",\n error_text: \"No system installed builds available.\"\n });\n this.table = new Table.View({ cls: \"grid\", selectable: false });\n this.table.addHeader(\"Name\");\n this.table.addHeader(\"Key\");\n this.table.addHeader(\"Number of chroms/contigs\");\n this.table.addHeader(\"\");\n this.table.appendHeader();\n this.setElement(\n $(\"\")\n .append($(\"\").text(\"Current Custom Builds\"))\n .append(this.table.$el)\n .append(\n (this.$installed = $(\"\")\n .append(\n $(\"\")\n .text(\"System Installed Builds\")\n .addClass(\"ui-margin-top\")\n )\n .append(this.installed_builds.$el))\n )\n .append(\n $(\"\")\n .text(\"Add a Custom Build\")\n .addClass(\"ui-margin-top\")\n )\n .append(\n $(\"\")\n .addClass(\"ui-column\")\n .append(\n $(\"\")\n .addClass(\"ui-column-left\")\n .append(this.message.$el)\n .append((this.$form = $(\"\").addClass(\"ui-margin-top\")))\n )\n .append((this.$help = $(\"\").addClass(\"ui-column-right\")))\n )\n );\n this.listenTo(this.collection, \"add remove reset\", () => {\n self._renderTable();\n });\n this.listenTo(this.model, \"change\", () => {\n self._renderForm();\n });\n this.collection.fetch();\n this.model.fetch();\n },\n\n render: function() {\n this._renderTable();\n this._renderForm();\n },\n\n _renderTable: function() {\n var self = this;\n this.table.delAll();\n this.collection.sort();\n this.collection.each(model => {\n self.table.add(model.get(\"name\"));\n self.table.add(model.id);\n self.table.add(model.get(\"count\") !== undefined ? model.get(\"count\") : \"Processing...\");\n self.table.add(\n new Ui.ButtonIcon({\n icon: \"fa-trash-o\",\n cls: \"ui-button-icon-plain\",\n tooltip: \"Delete custom build.\",\n onclick: function() {\n model.destroy();\n }\n }).$el\n );\n self.table.append(model.id);\n });\n },\n\n _renderForm: function() {\n var self = this;\n var initial_type = \"fasta\";\n var form = new Form({\n inputs: [\n {\n type: \"text\",\n name: \"name\",\n label: \"Name\",\n help: \"Specify a build name e.g. Hamster.\"\n },\n {\n type: \"text\",\n name: \"id\",\n label: \"Key\",\n help: \"Specify a build key e.g. hamster_v1.\"\n },\n {\n name: \"len\",\n type: \"conditional\",\n test_param: {\n name: \"type\",\n label: \"Definition\",\n help: \"Provide the data source.\",\n type: \"select\",\n value: initial_type,\n data: [\n {\n value: \"fasta\",\n label: \"FASTA-file from history\"\n },\n {\n value: \"file\",\n label: \"Len-file from disk\"\n },\n {\n value: \"text\",\n label: \"Len-file by copy/paste\"\n }\n ]\n },\n cases: [\n {\n value: \"fasta\",\n inputs: [\n {\n type: \"select\",\n name: \"value\",\n label: \"FASTA-file\",\n data: this.model.get(\"fasta_hdas\")\n }\n ]\n },\n {\n value: \"file\",\n inputs: [\n {\n type: \"upload\",\n name: \"value\",\n label: \"Len-file\",\n data: this.model.get(\"len_hdas\")\n }\n ]\n },\n {\n value: \"text\",\n inputs: [\n {\n type: \"text\",\n area: true,\n name: \"value\",\n label: \"Edit/Paste\"\n }\n ]\n }\n ]\n }\n ],\n buttons: {\n save: new Ui.Button({\n icon: \"fa-save\",\n tooltip: \"Create new Build\",\n title: \"Save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function() {\n var data = form.data.create();\n if (!data.id || !data.name) {\n self.message.update({\n message: \"All inputs are required.\",\n status: \"danger\"\n });\n } else {\n self.collection.create(data, {\n wait: true,\n success: function(response) {\n if (response.get(\"message\")) {\n self.message.update({\n message: response.get(\"message\"),\n status: \"warning\"\n });\n } else {\n self.message.update({\n message: \"Successfully added a new custom build.\",\n status: \"success\"\n });\n }\n },\n error: function(response, err) {\n var message = err && err.responseJSON && err.responseJSON.err_msg;\n self.message.update({\n message: message || \"Failed to create custom build.\",\n status: \"danger\"\n });\n }\n });\n }\n }\n })\n },\n onchange: function() {\n var input_id = form.data.match(\"len|type\");\n if (input_id) {\n var input_field = form.field_list[input_id];\n self._renderHelp(input_field.value());\n }\n }\n });\n this.$form.empty().append(form.$el);\n var installed_builds = this.model.get(\"installed_builds\");\n if (installed_builds && installed_builds.length) {\n this.$installed.show();\n this.installed_builds.update(this.model.get(\"installed_builds\"));\n } else {\n this.$installed.hide();\n }\n this._renderHelp(initial_type);\n },\n\n _renderHelp: function(len_type) {\n this.$help\n .empty()\n .addClass(\"alert alert-info\")\n .html(len_type == \"fasta\" ? this._templateFasta() : this._templateLen());\n },\n\n _templateLen: function() {\n return (\n \"
Length Format
\" +\n \"
\" +\n \"The length format is two-column, separated by whitespace, of the form:\" +\n \"
chrom/contig length of chrom/contig
\" +\n \"\" +\n \"
\" +\n \"For example, the first few entries of mm9.len are as follows:\" +\n \"
Trackster uses this information to populate the select box for chrom/contig, and\" +\n \"to set the maximum basepair of the track browser. You may either upload a .len file\" +\n \"of this format (Len File option), or directly enter the information into the box \" +\n \"(Len Entry option).
\" +\n \"This is a multi-fasta file from your current history that provides the genome\" +\n \"sequences for each chromosome/contig in your build.\" +\n \"
\" +\n \"
\" +\n \"Here is a snippet from an example multi-fasta file:\" +\n \"
`\n );\n });\n $tmpl.append($table);\n } else {\n $tmpl.append(`No ${this.model.get(\"plural\").toLowerCase()} have been shared with you.`);\n }\n return $tmpl;\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/grid/grid-shared.js","/** Workflow view */\nimport * as mod_toastr from \"libs/toastr\";\nimport TAGS from \"mvc/tag\";\nimport WORKFLOWS from \"mvc/workflow/workflow-model\";\nimport QueryStringParsing from \"utils/query-string-parsing\";\n/** View of the individual workflows */\nvar WorkflowItemView = Backbone.View.extend({\n tagName: \"tr\", // name of (orphan) root tag in this.el\n initialize: function() {\n _.bindAll(\n this,\n \"render\",\n \"_rowTemplate\",\n \"renderTagEditor\",\n \"_templateActions\",\n \"removeWorkflow\",\n \"copyWorkflow\"\n ); // every function that uses 'this' as the current object should be in here\n mod_toastr.options.timeOut = 1500;\n },\n\n events: {\n \"click #show-in-tool-panel\": \"showInToolPanel\",\n \"click #delete-workflow\": \"removeWorkflow\",\n \"click #rename-workflow\": \"renameWorkflow\",\n \"click #copy-workflow\": \"copyWorkflow\"\n },\n\n render: function() {\n $(this.el).html(this._rowTemplate());\n return this;\n },\n\n showInToolPanel: function() {\n this.model.set(\"show_in_tool_panel\", !this.model.get(\"show_in_tool_panel\"));\n this.model.save();\n // This reloads the whole page, so that the workflow appears in the tool panel.\n // Ideally we would notify only the tool panel of a change\n window.location = `${Galaxy.root}workflow`;\n },\n\n removeWorkflow: function() {\n var wfName = this.model.get(\"name\");\n if (window.confirm(`Are you sure you want to delete workflow '${wfName}'?`)) {\n this.model.destroy({\n success: function() {\n mod_toastr.success(`Successfully deleted workflow '${wfName}'`);\n }\n });\n this.remove();\n }\n },\n\n renameWorkflow: function() {\n var oldName = this.model.get(\"name\");\n var newName = window.prompt(`Enter a new Name for workflow '${oldName}'`, oldName);\n if (newName) {\n this.model.save(\n { name: newName },\n {\n success: function() {\n mod_toastr.success(`Successfully renamed workflow '${oldName}' to '${newName}'`);\n }\n }\n );\n this.render();\n }\n },\n\n copyWorkflow: function() {\n var self = this;\n var oldName = this.model.get(\"name\");\n $.getJSON(`${this.model.urlRoot}/${this.model.id}/download`, wfJson => {\n var newName = `Copy of ${oldName}`;\n var currentOwner = self.model.get(\"owner\");\n if (currentOwner != Galaxy.user.attributes.username) {\n newName += ` shared by user ${currentOwner}`;\n }\n wfJson.name = newName;\n self.collection.create(wfJson, {\n at: 0,\n wait: true,\n success: function() {\n mod_toastr.success(`Successfully copied workflow '${oldName}' to '${newName}'`);\n },\n error: function(model, resp, options) {\n // signature seems to have changed over the course of backbone dev\n // see https://github.com/jashkenas/backbone/issues/2606#issuecomment-19289483\n mod_toastr.error(options.errorThrown);\n }\n });\n }).error((jqXHR, textStatus, errorThrown) => {\n mod_toastr.error(jqXHR.responseJSON.err_msg);\n });\n },\n\n _rowTemplate: function() {\n var show = this.model.get(\"show_in_tool_panel\");\n var wfId = this.model.id;\n var checkboxHtml = ``;\n var trHtml = `
Click the link above to visit myExperiment and browse for Galaxy workflows.
`;\n }\n});\n\nexport default {\n View: WorkflowListView,\n ImportWorkflowView: ImportWorkflowView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/workflow/workflow.js","import baseMVC from \"mvc/base-mvc\";\n/* global Backbone */\n// workflow model\n\nvar logNamespace = \"workflow\";\n//==============================================================================\n/** @class model for a single workflow.\n * @name WorkflowItem\n * @augments Backbone.Model\n */\nvar WorkflowItem = Backbone.Model.extend(baseMVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n urlRoot: `${Galaxy.root}api/workflows`,\n\n toJSON: function() {\n // need to overwrite this as endpoint expects the 'workflow' key in payload\n return { workflow: this.attributes };\n }\n});\n\n//==============================================================================\n/** @class collection for workflows.\n * @name WorkflowCollection\n * @augments Backbone.Collection\n */\nvar WorkflowCollection = Backbone.Collection.extend({\n model: WorkflowItem,\n url: `${Galaxy.root}api/workflows`\n});\n\n//==============================================================================\n\nexport default {\n WorkflowItem: WorkflowItem,\n WorkflowCollection: WorkflowCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/workflow/workflow-model.js","/** This class renders the grid list. */\nimport Utils from \"utils/utils\";\nimport GridView from \"mvc/grid/grid-view\";\nimport HistoryModel from \"mvc/history/history-model\";\nimport historyCopyDialog from \"mvc/history/copy-dialog\";\nvar View = Backbone.View.extend({\n title: \"Histories\",\n initialize: function(options) {\n var self = this;\n this.setElement($(\"\"));\n this.model = new Backbone.Model();\n Utils.get({\n url: `${Galaxy.root}history/${options.action_id}?${$.param(Galaxy.params)}`,\n success: function(response) {\n response[\"dict_format\"] = true;\n _.each(response[\"operations\"], operation => {\n if (operation.label == \"Copy\") {\n operation.onclick = id => {\n self._showCopyDialog(id);\n };\n }\n });\n self.model.set(response);\n self.render();\n }\n });\n },\n\n render: function() {\n var grid = new GridView(this.model.attributes);\n this.$el.empty().append(grid.$el);\n },\n\n _showCopyDialog: function(id) {\n var history = new HistoryModel.History({ id: id });\n history\n .fetch()\n .fail(() => {\n alert(\"History could not be fetched. Please contact an administrator\");\n })\n .done(() => {\n historyCopyDialog(history, {}).done(() => {\n if (window.parent && window.parent.Galaxy && window.parent.Galaxy.currHistoryPanel) {\n window.parent.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n window.location.reload(true);\n });\n });\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-list.js","import Utils from \"utils/utils\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\n/** Dataset edit attributes view */\nvar View = Backbone.View.extend({\n initialize: function() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.render();\n },\n\n // Fetch data for the selected dataset and\n render: function() {\n var data_url = `${Galaxy.root}api/datasets/${this.model.get(\"dataset_id\")}`;\n\n var self = this;\n\n Utils.get({\n url: data_url,\n success: function(dataset) {\n var job_url = `${Galaxy.root}api/jobs/${dataset.creating_job}?full=True`;\n Utils.get({\n url: job_url,\n success: function(job) {\n var job_url = `${Galaxy.root}api/jobs/${dataset.creating_job}?full=True`;\n self.render_error_page(self, dataset, job);\n },\n error: function(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the job.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n error: function(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the dataset.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n\n /** Render the view */\n render_error_page: function(self, dataset, job) {\n self.$el.empty().append(self._templateHeader());\n self.$el.append(\"
Dataset Error
\");\n self.$el.append(`
An error occured while running the tool ${job.tool_id}.
`);\n self.$el.append(\"
Tool execution generated the following messages:
\");\n self.$el.append(`
${job.stderr}
`);\n self.$el.append(\"
Report This Error\");\n self.$el.append(\n \"
Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.
\";\n },\n\n /** Convert tab template */\n _getBugFormTemplate: function(dataset, job) {\n var self = this;\n var inputs = [\n {\n help: \"Your email address\",\n options: [],\n type: \"text\",\n name: \"email\",\n label: \"Your email\",\n value: Galaxy.user.get(\"email\")\n },\n {\n help: \"Any additional comments you can provide regarding what you were doing at the time of the bug.\",\n options: [],\n type: \"text\",\n area: true,\n name: \"message\",\n label: \"Message\"\n }\n ];\n\n // TODO\n /*\n if (false && response.any_public) {\n inputs.push({\n name: \"public_consent\",\n label: \"Public Disclosure Consent\",\n help:\n \"This Galaxy is configured to report to one or more error reporting backends that public to the world. By selecting 'yes', you acknowledge that this bug report will be made public.\",\n value: String(Boolean(false)),\n options: [],\n type: \"boolean\"\n });\n }\n */\n\n var form = new Form({\n title: \"Error Report\",\n inputs: inputs,\n buttons: {\n save: new Ui.Button({\n icon: \"fa-bug\",\n title: \"Report\",\n cls: \"ui-button btn btn-primary\",\n floating: \"clear\",\n onclick: function() {\n var form_data = form.data.create();\n var url = `${Galaxy.root}api/jobs/${job.id}/error`;\n form_data.dataset_id = dataset.id;\n self.submit(form_data, url);\n }\n })\n }\n });\n return form.$el;\n },\n\n /** Make ajax request */\n submit: function(form_data, url) {\n var self = this;\n // Some required metadata\n $.ajax({\n type: \"POST\",\n url: url,\n data: form_data,\n success: function(response) {\n // Clear out the div\n self.$el.empty().append(self._templateHeader());\n // And display the messages.\n response.messages.forEach(message => {\n self.display_message(\n {\n status: message[1],\n message: message[0],\n persistent: true\n },\n self.$(\".response-message\"),\n true,\n true\n );\n });\n },\n error: function(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while saving. Please fill all the required fields and try again.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/dataset-error.js","/** Dataset edit attributes view */\nimport Utils from \"utils/utils\";\nimport Tabs from \"mvc/ui/ui-tabs\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\nvar View = Backbone.View.extend({\n initialize: function() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.message = new Ui.Message({ persistent: true });\n this.tabs = this._createTabs();\n this.$el\n .append($(\"\").append(\"Edit dataset attributes\"))\n .append(this.message.$el)\n .append(\"\")\n .append(this.tabs.$el)\n .hide();\n this.render();\n },\n\n /** fetch data for the selected dataset and build forms */\n render: function() {\n var self = this;\n $.ajax({\n url: `${Galaxy.root}dataset/get_edit?dataset_id=${self.model.get(\"dataset_id\")}`,\n success: function(response) {\n !self.initial_message && self.message.update(response);\n self.initial_message = true;\n _.each(self.forms, (form, key) => {\n form.model.set(\"inputs\", response[`${key}_inputs`]);\n form.model.set(\"hide_operations\", response[`${key}_disable`]);\n form.render();\n });\n self.$el.show();\n },\n error: function(response) {\n var err_msg = response.responseJSON && response.responseJSON.err_msg;\n self.message.update({\n status: \"danger\",\n message: err_msg || \"Error occured while loading the dataset.\"\n });\n }\n });\n },\n\n /** submit data to backend to update attributes */\n _submit: function(operation, form) {\n var self = this;\n var data = form.data.create();\n data.dataset_id = this.model.get(\"dataset_id\");\n data.operation = operation;\n $.ajax({\n type: \"PUT\",\n url: `${Galaxy.root}dataset/set_edit`,\n data: data,\n success: function(response) {\n self.message.update(response);\n self.render();\n self._reloadHistory();\n },\n error: function(response) {\n var err_msg = response.responseJSON && response.responseJSON.err_msg;\n self.message.update({\n status: \"danger\",\n message: err_msg || \"Error occured while editing the dataset attributes.\"\n });\n }\n });\n },\n\n /** create tabs for different dataset attribute categories*/\n _createTabs: function() {\n this.forms = {\n attribute: this._getAttribute(),\n conversion: this._getConversion(),\n datatype: this._getDatatype(),\n permission: this._getPermission()\n };\n var tabs = new Tabs.View();\n tabs.add({\n id: \"attribute\",\n title: \"Attributes\",\n icon: \"fa fa-bars\",\n tooltip: \"Edit dataset attributes\",\n $el: this.forms.attribute.$el\n });\n tabs.add({\n id: \"convert\",\n title: \"Convert\",\n icon: \"fa-gear\",\n tooltip: \"Convert to new format\",\n $el: this.forms.conversion.$el\n });\n tabs.add({\n id: \"datatype\",\n title: \"Datatypes\",\n icon: \"fa-database\",\n tooltip: \"Change data type\",\n $el: this.forms.datatype.$el\n });\n tabs.add({\n id: \"permissions\",\n title: \"Permissions\",\n icon: \"fa-user\",\n tooltip: \"Permissions\",\n $el: this.forms.permission.$el\n });\n return tabs;\n },\n\n /** edit main attributes form */\n _getAttribute: function() {\n var self = this;\n var form = new Form({\n title: \"Edit attributes\",\n operations: {\n submit_attributes: new Ui.ButtonIcon({\n tooltip: \"Save attributes of the dataset.\",\n icon: \"fa-floppy-o\",\n title: \"Save\",\n onclick: function() {\n self._submit(\"attributes\", form);\n }\n }),\n submit_autodetect: new Ui.ButtonIcon({\n tooltip:\n \"This will inspect the dataset and attempt to correct the values of fields if they are not accurate.\",\n icon: \"fa-undo\",\n title: \"Auto-detect\",\n onclick: function() {\n self._submit(\"autodetect\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** datatype conversion form */\n _getConversion: function() {\n var self = this;\n var form = new Form({\n title: \"Convert to new format\",\n operations: {\n submit_conversion: new Ui.ButtonIcon({\n tooltip: \"Convert the datatype to a new format.\",\n title: \"Convert datatype\",\n icon: \"fa-exchange\",\n onclick: function() {\n self._submit(\"conversion\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** change datatype form */\n _getDatatype: function() {\n var self = this;\n var form = new Form({\n title: \"Change datatype\",\n operations: {\n submit_datatype: new Ui.ButtonIcon({\n tooltip: \"Change the datatype to a new type.\",\n title: \"Change datatype\",\n icon: \"fa-exchange\",\n onclick: function() {\n self._submit(\"datatype\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** dataset permissions form */\n _getPermission: function() {\n var self = this;\n var form = new Form({\n title: \"Manage dataset permissions\",\n operations: {\n submit_permission: new Ui.ButtonIcon({\n tooltip: \"Save permissions.\",\n title: \"Save permissions\",\n icon: \"fa-floppy-o \",\n onclick: function() {\n self._submit(\"permission\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** reload Galaxy's history after updating dataset's attributes */\n _reloadHistory: function() {\n if (window.Galaxy) {\n window.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/dataset-edit-attributes.js"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack:///analysis.bundled.js","webpack:///./galaxy/scripts/mvc/ui/ui-popover.js","webpack:///./galaxy/scripts/mvc/dataset/states.js","webpack:///./galaxy/scripts/mvc/ui/ui-select.js","webpack:///./galaxy/scripts/ui/fa-icon-button.js","webpack:///./galaxy/scripts/mvc/upload/upload-model.js","webpack:///./galaxy/scripts/mvc/tag.js","webpack:///./galaxy/scripts/layout/router.js","webpack:///./galaxy/scripts/mvc/upload/upload-settings.js","webpack:///./galaxy/scripts/mvc/upload/upload-ftp.js","webpack:///./galaxy/scripts/mvc/upload/upload-extension.js","webpack:///./galaxy/scripts/utils/uploadbox.js","webpack:///./galaxy/scripts/mvc/collection/list-collection-creator.js","webpack:///./galaxy/scripts/mvc/history/hdca-model.js","webpack:///./galaxy/scripts/mvc/collection/collection-model.js","webpack:///./galaxy/scripts/mvc/history/history-model.js","webpack:///./galaxy/scripts/mvc/history/history-contents.js","webpack:///./galaxy/scripts/mvc/history/history-preferences.js","webpack:///./galaxy/scripts/mvc/list/list-item.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-li.js","webpack:///./galaxy/scripts/mvc/collection/collection-li.js","webpack:///./galaxy/scripts/mvc/form/form-wrapper.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-model.js","webpack:///./galaxy/scripts/mvc/history/history-content-model.js","webpack:///./galaxy/scripts/mvc/collection/base-creator.js","webpack:///./galaxy/scripts/utils/natural-sort.js","webpack:///./galaxy/scripts/ui/hoverhighlight.js","webpack:///./galaxy/scripts/mvc/tool/tool-form-composite.js","webpack:///./galaxy/scripts/mvc/history/copy-dialog.js","webpack:///./galaxy/scripts/mvc/ui/error-modal.js","webpack:///./galaxy/scripts/mvc/base/controlled-fetch-collection.js","webpack:///./galaxy/scripts/mvc/history/hda-model.js","webpack:///./galaxy/scripts/mvc/list/list-view.js","webpack:///./galaxy/scripts/ui/search-input.js","webpack:///./galaxy/scripts/mvc/history/hda-li.js","webpack:///./galaxy/scripts/mvc/history/history-item-li.js","webpack:///./galaxy/scripts/mvc/history/hdca-li.js","webpack:///./galaxy/scripts/mvc/collection/collection-view.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-li-edit.js","webpack:///./galaxy/scripts/mvc/annotation.js","webpack:///./galaxy/scripts/apps/analysis.js","webpack:///./galaxy/scripts/apps/panels/tool-panel.js","webpack:///./galaxy/scripts/mvc/upload/upload-view.js","webpack:///./galaxy/scripts/mvc/upload/upload-button.js","webpack:///./galaxy/scripts/mvc/upload/default/default-view.js","webpack:///./galaxy/scripts/mvc/upload/default/default-row.js","webpack:///./galaxy/scripts/mvc/lazy/lazy-limited.js","webpack:///./galaxy/scripts/mvc/upload/composite/composite-view.js","webpack:///./galaxy/scripts/mvc/upload/composite/composite-row.js","webpack:///./galaxy/scripts/mvc/upload/collection/collection-view.js","webpack:///./galaxy/scripts/mvc/upload/collection/collection-row.js","webpack:///./galaxy/scripts/mvc/workflow/workflow-icons.js","webpack:///./galaxy/scripts/apps/panels/history-panel.js","webpack:///./galaxy/scripts/mvc/history/options-menu.js","webpack:///./galaxy/scripts/mvc/history/history-view-edit-current.js","webpack:///./galaxy/scripts/utils/ajax-queue.js","webpack:///./galaxy/scripts/mvc/history/history-view-edit.js","webpack:///./galaxy/scripts/mvc/history/history-view.js","webpack:///./galaxy/scripts/ui/loading-indicator.js","webpack:///./galaxy/scripts/mvc/history/hda-li-edit.js","webpack:///./galaxy/scripts/mvc/history/hdca-li-edit.js","webpack:///./galaxy/scripts/mvc/collection/collection-view-edit.js","webpack:///./galaxy/scripts/mvc/collection/collection-li-edit.js","webpack:///./galaxy/scripts/mvc/collection/pair-collection-creator.js","webpack:///./galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js","webpack:///./galaxy/scripts/utils/levenshtein.js","webpack:///./galaxy/scripts/mvc/user/user-preferences.js","webpack:///./galaxy/scripts/mvc/user/user-custom-builds.js","webpack:///./galaxy/scripts/mvc/grid/grid-shared.js","webpack:///./galaxy/scripts/mvc/workflow/workflow.js","webpack:///./galaxy/scripts/mvc/workflow/workflow-model.js","webpack:///./galaxy/scripts/mvc/history/history-list.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-error.js","webpack:///./galaxy/scripts/mvc/dataset/dataset-edit-attributes.js"],"names":["webpackJsonp","module","exports","__webpack_require__","Backbone","_","$","Object","defineProperty","value","_utils","_utils2","obj","__esModule","default","View","extend","optionsDefault","with_close","title","placement","container","body","initialize","options","this","setElement","_template","uid","defaults","parent","append","el","$title","$close","$body","self","on","e","visible","is","target","has","length","hide","render","html","$el","removeClass","addClass","css","_get_placement","show","off","newTitle","undefined","empty","remove","top","left","width","_get_width","height","$container","container_width","container_height","_get_height","container_position","position","indexOf","parseInt","call","STATES","UPLOAD","QUEUED","RUNNING","SETTING_METADATA","NEW","EMPTY","OK","PAUSED","FAILED_METADATA","NOT_VIEWABLE","DISCARDED","ERROR","READY_STATES","NOT_READY_STATES","placeholder","data","multiple","minimumInputLength","initialData","merge","console","log","select_data","_refresh","_setValue","onchange","new_value","before","_getValue","after","text","select2","disabled","enable","disable","add","push","id","del","index","_getIndex","splice","update","key","select_opt","containerCssClass","ajax","dropdownCssClass","escapeMarkup","formatResult","formatSelection","initSelection","selected","dropdownAutoWidth","findIndex","_jquery","_jquery2","faIconButton","tooltipConfig","classes","concat","join","href","faIcon","$button","tooltip","isFunction","onclick","click","Model","extension","genome","url_paste","status","info","file_name","file_mode","file_size","file_type","file_path","file_data","percentage","space_to_tab","to_posix_lines","enabled","reset","attr","clear","set","Collection","model","_interopRequireDefault","_baseMvc","_baseMvc2","_localization","_localization2","TagsEditor","LoggableMixin","HiddenUntilActivatedViewMixin","tagName","className","select_width","events","show_editor","usePrompt","label","workflow_mode","keydown","hiddenUntilActivated","$activator","_workflowTemplate","_defaultTemplate","$input","tags","_getTagsUsed","_setUpBehaviors","_hashToName","tag","startsWith","slice","_nameToHash","_renderEditor","_renderTags","keydownHandler","which","hideEditor","showEditor","tagsToCSV","get","renderedArray","each","renderString","tagsArray","isArray","isEmpty","map","escape","sort","find","Galaxy","user","event","val","save","added","_addNewTagToTagsUsed","newTag","tagsUsed","contains","stopListening","prototype","toString","_queryStringParsing","_queryStringParsing2","_uiMisc","_uiMisc2","Router","page","url","__identifer","Math","random","substr","isEmptyObject","param","params","navigate","trigger","execute","callback","args","name","debug","queryObj","parse","pop","authenticate","apply","access_denied","display","Message","message","persistent","class_check","class_uncheck","parameters","$cover","$table","listenTo","parameter","$checkbox","cls","class_add","class_remove","class_partial","help_enabled","help_text","ftp_upload_site","collection","onadd","onremove","$content","$wait","$help","$number","$disk","$warning","$select","root","method","success","ftp_files","_index","_renderTable","error","rows","size","ftp_file","_renderRow","bytesToString","_all","attributes","$it","_templateRow","$icon","model_index","ftp_index","path","_switch","hasClass","new_index","counts","reduce","memo","element","ctime","_uiPopover","_uiPopover2","description","findWhere","list","extension_popup","_templateDescription","tmpl","description_url","jQuery","props","uploadpost","config","cnf","progress","maxfilesize","error_filesize","error_default","error_server","error_login","error_message","form","FormData","payload","sizes","files","d","file","xhr","XMLHttpRequest","open","setRequestHeader","onreadystatechange","readyState","DONE","response","extra_info","responseText","parseJSON","err_msg","statusText","upload","addEventListener","lengthComputable","round","loaded","total","emit","send","fn","uploadinput","opts","ondragover","ondragleave","change","dataTransfer","preventDefault","stopPropagation","dialog","uploadbox","queue_running","mode","filter","queue","f","duplicate","String","queue_index","announce","queue_length","process","queue_stop","complete","select","start","stop","configure","compatible","window","File","FileList","dragover","dragleave","m","alert","createListCollection","contents","defaultHideSourceItems","elements","toJSON","listCollectionCreatorModal","creationFn","hideSourceItems","src","history_content_type","createHDCA","_hdcaModel","_hdcaModel2","_states","_states2","_baseCreator","_baseCreator2","_uiModal","_uiModal2","_naturalSort","DatasetCollectionElementView","_logNamespace","dragStartHandler","bind","_dragstart","dragEndHandler","_dragend","handle","template","toggle","toggleClass","source","discard","view","parentWidth","animate","margin-right","destroy","click .name","click .discard","drop","_click","ev","_clickName","prompt","_clickDiscard","originalEvent","effectAllowed","setData","JSON","stringify","_sendToParent","ListCollectionCreator","CollectionCreatorMixin","elementViewClass","collectionClass","HistoryListDatasetCollection","minElements","defaultAttributes","TypeError","oncreate","oncancel","autoscrollDist","highlightClr","footerSettings",".hide-originals","metric","creator","initialElements","_setUpCommonSettings","_instanceSetUp","_elementsSetUp","selectedIds","$dragging","blocking","invalidElements","workingElements","elementViews","_ensureElementIds","_validateElements","_mangleDuplicateNames","_sortElements","forEach","hasOwnProperty","uniqueId","problem","_isElementInvalid","state","deleted","purged","counter","existingNames","currName","Error","speed","_renderInvalid","templates","main","_renderHeader","_renderMiddle","_renderFooter","_addPluginComponents","focus","invalidInitial","problems","$header","header","prepend","helpContent","_invalidElementsAlert","$middle","middle","_renderList","hoverhighlight","_showAlert","_disableNameAndCreate","isUndefined","prop","$list","_renderClearSelected","$tmp","removeElementView","elementView","_createElementView","children","invoke","_listenToElementView","addElementView","without","_renderNoElementsLeft","noElementsLeft","_elementToJSON","createList","hideOriginals","always","fail","done","_errorHandler","once","content","responseJSON","click .more-help","click .less-help","click .main-help","click .header .alert button","click .reset","click .clear-selected","click .collection-elements","dragover .collection-elements","drop .collection-elements","collection-element.dragstart .collection-elements","collection-element.dragend .collection-elements","change .collection-name","keydown .collection-name","change .hide-originals","click .cancel-create","click .create-collection","clearSelectedElements","_dragoverElements","_checkForAutoscroll","clientY","$nearest","_getNearestElement","$placeholder","$element","y","offset","scrollTop","upperDist","lowerDist","outerHeight","lis","toArray","i","$li","halfHeight","floor","_dropElements","dropEffect","insertBefore","insertAfter","last","_syncOrderToDom","newElements","_elementDragstart","_elementDragend","_creatorTemplates","footer","collectionCreatorModal","CreatorClass","deferred","Deferred","modal","reject","resolve","closing_events","_collectionCreator","buildHDCASave","_super","isNew","urlRoot","type","_collectionModel","_collectionModel2","_historyContentModel","_historyContentModel2","hcontentMixin","HistoryContentMixin","ListDC","ListDatasetCollection","PairDC","PairDatasetCollection","ListPairedDC","ListPairedDatasetCollection","ListOfListsDC","ListOfListsDatasetCollection","clone","collection_type","model_class","HistoryPairDatasetCollection","HistoryListPairedDatasetCollection","HistoryListOfListsDatasetCollection","_datasetModel","_datasetModel2","DatasetCollectionElementMixin","element_identifier","element_index","element_type","_mergeObject","object","element_id","constructor","idAttribute","arguments","DatasetCollectionElement","DCECollection","DatasetDCE","DatasetAssociation","mixin","warn","_downloadQueryParameters","fileExt","elementIdentifier","hasDetails","DatasetDCECollection","DatasetCollection","SearchableModelMixin","_createElementsModel","unset","silent","parent_hdca_id","json","inReadyState","populated","isDeletedOrPurged","getVisibleContents","filters","parsed","create_time","Date","update_time","delete","when","undelete","searchAttributes","NestedDCDCE","NestedDCDCECollection","NestedPairDCDCE","NestedPairDCDCECollection","NestedListDCDCE","NestedListDCDCECollection","_historyContents","_historyContents2","_historyPreferences","_controlledFetchCollection","_controlledFetchCollection2","History","UPDATE_DELAY","contents_active","contents_states","contentsClass","HistoryContents","searchAliases","historyJSON","logger","history","historyId","order","_setUpListeners","_setUpCollectionListeners","updateTimeoutId","msg","details","clearUpdateTimeout","change:id","newId","makeArray","contentsShown","contentsActive","shown","active","includeDeleted","includeHidden","hidden","nice_size","ownedByCurrUser","isAnonymous","numOfUnfinishedJobs","unfinishedJobIds","numOfUnfinishedShownContents","runningAndActive","_fetchContentRelatedAttributes","contentRelatedAttrs","fetch","keys","refresh","_this","lastUpdateTime","allFetched","currentPage","fetchPage","fetchUpdated","serverResponseDatetime","getResponseHeader","err","checkForUpdates","_this2","delay","_delayThenUpdate","setTimeout","historyData","clearTimeout","fetchWithContents","contentsOptions","then","setHistoryId","fetchContents","fetchCurrentPage","_delete","purge","copy","current","allDatasets","postData","history_id","all_datasets","post","setAsCurrent","getJSON","_collectionSuper","InfinitelyScrollingCollection","HistoryCollection","limitOnFirstFetch","limitPerFetch","models","currentHistoryId","setUpListeners","change:deleted","copied","original","newData","setCurrent","set-as-current","oldCurrentId","_buildFetchData","_buildFetchFilters","superFilters","fetchFirst","limit","encoded_id-in","fetchMore","comparators","buildComparator","ascending","name-dsc","size-asc","currentHistory","unshift","create","hdas","historyOptions","xhrOptions","_hdaModel","_hdaModel2","_historyPreferences2","_ajaxQueue","_ajaxQueue2","PaginatedCollection","limitPerPage","limitPerProgressiveFetch","attrs","HistoryDatasetAssociation","validationError","_setUpWebStorage","initialSettings","storage","HistoryPrefs","historyStorageKey","include-deleted","newVal","include-hidden","hid","hid-asc","running","c","getByHid","haveDetails","all","visibleAndUndeleted","setIncludeDeleted","setting","isBoolean","result","setIncludeHidden","prefs","expandedIds","values","v","_fetchParams","getTotalItemCount","since","update_time-ge","toISOString","fetchDeleted","fetchHidden","fetchAllDetails","detailsFlag","fetchCollectionCounts","_filterAndUpdate","filterParams","updateWhat","updateArgs","fetched","modelArray","currJson","ajaxQueue","ajaxFn","AjaxQueue","reverse","isString","progressivelyFetchDetails","_recursivelyFetch","_options","detailKeys","defer","notify","limitPerCall","isCopyable","contentsJSON","copyableModelClasses","isObject","contentType","LibraryDatasetDatasetAssociation","HistoryDatasetCollectionAssociation","elementIdentifiers","collectionType","hide_source_items","element_identifiers","haveSearchDetails","matches","matchesWhat","SessionStorageModel","show_deleted","show_hidden","addExpanded","removeExpanded","isExpanded","contentId","allExpanded","clearExpanded","storageKeyPrefix","clearAll","sessionStorage","removeItem","ExpandableView","expanded","fxSpeed","$newRender","_buildNewRender","_queueNewRender","$details","replaceWith","_renderDetails","_swapNewRender","next","fadeOut","fadeIn","$where","$newDetails","toggleExpanded","expand","collapse","_fetchModelDetails","_expand","slideDown","slideUp","ListItemView","SelectableViewMixin","DraggableViewMixin","isSelectable","_renderWarnings","_renderTitleBar","_renderPrimaryActions","_renderSubtitle","selectable","showSelector","draggable","draggableOn","$warnings","warnings","templateFn","titleBar","subtitle","click .title-bar","keydown .title-bar","click .selector","_clickTitleBar","altKey","toggleSelect","_keyDownTitleBar","keyCode","wrapTemplate","FoldoutListItemView","foldoutStyle","foldoutPanelClass","foldout","_createFoldoutPanel","_attachFoldout","FoldoutClass","_getFoldoutPanelClass","_getFoldoutPanelOptions","$whereTo","_expandByDrilldown","detailsTemplate","_listItem","_listItem2","_faIconButton","_faIconButton2","DatasetListItemView","linkTarget","changedAttributes","changed","_renderNametags","_renderDisplayButton","displayBtnData","urls","frame","addDataset","noAccess","_renderSecondaryActions","_renderSummary","_renderDetailMessages","_renderDisplayApplications","summaryRenderFn","summaries","unknown","detailMessages","displayApplications","_renderDownloadButton","_renderShowParamsButton","show_params","hasData","download","_renderMetaFileDownloadButton","meta_file","meta_download","click .display-btn","click .params-btn","click .download-btn","failed_metadata","noAccessTemplate","summaryTemplates","detailMessageTemplates","resubmitted","displayApplicationsTemplate","_datasetLi","_datasetLi2","DCListItemView","hasUser","$selector","titleBarTemplate","subtitleTemplate","DCEListItemView","DatasetDCEListItemView","NestedDCDCEListItemView","_formView","_formView2","redirect","icon","inputs","buttons","submit","Button","submit_tooltip","submit_title","submit_icon","_submit","success_message","location","matchModel","input","input_id","field_list","_showMessage","parents","first","searchableMixin","accessible","data_type","file_ext","meta_files","misc_blurb","misc_info","_generateUrls","edit","report_error","rerun","visualization","currModel","newState","previous","ready","dataset","wait","hda","responseObj","format","database","blurb","nameAndId","DatasetAssociationCollection","ids","item","notReady","startingLength","responses","ajaxFns","chain","curr","shift","isVisible","historyContentType","historyContentId","unhide","_validationWarning","what","_changeHideOriginals","_changeName","_getName","_nameCheckForEnter","_clickCreate","_clickMoreHelp","_clickLessHelp","_toggleHelp","alertClass","_hideAlert","_cancelCreate","$footer","property","selector","naturalSort","a","b","re","x","toLowerCase","nC","fromCharCode","xN","replace","split","yN","xD","getTime","yD","oFxNcL","oFyNcL","cLoc","numS","max","parseFloat","scope","color","$this","targetSelector","mouseover","background","mouseout","_deferred","_deferred2","_formData","_formData2","_toolFormBase","_toolFormBase2","_webhooks","_webhooks2","_workflowIcons","_workflowIcons2","$message","$steps","_configure","resize","step_index","margin","child","_handleWorkflowParameter","match","exec","wp_name","wp_inputs","wp_count","style","links","forms","steps","parms","step","step_type","step_label","step_name","annotation","step_version","fixed_title","help","citations","collapsible","collapsed","_isDataStep","sustain_version","sustain_repeats","sustain_conditionals","narrow","text_enable","text_disable","cls_enable","cls_disable","errors","messages","initial_errors","hide_operations","needs_refresh","always_refresh","visitInputs","output_connections","output_connection","sub_step","j","input_step_index","connections_by_name","connection","input_name","step_linked","output_name","wp_input","wp_linked","backdrop","post_job_actions","pja","action_arguments","arg","data_resolved","context","is_runtime_value","__class__","is_data_input","data_ref","is_workflow","default_value","flavor","optional","collapsible_value","collapsible_preview","_renderMessage","_renderParameters","_renderHistory","_renderStep","execute_btn","_execute","Label","fade","step_version_changes","wp_form","input_list","input_def","_refreshStep","_append","history_form","test_param","cases","promise","postchange","current_state","tool_id","tool_version","version","request","portlet","short_str","is_simple_input","hide_label","link","ignore","show_progress","wait_text","field","source_step","wp_field","wp_value","_refreshHistory","currHistoryPanel","_refresh_history","_enabled","history_form_data","job_def","new_history_name","replacement_params","parameters_normalized","batch","validated","job_inputs","job_input_id","input_value","highlight","_templateSuccess","WebhookView","toolId","toolVersion","input_found","err_data","step_related_errors","error_messages","matchResponse","_templateError","Close","lst","sanitize","_errorModal","_errorModal2","CopyDialog","defaultName","submitLabel","errorMessage","progressive","activeLabel","allLabel","anonWarning","_showAjaxIndicator","indicator","margin-top","checkNameAndCopy","copyAllDatasets","ajaxErrorModal","rejectWith","autoClose","defaultCopyNameFn","nameFn","defaultCopyName","defaultCopyWhat","allowAll","originalClosingCallback","closing_callback","isAnon","copyWhat","cancelled","ImportDialog","historyCopyDialog","useImport","Ok","appendTo","DETAILS_MSG","errorModal","offlineErrorModal","badGatewayErrorModal","CONTACT_MSG","DEFAULT_AJAX_ERR_MSG","_ajaxDetails","raven","Raven","userAgent","navigator","onLine","omit","functions","lastAjax","_interopRequireWildcard","newObj","_underscore","_backbone","ControlledFetchCollection","setOrder","changed-order","_buildFetchOptions","traditional","_fetchFiltersToAjaxData","pick","filterMap","q","qv","k","update_time-asc","create_time-asc","comparator","shouldPaginate","getLastPage","getPageCount","getPageLimitOffset","pageNum","constrainPageNum","min","fetchPrevPage","fetchNextPage","lastFetched","fetchedData","numFetched","fetchAll","_loadingIndicator","_loadingIndicator2","ListPanel","viewClass","emptyMsg","noneFoundMsg","searchPlaceholder","searchFor","selecting","lastSelected","dragItems","views","_createDefaultCollection","$scrollContainer","loading","_showLoadingIndicator","loading-done","_hideLoadingIndicator","_setUpViewListeners","changes","renderAll","removed","renderItems","addItemView","removeItemView","view:selected","shiftKey","lastSelectedView","viewFromModelId","selectRange","showSelectors","view:de-selected","_renderControls","_renderTitle","_renderSearch","$controls","controls","panel","_renderMultiselectActionMenu","$menu","actions","multiselectActions","$newMenu","$actions","action","func","$messages","$emptyMessage","freeViews","shownModels","_filterCollection","itemModel","_createItemView","_attachItems","_renderEmptyMessage","_filterItem","every","matchesAll","ViewClass","_getItemViewClass","_getItemViewOptions","_setUpItemViewListeners","_destroyItemView","_destroyItemViews","Array","getSelectedModels","_renderItemView$el","expandAll","collapseAll","modelIndex","_attachView","useFx","_insertIntoListAt","$what","eq","viewFromModel","viewsWhereModel","properties","isMatch","viewRange","viewA","viewB","indexA","indexB","searchInput","initialVal","onfirstsearch","_firstSearch","onsearch","searchItems","onclear","clearSearch","force","$search","THROTTLE_SELECTOR_FX_AT","hideSelectors","hideSelector","toggleSelectors","selectAll","deselectAll","deselect","range","getSelectedViews","scrollPosition","scrollTo","pos","scrollToTop","scrollToItem","scrollToId","click .select-all","click .deselect-all","ModelListPanel","modelCollectionKey","setModel","freeModel","oldModelId","_setUpModelListeners","controlsTemplate","parentNode","clearSearchInput","blur","search","searchTerms","firstSearch","inputTemplate","KEYCODE_ESC","KEYCODE_RETURN","$parentNode","inputVal","minSearchLen","escWillClear","oninit","keyup","_l","s","_historyItemLi","_historyItemLi2","HDAListItemView","nametagTemplate","_labelIfName","historyItem","sortBy","uniq","_collectionLi","_collectionLi2","_collectionView","_collectionView2","HDCAListItemView","change:tags change:populated change:visible","ListCollectionView","PairCollectionView","ListOfPairsCollectionView","ListOfListsCollectionView","_listView","_listView2","CollectionView","DatasetDCEViewClass","NestedDCDCEViewClass","panelStack","parentName","downloadUrl","expanded:drilldown","drilldown","_expandDrilldownPanel","collapsed:drilldown","_collapseDrilldownPanel","click .navigation .back","close","_tag","_tag2","_annotation","_annotation2","DatasetListItemEdit","purgeAllowed","tagsEditorShown","annotationEditorShown","_renderEditButton","_renderDeleteButton","editBtnData","router","dataset_id","deletedAlready","_renderAnnotation","_makeDbkeyEditLink","_renderToolHelpButton","datasetID","jobID","creating_job","parseToolBuild","helpString","parseHTML","parseToolID","_renderErrButton","_renderRerunButton","_renderVisualizationsButton","job_id","visualizations","$visualizations","_addScratchBookFn","addBack","$links","tagsEditor","onshowFirstTime","onshow","onhide","annotationEditor","AnnotationEditor","editableDbkey","click .undelete-link","click .purge-link","click .edit-btn","click .delete-btn","click .rerun-btn","click .report-err-btn","click .visualization-btn","click .dbkey a","_clickUndeleteLink","_clickPurgeLink","confirm","visualizationsTemplate","$annotation","make_text_editable","use_textarea","on_finish","newAnnotation","_galaxy","_galaxy2","_router","_router2","_toolPanel","_toolPanel2","_historyPanel","_historyPanel2","_page","_page2","_toolForm","_toolForm2","_formWrapper","_formWrapper2","_userPreferences","_userPreferences2","_userCustomBuilds","_userCustomBuilds2","_tours","_tours2","_gridView","_gridView2","_gridShared","_gridShared2","_workflow","_workflow2","_historyList","_historyList2","_toolFormComposite","_toolFormComposite2","_datasetError","_datasetError2","_datasetEditAttributes","_datasetEditAttributes2","app","bootstrapped","GalaxyApp","AnalysisRouter","routes","(/)","(/)root*","(/)tours(/)(:tour_id)","(/)user(/)","(/)user(/)(:form_id)","(/)workflow(/)","(/)workflow/run(/)","(/)pages(/)create(/)","(/)pages(/)edit(/)","(/)pages(/)(:action_id)","(/)visualizations(/)edit(/)","(/)visualizations/(:action_id)","(/)workflows/list_published(/)","(/)histories(/)rename(/)","(/)histories(/)permissions(/)","(/)histories(/)(:action_id)","(/)datasets(/)list(/)","(/)workflow/import_workflow","(/)custom_builds","(/)datasets/edit","(/)datasets/error","require_login","show_tours","tour_id","giveTour","ToursView","show_user","show_user_form","form_id","user_id","show_visualizations","action_id","plural","show_visualizations_edit","show_workflows_published","url_base","dict_format","show_histories","show_histories_rename","show_histories_permissions","show_datasets","show_pages","show_pages_create","show_pages_edit","show_workflows","show_run","_loadWorkflow","show_import_workflow","ImportWorkflowView","show_custom_builds","historyPanel","historyView","show_dataset_edit_attributes","show_dataset_error","home","toolPanel","_loadCenterIframe","_loadToolForm","workflow_id","m_c","m_a","decodeURIComponent","getQueryString","error_msg","Left","Right","_tools","_tools2","_uploadView","_uploadView2","ToolPanel","stored_workflow_menu_entries","tool_search","ToolSearch","tools","ToolCollection","toolbox","tool_panel","layout","toolbox_in_panel","tool_panel_view","ToolPanelView","upload_button","nginx_upload_path","default_genome","default_extension","_templateAllWorkflow","menu_entry","_templateWorkflowLink","stored_workflow","encoded_stored_workflow_id","_templateTool","tool","wf","_uiTabs","_uiTabs2","_uploadButton","_uploadButton2","_defaultView","_defaultView2","_compositeView","_compositeView2","auto","list_extensions","list_genomes","ui_button","onunload","datatypes","composite_files","a_text","b_text","datatypes_disable_auto","genomes","current_user","tabs","default_view","composite_view","collection_view","title_separator","currentFtp","toData","items","file_count","dbkey","it","prefix","$progress","_uploadModel","_uploadModel2","_defaultRow","_defaultRow2","_uploadFtp2","_uploadFtp3","_uploadExtension","_uploadExtension2","_uiSelect","_uiSelect2","_lazyLimited","_lazyLimited2","upload_size","$uploadbox","$uploadtable","btnLocal","btnFtp","_eventFtp","btnCreate","_eventCreate","btnStart","_eventStart","btnStop","_eventStop","btnReset","_eventReset","btnClose","button","_eventAnnounce","_eventProgress","_eventSuccess","_eventError","_eventComplete","ftp","select_extension","ext","_changeExtension","select_genome","_changeGenome","loader","new_content","upload_row","_eventRemove","enable_reset","enable_start","enable_sources","show_table","new_model","_uploadPercentage","upload_completed","refreshContents","_uploadFtp","defaults_only","_uploadSettings","_uploadSettings2","status_classes","init","queued","$mode","$text","$size","$info_text","$info_progress","$text_content","$settings","$symbol","$progress_bar","$percentage","settings","_removeRow","showExtensionInfo","_showSettings","_refreshPercentage","_refreshStatus","_refreshInfo","_refreshGenome","_refreshExtension","_refreshFileSize","_refreshType","content_list","_reset","_remove","_done","model_id","_compositeRow","_compositeRow2","file_desc","where","$source","$status","$file_name","$file_desc","$file_size","_refreshReady","button_menu","ButtonMenu","pull","addMenu","_showFtp","_refreshFileName","_refreshMode","offsetHeight","_collectionRow","_collectionRow2","_listCollectionCreator","btnBuild","_eventBuild","updateExtension","select_collection","updateCollectionType","updateGenome","_updateScreen","hids","pluck","allHids","selection","buildCollection","enable_build","data_input","data_collection_input","subworkflow","pause","_optionsMenu","_optionsMenu2","_historyViewEditCurrent","_historyViewEditCurrent2","HistoryPanel","userIsAnonymous","allow_user_dataset_purge","CurrentHistoryView","listenToGalaxy","buttonRefresh","ButtonLink","loadCurrentHistory","buttonOptions","buttonViewMulti","connectToQuotaMeter","quotaMeter","optionsMenu","anonymous","buildMenu","menu","menuOption","anon","galaxy_main","_popupMenu","_popupMenu2","_copyDialog","_copyDialog2","createNewHistory","user_action","async","webhooks","webhooks_menu","webhook","activate","_historyModel","_historyViewEdit","_historyViewEdit2","HistoryViewPrefs","storageKey","HistoryViewEdit","HDCAViewClass","preferences","currentContentId","loadHistory","switchToHistory","change:nice_size change:size","oldState","_debouncedScrollCaptureHandler","debounce","prependTo","_renderQuotaMessage","quotaMsg","_setCurrentContentById","setCurrentContent","delegateEvents","click .uploader-link","click .get-data-link","$toolMenu","galaxy","center-frame:load","pathToMatch","fullpath","hdaId","useToURLRegexMap","regex","use","center-panel:load","showQuotaMessage","hideQuotaMessage","isOverQuota","clearMessages","$target","currentTarget","not","$msg","unhideHidden","deleteHidden","quotaMsgTemplate","_possibleConstructorReturn","ReferenceError","_inherits","subClass","superClass","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","instance","Constructor","_get","receiver","Function","desc","getOwnPropertyDescriptor","getPrototypeOf","getter","_createClass","defineProperties","descriptor","protoProps","staticProps","initialFunctions","numToProcess","fnIndex","causeFail","NamedAjaxQueue","_AjaxQueue","_this3","names","_historyView","_historyView2","_hdaLiEdit","_hdaLiEdit2","_hdcaLiEdit","_hdcaLiEdit2","_listCollectionCreator2","_pairCollectionCreator","_pairCollectionCreator2","_listOfPairsCollectionCreator","_listOfPairsCollectionCreator2","HistoryView","HDAViewClass","HDAListItemEdit","HDCAListItemEdit","droptarget:drop","dataDropped","dropTargetOff","view:attached view:removed","_renderCounts","search:loading-progress","_renderSearchProgress","search:searching","_renderSearchFindings","updateHistoryDiskSize","_handleItemDeletedChange","change:visible","_handleItemVisibleChange","change:purged","fetching-deleted","fetching-hidden","fetching-deleted-done fetching-hidden-done","toggleHDATagEditors","toggleHDAAnnotationEditors","newName","previousName","_collectionActions","createFunc","createPairCollection","createListOfPairsCollection","_handleItemDeletion","_handleItemUndeletion","_handleItemHidden","_handleItemUnhidden","showOrHide","click .show-selectors-btn","click .toggle-deleted-link","toggleShowDeleted","click .toggle-hidden-link","toggleShowHidden","found","dropTargetOn","dropTarget","dropHandlers","dragenter","$dropTarget","_renderDropTarget","_renderDropTargetHelp","evName","_dropHandlers","dropTargetToggle","getData","countsTemplate","foundTemplate","_historyModel2","_hdaLi","_hdaLi2","_hdcaLi","_hdcaLi2","_userModel","FETCH_COLLECTION_COUNTS_DELAY","detailedFetchTimeoutId","_clearDetailedFetchTimeout","errorHandler","views:ready view:attached view:removed","_renderSelectButton","view:attached","fetching-more","_toggleContentsLoadingIndicator","fetching-more-done","$indicator","$existing","$emptyMsg","_renderPagination","_renderSomeItems","$paginationControls","pagination","click > .controls .prev","click > .controls .next","change > .controls .pages","click .messages [class$=message]","_clickPrevPage","_clickNextPage","_changePageSelect","store","_this4","_this5","scrollToHid","ordinalIndicator","number","numStr","charAt","mainTemplate","paginationTemplate","LoadingIndicator","cover","z-index","bottom","right","opacity","background-color","text-align","font-style","_datasetLiEdit","_datasetLiEdit2","click .unhide-link","_collectionViewEdit","_collectionViewEdit2","ListCollectionViewEdit","PairCollectionViewEdit","ListOfPairsCollectionViewEdit","ListOfListsCollectionViewEdit","_collectionLiEdit","_collectionLiEdit2","CollectionViewEdit","DatasetDCEListItemEdit","NestedDCDCEListItemEdit","NestedPairCollectionViewEdit","DCListItemEdit","DCEListItemEdit","pairCollectionCreatorModal","PairedDatasetCollectionElementView","identifier","PairCollectionCreator","_createForwardElementView","_createReverseElementView","swap","click .swap","autoPairFnBuilder","getRegExps","_regexps","RegExp","createPair","listA","listB","aInBIndex","bInAIndex","_pair","preprocessMatch","regexps","matchTo","possible","bestMatch","score","paired","scoreThreshold","pairedCollectionCreatorModal","_levenshtein","_levenshtein2","_naturalSort2","PairView","pair","PairedCollectionCreator","datasets","DEFAULT_FILTERS","automaticallyPair","strategy","matchPercentage","twoPassAutopairing","initialList","commonFilters","strategies","DEFAULT_STRATEGY","removeExtensions","unpairedPanelHidden","pairedPanelHidden","_dataSetUp","illumina","Rs","simple","lcs","levenshtein","unpaired","_sortInitialList","_ensureIds","autoPair","_sortDatasetList","_splitByFilters","_filter","test","regexFilters","stringFilter","_addToUnpaired","binSearchSortedIndex","low","hi","mid","compared","autopairSimple","autopairLevenshtein","distance","autopairLCS","_naiveStartingAndEndingLCS","s1","s2","fwdLCS","revLCS","fwd","rev","_createPair","_guessNameForPair","forward","fwdName","revName","lastDotIndex","lastIndexOf","_unpair","unpairAll","pairs","_pairToJSON","ajaxData","dataType","_ajaxErrHandler","_renderFilters","_renderUnpaired","_renderPaired","$fwd","$rev","$prd","_renderUnpairedDisplayStr","_renderUnpairedEmpty","_renderPairButton","_renderUnpairedDataset","_adjUnpairedOnScrollbar","_renderUnpairedNotShown","numFiltered","$unpairedColumns","$firstDataset","ucRight","outerWidth","dsRight","rightDiff","_renderPairedEmpty","pairView",".remove-extensions","_chooseFiltersPopover","filterChoice","val1","val2","$popoverContent","filterSet","popover","splitView","msgClass","hideUnpaired","click .forward-column .column-title","click .reverse-column .column-title","click .unpair-all-link","change .forward-unpaired-filter input","focus .forward-unpaired-filter input","click .autopair-link","click .choose-filters .filter-choice","click .clear-filters-link","change .reverse-unpaired-filter input","focus .reverse-unpaired-filter input","click .forward-column .dataset.unpaired","click .reverse-column .dataset.unpaired","click .paired-column .dataset.unpaired","click .unpaired-columns","mousedown .unpaired-columns .dataset","click .paired-column-title","mousedown .flexible-partition-drag","click .paired-columns .dataset.paired","click .paired-columns","click .paired-columns .pair-name","click .unpair-btn","dragover .paired-columns .column-datasets","drop .paired-columns .column-datasets","pair.dragstart .paired-columns .column-datasets","pair.dragend .paired-columns .column-datasets","change .remove-extensions","toggleExtensions","_clickShowOnlyUnpaired","hidePaired","_clickShowOnlyPaired","_clickUnpairAll","_clickAutopair","_clickFilterChoice","$selected","_hideChooseFilters","_clearFilters","_clickUnpairedDataset","toggleSelectUnpaired","$dataset","waitToPair","pairAllSelected","fwds","revs","clearSelectedUnpaired","_mousedownUnpaired","$startTarget","moveListener","document","one","_clickPairRow","rowIndex","_startPartitionDrag","endDrag","unbind","trackMouse","pageY","startingY","adjPartition","mousemove","adj","$unpaired","$paired","unpairedHi","pairedHi","movingUpwards","flex","selectPair","clearSelectedPaired","_clickPairName","$name","$pair","customizedName","_clickUnpair","pairIndex","_dragoverPairedColumns","_getNearestPairedDatasetLi","_dropPairedColumns","_syncPairsToDom","newPaired","_pairDragstart","_pairDragend","_printList","_printPair","levenshteinDistance","matrix","information","password","communication","permissions","api_key","toolbox_filters","openids","custom_builds","logout","Cancel","Sign out","session_csrf_token","$preferences","email","use_remote_user","_addLink","enable_communication_server","has_user_tool_filters","enable_openid","_templateFooter","$row","_templateLink","$a","nice_total_disk_usage","enable_quotas","quota","_uiTable","_uiTable2","installed_builds","Select","empty_text","error_text","table","addHeader","appendHeader","$installed","$form","_renderForm","delAll","ButtonIcon","area","input_field","_renderHelp","len_type","_templateFasta","_templateLen","grid","_templateShared","$tmpl","shared_by_others","display_url","username","slug","_toastr","mod_toastr","_workflowModel","_workflowModel2","WorkflowItemView","bindAll","timeOut","click #show-in-tool-panel","click #delete-workflow","click #rename-workflow","click #copy-workflow","_rowTemplate","showInToolPanel","removeWorkflow","wfName","renameWorkflow","oldName","copyWorkflow","wfJson","currentOwner","at","resp","errorThrown","jqXHR","textStatus","wfId","checkboxHtml","trHtml","_templateActions","renderTagEditor","TagEditor","WorkflowListView","WorkflowCollection","appendItem","unhighlightDropZone","readWorkflowFiles","reader","FileReader","onload","theFile","wf_json","readAsText","_showArgErrors","msg_text","_templateHeader","templateActions","_templateActionButtons","tableTemplate","_templateWorkflowTable","confirmDelete","searchWorkflow","adjustActiondropdown","workflowItemView","workflow","$el_searchinput","$el_tabletr","min_querylen","query","regular_expression","_templateNoWorkflow","tableHtml","_mainTemplate","myexperiment_target_url","WorkflowItem","operation","_showCopyDialog","reload","data_url","job_url","job","render_error_page","error_response","display_message","stderr","_getBugFormTemplate","doNotClear","safe","UnescapedMessage","floating","form_data","_createTabs","initial_message","_reloadHistory","attribute","_getAttribute","conversion","_getConversion","datatype","_getDatatype","permission","_getPermission","operations","submit_attributes","submit_autodetect","submit_conversion","submit_datatype","submit_permission"],"mappings":"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G,oBACH,UACA,iDACA,SACA,kEACA,6CACA,EAAA0J,EAAA1J,SAAG,oBACH,OACA,SACA,SACA,SACA,yDACA,8BACA,6DACA,EAAA0J,EAAA1J,SAAG,kBACH,OACA,6DACA,EAAA0J,EAAA1J,SAAG,iBACH,aACA,wDACA,EAAA0J,EAAA1J,SAAG,aACH,OACA,SACA,SACA,kDACA,8BACA,6BACA,wBACA,EAAA0J,EAAA1J,SAAG,oBACH,UACA,iDACA,SACA,kEACA,6CACA,EAAA0J,EAAA1J,SAAG,oBACH,OACA,SACA,SACA,SACA,UACFwH,KAAK,KAIXmX,OAAQpf,EAAEia,UAGF,iFACA,kDACA,oCACA,SACA,yDACA,oCACA,SACA,kDACA,oCACA,SACA,SACA,mCACA,gDACA,EAAA9P,EAAA1J,SAAG,kBACH,WACA,8BACA,iDACA,8BACA,SACA,0DACA,EAAA0J,EAAA1J,SAAG,cACH,OACA,SACA,SACA,+EACA,oCACA,UACFwH,KAAK,KAIX+b,OAAQhkB,EAAEia,UAEF,iCACA,sBACA,6CACA,EAAA9P,EAAA1J,SAAG,0BACH,IACA,8DACA,WACA,6CACA,EAAA0J,EAAA1J,SAAG,0CACH,IACA,iEACA,WACA,SACA,sBACA,0DACA,iBACA,EAAA0J,EAAA1J,SAAG,kCACH,OACA,mDACA,EAAA0J,EAAA1J,SAAG,QACH,UACA,SACA,SAEA,gDACA,wCACA,oDACA,EAAA0J,EAAA1J,SAAG,UACH,YACA,8CACA,2EACA,EAAA0J,EAAA1J,SAAG,yCACH,+BACA,YACA,yCACA,oBACA,EAAA0J,EAAA1J,SAAG,+BACH,YACA,oBACA,EAAA0J,EAAA1J,SAAG,6CACH,YACA,QACA,SACA,SAEA,wCACA,sDACA,EAAA0J,EAAA1J,SAAG,eACH,YACA,SACA,UACFwH,KAAK,KAIXgX,YAAajf,EAAEia,UAEP,OACA,EAAA9P,EAAA1J,UAEQ,wGACA,2GACA,yGACA,sCACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,8FACA,yDACA,wFACA,iCACA,8BACA,sEACA,yDACA,4CACA,sEACA,yDACA,QACA,6DACA,qEACA,uDACA,4CACA,QACA,6DACA,4DACA,QACA,SACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,gEACA,oDACA,yEACA,sEACA,QACA,8DACA,mEACA,QACA,iEACA,8FACA,uEACA,6CACA,QACA,4CACA,iEACA,QACA,SACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,iDACA,2FACA,0FACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,sGACA,qGACFwH,KAAK,KAEX,OACA,OACA,EAAAkC,EAAA1J,UAEQ,4FACA,gEACA,oEACFwH,KAAK,KAEX,QACFA,KAAK,SAOnBm6D,EAA+B,SAAuCO,EAAUxhE,GAChF,GACIqb,GADA2H,EAAW1Q,EAAO2Q,UAetB,IAZAjjB,EAAUnB,EAAEwB,SAASL,OACjBwhE,SAAUA,EACVzmD,SAAU,WACNnP,OAAOsX,MAAM9hB,OACb4hB,EAASG,OAAO,cAEpBrI,SAAU,SAASO,EAASrH,GACxBpI,OAAOsX,MAAM9hB,OACb4hB,EAASI,QAAQpP,OAIpB2C,OAAO/K,SAAWA,OAAOsX,MAC1B,KAAM,IAAInG,OAAM,mCAepB,OAZA1B,GAAU,GAAIkmD,GAAwBvhE,GACtC4L,OAAOsX,MAAMthB,MACTjC,MAAO,yCACPG,KAAMub,EAAQ9Z,IACda,MAAO,MACPE,OAAQ,QACR+gB,gBAAgB,IAEpBhI,EAAQha,SACRsV,OAAO0E,QAAUA,EAGV2H,EhEoieXtkB,GAAQY,SgErheJiiE,wBAAyBA,EACzBN,6BAA8BA,EAC9BrH,4BAA6BA,KhEwheJ72D,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,KAIjI,SAAUF,EAAQC,EAASC,GAEjC,YiErzhBA,SAAS4tE,GAAoBhsC,EAAGC,GAC5B,GAAiB,IAAbD,EAAEp/B,OACF,MAAOq/B,GAAEr/B,MAEb,IAAiB,IAAbq/B,EAAEr/B,OACF,MAAOo/B,GAAEp/B,MAGb,IAGI4gB,GAHAyqD,IAIJ,KAAKzqD,EAAI,EAAGA,GAAKye,EAAEr/B,OAAQ4gB,IACvByqD,EAAOzqD,IAAMA,EAIjB,IAAI6jB,EACJ,KAAKA,EAAI,EAAGA,GAAKrF,EAAEp/B,OAAQykC,IACvB4mC,EAAO,GAAG5mC,GAAKA,CAInB,KAAK7jB,EAAI,EAAGA,GAAKye,EAAEr/B,OAAQ4gB,IACvB,IAAK6jB,EAAI,EAAGA,GAAKrF,EAAEp/B,OAAQykC,IACnBpF,EAAEk9B,OAAO37C,EAAI,KAAOwe,EAAEm9B,OAAO93B,EAAI,GACjC4mC,EAAOzqD,GAAG6jB,GAAK4mC,EAAOzqD,EAAI,GAAG6jB,EAAI,GAEjC4mC,EAAOzqD,GAAG6jB,GAAK34B,KAAK6iC,IAChB08B,EAAOzqD,EAAI,GAAG6jB,EAAI,GAAK,EACvB34B,KAAK6iC,IACD08B,EAAOzqD,GAAG6jB,EAAI,GAAK,EACnB4mC,EAAOzqD,EAAI,GAAG6jB,GAAK,GAQvC,OAAO4mC,GAAOhsC,EAAEr/B,QAAQo/B,EAAEp/B,QjEgxhB9BpC,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,IA8DXP,EAAQY,QiE30hBOitE,GjE+0hBT,SAAU9tE,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUE,EAAGD,GAkBlD,QAAS+J,GAAuBxJ,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,GAhBvFL,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GkEp5hBX,IAAA08B,GAAAh9B,EAAA,GACAgO,GlEw5hBiB/D,EAAuB+yB,GkEx5hBxCh9B,EAAA,IlE45hBIiO,EAAWhE,EAAuB+D,GkE35hBtCF,EAAA9N,EAAA,GlE+5hBI+N,EAAuB9D,EAAuB6D,GkE75hB9CnF,EAAQ1I,EAAS0I,MAAM9H,QACvBO,WAAY,SAASC,GACjBA,EAAUA,MACVA,EAAQ0iD,QAAU1iD,EAAQ0iD,SAAW92C,OAAOC,KAAKvG,GACjDrF,KAAKwI,KACDi6C,QAAS1iD,EAAQ0iD,QACjB+pB,aACI9sE,MAAO,qBACPoS,YAAa,4EACbhF,iBAAkB/M,EAAQ0iD,QAA1B,sBACA5mB,KAAM,UACND,SAAU,QAEd6wC,UACI/sE,MAAO,kBACPoS,YAAa,+CACb+pB,KAAM,gBACN/uB,iBAAkB/M,EAAQ0iD,QAA1B,mBACAtmB,aAAc,gBACdP,SAAU,QAEd8wC,eACIhtE,MAAO,gCACPoS,YAAa,wEACbhF,iBAAkB/M,EAAQ0iD,QAA1B,wBACA5mB,KAAM,gBACND,SAAU,QAEd+wC,aACIjtE,MAAO,4CACPoS,YACI,sJACJhF,iBAAkB/M,EAAQ0iD,QAA1B,sBACA5mB,KAAM,WACNM,aAAc,mBACdP,SAAU,QAEdgxC,SACIltE,MAAO,iBACPoS,YAAa,mDACbhF,iBAAkB/M,EAAQ0iD,QAA1B,kBACA5mB,KAAM,SACNM,aAAc,mBACdC,YAAa,YAEjBywC,iBACIntE,MAAO,yBACPoS,YAAa,kEACbhF,iBAAkB/M,EAAQ0iD,QAA1B,0BACA5mB,KAAM,YACNM,aAAc,eACdP,SAAU,QAEdkxC,SACIptE,MAAO,iBACPoS,YAAa,uCACb+pB,KAAM,YACN10B,QAAS,WACLuP,OAAO6lB,SAASz1B,KAAU6E,OAAOqE,KAAjC,qDAGR+8D,eACIrtE,MAAO,uBACPoS,YAAa,sDACb+pB,KAAM,WACN10B,QAAS,WACLuP,OAAO6lB,SAASz1B,KAAU6E,OAAOqE,KAAjC,kBAGRg9D,QACIttE,MAAO,WACPoS,YAAa,0CACb+pB,KAAM,cACN10B,QAAS,WACLwE,OAAOsX,MAAMthB,MACTjC,MAAO,WACPG,KAAM,+DACNk8B,SACIkxC,OAAQ,WACJthE,OAAOsX,MAAM9hB,QAEjB+rE,WAAY,WACRx2D,OAAO6lB,SAASz1B,KAAU6E,OAAOqE,KAAjC,kCACIrE,OAAOwhE,8BAYvC7tE,EAAOX,EAASW,KAAKC,QACrBG,MAAO,mBACPI,WAAY,WACRE,KAAK0I,MAAQ,GAAIrB,GACjBrH,KAAKC,WAAW,UAChBD,KAAKoB,UAGTA,OAAQ,WACJ,GAAIT,GAAOX,KACPwS,EAAS7G,OAAO6G,MACpB3T,GAAEguB,QAAWlhB,OAAOqE,KAApB,aAAqCrE,OAAOC,KAAKvG,GAAM,SAAAtB,GACnDpD,EAAKysE,aAAevuE,EAAE,UACjB2C,SAAS,YACTlB,OAAOzB,EAAE,SAASyB,OAAO,qBACzBA,OAAOzB,EAAE,QAAQyB,OAAV,gCAAiD1B,EAAE4M,OAAOzH,EAAKspE,OAA/D,eACP/sE,OAAQK,EAAKgO,OAAS9P,EAAE,YAAY2C,SAAS,kBAClD,IAAI6M,GAAU5B,EAAApN,QAAmB2L,IAAI,WACjCvD,EAASgF,EAAApN,QAAmB2L,IAAI,SAChCqD,IAAW5G,GACX9G,EAAKysE,aAAaxvD,QAAQ,GAAIjR,GAAAtN,QAAG+O,SAAUC,QAASA,EAAS5G,OAAQA,IAAUnG,KAE9EkR,EAAO86D,kBACR3sE,EAAK4sE,SAAS,eACd5sE,EAAK4sE,SAAS,aAEd/6D,EAAOg7D,6BACP7sE,EAAK4sE,SAAS,iBAElB5sE,EAAK4sE,SAAS,iBACd5sE,EAAK4sE,SAAS,eACd5sE,EAAK4sE,SAAS,WACV/6D,EAAOi7D,uBACP9sE,EAAK4sE,SAAS,mBAEd/6D,EAAOk7D,gBAAkBl7D,EAAO86D,iBAChC3sE,EAAK4sE,SAAS,WAEd5hE,OAAOwhE,oBACPxsE,EAAK4sE,SAAS,UAElB5sE,EAAKysE,aAAa9sE,OAAOK,EAAKgtE,gBAAgB5pE,IAC9CpD,EAAKW,IAAIS,QAAQzB,OAAOK,EAAKysE,iBAIrCG,SAAU,SAASv6B,GACf,GAAIjzC,GAAUC,KAAK0I,MAAMsC,IAAIgoC,GACzB46B,EAAO/uE,EAAEmB,KAAK6tE,cAAc9tE,IAC5B+tE,EAAKF,EAAKliE,KAAK,IACf3L,GAAQoH,QACR2mE,EAAGltE,GAAG,QAAS,WACXb,EAAQoH,YAGZ2mE,EAAGxlE,KAAK,OAAWqD,OAAOqE,KAA1B,QAAsCgjC,GAE1ChzC,KAAK2O,OAAOrO,OAAOstE,IAGvBC,cAAe,SAAS9tE,GACpB,8CACIA,EAAQ87B,KADZ,mEAGI97B,EAAQL,MAHZ,iCAIiCK,EAAQ+R,YAJzC,oBAOJ67D,gBAAiB,SAAS5tE,GACtB,0DACIA,EAAQguE,sBADZ,qDAGIpiE,OAAO6G,OAAOw7D,cAAd,+BAA6DjuE,EAAQkuE,MAArE,cAA0F,IAH9F,0MlE45hBRxvE,GAAQY,SkEn5hBJC,KAAMA,EACN+H,MAAOA,KlEs5hBkBvE,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,KAIzG,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUE,GAsB/C,QAAS8J,GAAuBxJ,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,GApBvFL,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GmElliBX,IAAAC,GAAAP,EAAA,GACAgO,GnEsliBc/D,EAAuB1J,GmEtliBrCP,EAAA,InE0liBIiO,EAAWhE,EAAuB+D,GmEzliBtCgvB,EAAAh9B,EAAA,GnE6liBIi9B,EAAahzB,EAAuB+yB,GmE5liBxCwyC,EAAAxvE,EAAA,InEgmiBIyvE,EAAYxlE,EAAuBulE,GmE/liBnCzlE,EAAa9J,EAAS8J,WAAWlJ,QACjC+vC,WAAY,SAAShP,EAAGC,GAGpB,MAFAD,GAAIA,EAAEt1B,IAAI,QACVu1B,EAAIA,EAAEv1B,IAAI,QACHs1B,EAAIC,EAAI,EAAID,EAAIC,GAAK,EAAI,KAIpCjhC,EAAOX,EAASW,KAAKC,QACrBO,WAAY,SAASC,GACjB,GAAIY,GAAOX,KACPysB,EAAa9gB,OAAO+9B,kBAAoB/9B,OAAO+9B,iBAAiBhhC,MAAMrD,EAC1ErF,MAAK0I,MAAQ,GAAI/J,GAAS0I,MAC1BrH,KAAK0I,MAAMoE,IAASnB,OAAOqE,KAA3B,iBAAgDyc,EAAhD,0BACAzsB,KAAKsP,WAAa,GAAI7G,GACtBzI,KAAKsP,WAAWxC,IAASnB,OAAOqE,KAAhC,aAAiDrE,OAAOC,KAAKvG,GAA7D,iBACArF,KAAKqO,QAAU,GAAI1B,GAAAtN,QAAG+O,YACtBpO,KAAKouE,iBAAmB,GAAIzhE,GAAAtN,QAAGgvE,OAAO/uE,MAClC4nC,UAAU,EACVziC,SAAU,WACN9D,EAAKytE,iBAAiBpvE,MAAM,OAEhCsvE,WAAY,4BACZC,WAAY,0CAEhBvuE,KAAKwuE,MAAQ,GAAIL,GAAA9uE,QAAMC,MAAOyP,IAAK,OAAQ0nB,YAAY,IACvDz2B,KAAKwuE,MAAMC,UAAU,QACrBzuE,KAAKwuE,MAAMC,UAAU,OACrBzuE,KAAKwuE,MAAMC,UAAU,4BACrBzuE,KAAKwuE,MAAMC,UAAU,IACrBzuE,KAAKwuE,MAAME,eACX1uE,KAAKC,WACDpB,EAAE,UACGyB,OAAOzB,EAAE,SAASiG,KAAK,0BACvBxE,OAAON,KAAKwuE,MAAMltE,KAClBhB,OACIN,KAAK2uE,WAAa9vE,EAAE,UAChByB,OACGzB,EAAE,SACGiG,KAAK,2BACLtD,SAAS,kBAEjBlB,OAAON,KAAKouE,iBAAiB9sE,MAErChB,OACGzB,EAAE,SACGiG,KAAK,sBACLtD,SAAS,kBAEjBlB,OACGzB,EAAE,WACG2C,SAAS,aACTlB,OACGzB,EAAE,UACG2C,SAAS,kBACTlB,OAAON,KAAKqO,QAAQ/M,KACpBhB,OAAQN,KAAK4uE,MAAQ/vE,EAAE,UAAU2C,SAAS,mBAElDlB,OAAQN,KAAK2P,MAAQ9Q,EAAE,UAAU2C,SAAS,sBAG3DxB,KAAK4O,SAAS5O,KAAKsP,WAAY,mBAAoB,WAC/C3O,EAAK0P,iBAETrQ,KAAK4O,SAAS5O,KAAK0I,MAAO,SAAU,WAChC/H,EAAKkuE,gBAET7uE,KAAKsP,WAAWob,QAChB1qB,KAAK0I,MAAMgiB,SAGftpB,OAAQ,WACJpB,KAAKqQ,eACLrQ,KAAK6uE,eAGTx+D,aAAc,WACV,GAAI1P,GAAOX,IACXA,MAAKwuE,MAAMM,SACX9uE,KAAKsP,WAAW7D,OAChBzL,KAAKsP,WAAWpE,KAAK,SAAAxC,GACjB/H,EAAK6tE,MAAMrpE,IAAIuD,EAAMsC,IAAI,SACzBrK,EAAK6tE,MAAMrpE,IAAIuD,EAAMrD,IACrB1E,EAAK6tE,MAAMrpE,QAA2BrD,KAAvB4G,EAAMsC,IAAI,SAAyBtC,EAAMsC,IAAI,SAAW,iBACvErK,EAAK6tE,MAAMrpE,IACP,GAAIwH,GAAAtN,QAAG0vE,YACHlzC,KAAM,aACN9sB,IAAK,uBACL9H,QAAS,uBACTE,QAAS,WACLuB,EAAM4Q,aAEXhY,KAEPX,EAAK6tE,MAAMluE,OAAOoI,EAAMrD,OAIhCwpE,YAAa,WACT,GAAIluE,GAAOX,KAEPiT,EAAO,GAAA0oB,GAAAt8B,SACPy8B,SAEQpY,KAAM,OACN/V,KAAM,OACNlE,MAAO,OACP26B,KAAM,uCAGN1gB,KAAM,OACN/V,KAAM,KACNlE,MAAO,MACP26B,KAAM,yCAGNz2B,KAAM,MACN+V,KAAM,cACN0kB,YACIz6B,KAAM,OACNlE,MAAO,aACP26B,KAAM,2BACN1gB,KAAM,SACN1kB,MAvBG,QAwBH+E,OAEQ/E,MAAO,QACPyK,MAAO,4BAGPzK,MAAO,OACPyK,MAAO,uBAGPzK,MAAO,OACPyK,MAAO,4BAInB4+B,QAEQrpC,MAAO,QACP88B,SAEQpY,KAAM,SACN/V,KAAM,QACNlE,MAAO,aACP1F,KAAM/D,KAAK0I,MAAMsC,IAAI,kBAK7BhM,MAAO,OACP88B,SAEQpY,KAAM,SACN/V,KAAM,QACNlE,MAAO,WACP1F,KAAM/D,KAAK0I,MAAMsC,IAAI,gBAK7BhM,MAAO,OACP88B,SAEQpY,KAAM,OACNsrD,MAAM,EACNrhE,KAAM,QACNlE,MAAO,mBAO/BsyB,SACIhwB,KAAM,GAAIY,GAAAtN,QAAG48B,QACTJ,KAAM,UACN50B,QAAS,mBACTvH,MAAO,OACPqP,IAAK,iCACL5H,QAAS,WACL,GAAIpD,GAAOkP,EAAKlP,KAAK4qB,QAChB5qB,GAAKsB,IAAOtB,EAAK4J,KAMlBhN,EAAK2O,WAAWqf,OAAO5qB,GACnBi6B,MAAM,EACN9tB,QAAS,SAAS6D,GACVA,EAAS/I,IAAI,WACbrK,EAAK0N,QAAQ3I,QACT2I,QAAS0F,EAAS/I,IAAI,WACtBvD,OAAQ,YAGZ9G,EAAK0N,QAAQ3I,QACT2I,QAAS,yCACT5G,OAAQ,aAIpB6I,MAAO,SAASyD,EAAUsX,GACtB,GAAIhd,GAAUgd,GAAOA,EAAIxL,cAAgBwL,EAAIxL,aAAa1L,OAC1DxT,GAAK0N,QAAQ3I,QACT2I,QAASA,GAAW,iCACpB5G,OAAQ,cAxBpB9G,EAAK0N,QAAQ3I,QACT2I,QAAS,2BACT5G,OAAQ,eA8B5BhD,SAAU,WACN,GAAIi4B,GAAWzpB,EAAKlP,KAAKo/B,MAAM,WAC/B,IAAIzG,EAAU,CACV,GAAIuyC,GAAch8D,EAAK0pB,WAAWD,EAClC/7B,GAAKuuE,YAAYD,EAAYjwE,YAIzCgB,MAAK4uE,MAAM7sE,QAAQzB,OAAO2S,EAAK3R,IAC/B,IAAI8sE,GAAmBpuE,KAAK0I,MAAMsC,IAAI,mBAClCojE,IAAoBA,EAAiBltE,QACrClB,KAAK2uE,WAAWhtE,OAChB3B,KAAKouE,iBAAiB1oE,OAAO1F,KAAK0I,MAAMsC,IAAI,sBAE5ChL,KAAK2uE,WAAWxtE,OAEpBnB,KAAKkvE,YArIc,UAwIvBA,YAAa,SAASC,GAClBnvE,KAAK2P,MACA5N,QACAP,SAAS,oBACTH,KAAiB,SAAZ8tE,EAAsBnvE,KAAKovE,iBAAmBpvE,KAAKqvE,iBAGjEA,aAAc,WACV,MACI,0lBAsBRD,eAAgB,WACZ,MACI,+UnE+hiBZ3wE,GAAQY,SmE3giBJC,KAAMA,KnE8giBmBwD,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,KAIjF,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUE,EAAGD,GAElDE,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GoE7ziBX,IAAAygD,GAAA/gD,EAAA,IpEk0iBIghD,EAEJ,SAAgCvgD,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,IAF/CsgD,GoEj0iBpCngD,EAAOX,EAASW,KAAKC,QACrBO,WAAY,SAASC,GACjB,GAAIY,GAAOX,IACXA,MAAKC,WAAWpB,EAAE,WAClBmB,KAAK0I,MAAQ,GAAI/J,GAAS0I,MAAMtH,GAChCC,KAAKy+B,KAAOz+B,KAAK0I,MAAMsC,IAAI,QAC3BhL,KAAKN,MAAQM,KAAK0I,MAAMsC,IAAI,UAC5BnM,EAAEiH,MACEgH,IAAQnB,OAAOqE,KAAOhQ,KAAKy+B,KAA3B,IAAmCz+B,KAAK0I,MAAMsC,IAAI,aAAlD,IAAkEnM,EAAEuO,MAAMzB,OAAO0B,QACjF6C,QAAS,SAAS6D,GACdA,EAAA,aAA0B,EAC1BpT,EAAK+H,MAAMF,IAAIuL,GACfpT,EAAKS,aAKjBA,OAAQ,WACJ,GAAIkuE,GAAO,GAAA5vB,GAAArgD,QAAaW,KAAK0I,MAAMmI,WACnC7Q,MAAKsB,IAAIS,QAAQzB,OAAOgvE,EAAKhuE,KAC7BtB,KAAKsB,IAAIhB,OAAON,KAAKuvE,oBAGzBA,gBAAiB,WACb,GAAI5uE,GAAOX,KACPwvE,EAAQ3wE,cAAcmB,KAAK0I,MAAMsC,IAAI,UAA7B,yCACRjL,EAAUC,KAAK0I,MAAMmI,UACzB,IAAI9Q,EAAQ0vE,kBAAoB1vE,EAAQ0vE,iBAAiBvuE,OAAS,EAAG,CACjE,GAAIyN,GAAS9P,EACT,8IAOJD,GAAEsM,KAAKnL,EAAQ0vE,iBAAkB,SAACjnB,EAAIjjD,GAClC,GAAImqE,GAAiB/jE,OAAOqE,KAAOrP,EAAK89B,KAApC,0CACA+pB,EAAGmnB,SADH,SAEKnnB,EAAGonB,IACZjhE,GAAOrO,OAAP,oBACwBovE,EADxB,KACwC9wE,EAAE4M,OAAOg9C,EAAG9oD,OADpD,gBAC0Ed,EAAE4M,OACpEg9C,EAAGmnB,UAFX,gBAMJH,EAAMlvE,OAAOqO,OAEb6gE,GAAMlvE,OAAN,MAAmBN,KAAK0I,MAAMsC,IAAI,UAAU01B,cAA5C,8BAEJ,OAAO8uC,KpE2ziBf/wE,GAAQY,SoEtziBJC,KAAMA,KpEyziBmBwD,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,KAIzG,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUC,EAAGC,GAsBlD,QAAS8J,GAAuBxJ,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,GApBvFL,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GqE33iBX,IAAA6wE,GAAAnxE,EAAA,IAAYoxE,ErEg5iBZ,SAAiC3wE,GAAO,GAAIA,GAAOA,EAAIC,WAAc,MAAOD,EAAc,IAAImvC,KAAa,IAAW,MAAPnvC,EAAe,IAAK,GAAIwG,KAAOxG,GAAWL,OAAOwN,UAAU8P,eAAetZ,KAAK3D,EAAKwG,KAAM2oC,EAAO3oC,GAAOxG,EAAIwG,GAAgC,OAAtB2oC,GAAOjvC,QAAUF,EAAYmvC,GAhBzNuhC,GqE/3iBzCj1B,EAAAl8C,EAAA,IrEm4iBIm8C,EAAQlyC,EAAuBiyC,GqEl4iBnCm1B,EAAArxE,EAAA,KrEs4iBIsxE,EAAkBrnE,EAAuBonE,GqEr4iB7CvjE,EAAA9N,EAAA,GrEy4iBI+N,EAAuB9D,EAAuB6D,GqEv4iB9CyjE,EAAmBtxE,EAASW,KAAKC,QACjC4J,QAAS,KACTrJ,WAAY,WACRlB,EAAEsxE,QACElwE,KACA,SACA,eACA,kBACA,mBACA,iBACA,gBAEJ8vE,EAAW/vE,QAAQowE,QAAU,MAGjC7mE,QACI8mE,4BAA6B,kBAC7BC,yBAA0B,iBAC1BC,yBAA0B,iBAC1BC,uBAAwB,gBAG5BnvE,OAAQ,WAEJ,MADAvC,GAAEmB,KAAKO,IAAIc,KAAKrB,KAAKwwE,gBACdxwE,MAGXywE,gBAAiB,WACbzwE,KAAK0I,MAAMF,IAAI,sBAAuBxI,KAAK0I,MAAMsC,IAAI,uBACrDhL,KAAK0I,MAAMqD,OAGX2K,OAAO6lB,SAAc5wB,OAAOqE,KAA5B,YAGJ0gE,eAAgB,WACZ,GAAIC,GAAS3wE,KAAK0I,MAAMsC,IAAI,OACxB0L,QAAOonC,QAAP,6CAA4D6yB,EAA5D,QACA3wE,KAAK0I,MAAM4Q,SACPpJ,QAAS,WACL4/D,EAAW5/D,QAAX,kCAAqDygE,EAArD,QAGR3wE,KAAKgC,WAIb4uE,eAAgB,WACZ,GAAIC,GAAU7wE,KAAK0I,MAAMsC,IAAI,QACzBsuD,EAAU5iD,OAAOmD,OAAP,kCAAgDg3D,EAAhD,IAA4DA,EACtEvX,KACAt5D,KAAK0I,MAAMqD,MACL4B,KAAM2rD,IAEJppD,QAAS,WACL4/D,EAAW5/D,QAAX,kCAAqD2gE,EAArD,SAAqEvX,EAArE,QAIZt5D,KAAKoB,WAIb0vE,aAAc,WACV,GAAInwE,GAAOX,KACP6wE,EAAU7wE,KAAK0I,MAAMsC,IAAI,OAC7BnM,GAAEguB,QAAW7sB,KAAK0I,MAAM+a,QAAxB,IAAmCzjB,KAAK0I,MAAMrD,GAA9C,YAA6D,SAAA0rE,GACzD,GAAIzX,cAAqBuX,EACrBG,EAAerwE,EAAK+H,MAAMsC,IAAI,QAC9BgmE,IAAgBrlE,OAAOC,KAAKiF,WAAW8+D,WACvCrW,sBAA8B0X,GAElCD,EAAOpjE,KAAO2rD,EACd34D,EAAK2O,WAAWqf,OAAOoiD,GACnBE,GAAI,EACJjzC,MAAM,EACN9tB,QAAS,WACL4/D,EAAW5/D,QAAX,iCAAoD2gE,EAApD,SAAoEvX,EAApE,MAEJhpD,MAAO,SAAS5H,EAAOwoE,EAAMnxE,GAGzB+vE,EAAWx/D,MAAMvQ,EAAQoxE,kBAGlC7gE,MAAM,SAAC8gE,EAAOC,EAAYF,GACzBrB,EAAWx/D,MAAM8gE,EAAMvxD,aAAa1L,YAI5Cq8D,aAAc,WACV,GAAI7uE,GAAO3B,KAAK0I,MAAMsC,IAAI,sBACtBsmE,EAAOtxE,KAAK0I,MAAMrD,GAClBksE,gFACA5vE,cAAmBA,EAAnB,IAA6B,IAD7B,WAEO2vE,EAFP,IAYJ,OATIE,6FAAsG5yE,EAAE4M,OACxGxL,KAAK0I,MAAMsC,IAAI,SADf,uCAEoChL,KAAKyxE,mBAFzC,oCAGAH,EAHA,kCAKAtxE,KAAK0I,MAAMsC,IAAI,WAAaW,OAAOC,KAAKiF,WAAW8+D,SAAW,MAAQ3vE,KAAK0I,MAAMsC,IAAI,UALrF,mBAMehL,KAAK0I,MAAMsC,IAAI,mBAN9B,aAOAhL,KAAK0I,MAAMsC,IAAI,aAAe,MAAQ,MAPtC,YAQQumE,EARR,SAYRG,gBAAiB,WACb,GAAIC,GAAY,GAAI92B,GAAAx7C,QAAK2J,YACrBN,MAAO1I,KAAK0I,MACZnI,GAAI1B,EAAE6M,KAAF,IAAW1L,KAAK0I,MAAMrD,GAAtB,iBACJqE,eAAe,GAEnBioE,GAAU74D,QAAO,GACjB64D,EAAUvwE,UAIdqwE,iBAAkB,WACd,MAAIzxE,MAAK0I,MAAMsC,IAAI,WAAaW,OAAOC,KAAKiF,WAAW8+D,SACnD,qDAA4DhkE,OAAOqE,KAAnE,sBACIhQ,KAAK0I,MAAMrD,GADf,+BAE+BsG,OAAOqE,KAFtC,mBAE6DhQ,KAAK0I,MAAMrD,GAFxE,8BAGIsG,OAAOqE,KAHX,uBAIuBhQ,KAAK0I,MAAMrD,GAJlC,gCAIoEsG,OAAOqE,KAJ3E,iBAKIhQ,KAAK0I,MAAMrD,GALf,qMAOIsG,OAAOqE,KAPX,6BASIhQ,KAAK0I,MAAMrD,GATf,2FAYA,qDACIsG,OAAOqE,KADX,kDAEkDhQ,KAAK0I,MAAMsC,IAAI,SAFjE,SAEkFhL,KAAK0I,MAAMsC,IACzF,QAHJ,+BAIgCW,OAAOqE,KAJvC,mBAKIhQ,KAAK0I,MAAMrD,GALf,mHAOIrF,KAAK0I,MAAMrD,GAPf,WAQWsG,OAAOqE,KARlB,uCAQ6DhQ,KAAK0I,MAAMrD,GARxE,4BAcRusE,EAAmBjzE,EAASW,KAAKC,QACjCG,MAAO,YACPI,WAAY,WACRE,KAAKC,WAAW,UAChBrB,EAAEsxE,QAAQlwE,KAAM,wBAChBA,KAAKsP,WAAa,GAAI0gE,GAAA3wE,QAAUwyE,mBAChC7xE,KAAKsP,WAAWob,QAAQjL,KAAKzf,KAAKoB,UAClCpB,KAAKsP,WAAWkJ,KAAK,MAAOxY,KAAK8xE,YACjC9xE,KAAKsP,WAAW1O,GAAG,OAAQZ,KAAKoB,OAAQpB,OAG5CsJ,QACIwN,UAAW,sBACX2C,KAAM,OACN5C,SAAU,SAAS8C,GACf9a,EAAE,6BAA6B2C,SAAS,YACxC3C,EAAE,eAAe2C,SAAS,mBAC1BmY,EAAGvE,mBAIX28D,oBAAqB,WACjBlzE,EAAE,6BAA6B0C,YAAY,YAC3C1C,EAAE,eAAe0C,YAAY,oBAGjCkY,KAAM,SAAS5Y,GAEXb,KAAK+xE,sBACLlxE,EAAEuU,gBAGF,KAAK,GAAWQ,GAFZvC,EAAQxS,EAAEsU,aAAa9B,MACvB1S,EAAOX,KACF8hB,EAAI,EAAOlM,EAAIvC,EAAMyO,GAAKA,IAC/BnhB,EAAKqxE,kBAAkBp8D,IAI/Bo8D,kBAAmB,SAASp8D,GACxB,GAAIjV,GAAOX,KACPiyE,EAAS,GAAIC,WACjBD,GAAOE,OAAS,SAAAC,GACZ,GAAIC,EACJ,KACIA,EAAUn4D,KAAKpM,MAAMmkE,EAAOphD,QAC9B,MAAOhwB,GACLivE,EAAWx/D,MAAX,wBAAyCsF,EAAEjI,KAA3C,2CACA0kE,EAAU,KAEVA,GACA1xE,EAAK2O,WAAWqf,OAAO0jD,GACnBpB,GAAI,EACJjzC,MAAM,EACN9tB,QAAS,WACL4/D,EAAW5/D,QAAX,mCAAsDmiE,EAAQ1kE,KAA9D,MAEJ2C,MAAO,SAAS5H,EAAOwoE,EAAMnxE,GACzB+vE,EAAWx/D,MAAMvQ,EAAQoxE,iBAKzCc,EAAOK,WAAW18D,EAAG,UAGzB28D,eAAgB3zE,EAAE+gB,KAAK,WAEnB,GAAI6yD,GAAW/lE,EAAApN,QAAmB2L,IAAI,UAEnB,WADFyB,EAAApN,QAAmB2L,IAAI,UAEpC8kE,EAAWx/D,MAAM1R,EAAE4M,OAAOgnE,GAAY,2DAC/BA,GACP1C,EAAWpoE,KAAK9I,EAAE4M,OAAOgnE,MAIjCpxE,OAAQ,WAEJ,GAAIuc,GAAS3d,KAAKyyE,kBAEdC,EAAkB1yE,KAAK2yE,yBACvBC,EAAgB5yE,KAAK6yE,wBACzB7yE,MAAKsB,IAAID,KAAKsc,EAAS+0D,EAAkBE,EACzC,IAAIjyE,GAAOX,IACXpB,GAAEoB,KAAKsP,WAAW6d,QAAQjiB,KAAK,SAAAuzB,GAE3B99B,EAAKmxE,WAAWrzC,GAChB99B,EAAKmyE,cAAcr0C,IACpBz+B,KAKH,OAHAA,MAAK+yE,eAAe/yE,KAAKnB,EAAE,cAAemB,KAAKnB,EAAE,uBAD5B,GAErBmB,KAAKgzE,uBACLhzE,KAAKuyE,iBACEvyE,MAGX8xE,WAAY,SAASrzC,GACjB,GAAIw0C,GAAmB,GAAIhD,IACvBvnE,MAAO+1B,EACPnvB,WAAYtP,KAAKsP,YAErBzQ,GAAE,oBAAoByB,OAAO2yE,EAAiB7xE,SAASb,IACvD0yE,EAAiBvB,mBAIrBoB,cAAe,SAASI,GACKlzE,KAAKnB,EAAL,wBAA+Bq0E,EAAS7tE,IAC9C+B,MAAM,iBACrBsP,QAAOonC,QAAP,wDAAuEo1B,EAASriE,WAAWlD,KAA3F,SAKRolE,eAAgB,SAASI,EAAiBC,EAAaC,GACnDF,EAAgBvyE,GAAG,QAAS,WACxB,GAAI0yE,GAAQz0E,EAAEmB,MAAM8L,KAGpB,IAAIwnE,EAAMpyE,QAAUmyE,EAAc,CAE9B,GAAIE,GAAqB,GAAItT,QAAOqT,EAAO,IAC3CF,GAAYjyE,OACZiyE,EACK19D,OAAO,WAGJ,MAAO69D,GAAmBtQ,KAAKpkE,EAAEmB,MAAM8E,UAE1CnD,WAELyxE,GAAYzxE,UAMxBqxE,qBAAsB,WAClBn0E,EAAEmB,KAAKO,IAAIK,GAAG,mBAAoB,WAC9B/B,EAAEmB,KAAKO,IAAIkB,IAAI,WAAY,aAE/B5C,EAAEmB,KAAKO,IAAIK,GAAG,mBAAoB,WAC9B/B,EAAEmB,KAAKO,IAAIkB,IAAI,WAAY,WAKnC+xE,oBAAqB,WACjB,MAAO,yDAIXb,uBAAwB,WACpB,mQACIhnE,OAAOqE,KADX,8IAGIrE,OAAOqE,KAHX,4CAQJ6iE,uBAAwB,WAWpB,MACIY,sTAKRhB,gBAAiB,WACb,MACI,wIAUR7uB,EAAqBjlD,EAASW,KAAKC,QACnCO,WAAY,WACRE,KAAKC,WAAW,UAChBD,KAAKoB,UAITA,OAAQ,WACJ,GAAIT,GAAOX,IACXnB,GAAEguB,QAAWlhB,OAAOqE,KAApB,kCAA2D,SAAAjQ,GACvDY,EAAKW,IAAIS,QAAQzB,OAAOK,EAAK+yE,cAAc3zE,OAKnD2zE,cAAe,SAAS3zE,GACpB,0KACI4L,OAAOqE,KADX,gMAGIjQ,EAAQ+M,IAHZ,2vBAKI/M,EAAQ4zE,wBALZ,sNrEo1iBRl1E,GAAQY,SqEz0iBJC,KAAMsyE,EACNhuB,mBAAoBA,KrE40iBK9gD,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,KAIzG,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,GAErCG,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GsExsjBX,IAAA4J,GAAAlK,EAAA,GtE6sjBImK,EAEJ,SAAgC1J,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,IAFhDyJ,GsEnsjBnCgrE,EAAej1E,EAAS0I,MAAM9H,OAAOsJ,EAAAxJ,QAAQ4J,eAAe1J,QAC5D+Y,cAPe,WASfmL,QAAY9X,OAAOqE,KAAnB,gBAEAqH,OAAQ,WAEJ,OAAS67D,SAAUlzE,KAAK6Q,eAS5BghE,EAAqBlzE,EAAS8J,WAAWlJ,QACzCmJ,MAAOkrE,EACP9mE,IAAQnB,OAAOqE,KAAf,iBtEqtjBJvR,GAAQY,SsE/sjBJu0E,aAAcA,EACd/B,mBAAoBA,KtEktjBK/uE,KAAKrE,EAASC,EAAoB,KAIzD,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUE,EAAGD,GAsBlD,QAAS+J,GAAuBxJ,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,GApBvFL,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GuE9vjBX,IAAAC,GAAAP,EAAA,GvEmwjBIQ,EAAUyJ,EAAuB1J,GuElwjBrCwgD,EAAA/gD,EAAA,IvEswjBIghD,EAAa/2C,EAAuB82C,GuErwjBxC8S,EAAA7zD,EAAA,IvEywjBI08D,EAAiBzyD,EAAuB4pD,GuExwjB5CT,EAAApzD,EAAA,IvE4wjBIqzD,EAAeppD,EAAuBmpD,GuE3wjBtCxyD,EAAOX,EAASW,KAAKC,QACrBG,MAAO,YACPI,WAAY,SAASC,GACjB,GAAIY,GAAOX,IACXA,MAAKC,WAAWpB,EAAE,WAClBmB,KAAK0I,MAAQ,GAAI/J,GAAS0I,MAC1BnI,EAAAG,QAAM2L,KACF8B,IAAQnB,OAAOqE,KAAf,WAA8BjQ,EAAQ4iD,UAAtC,IAAmD9jD,EAAEuO,MAAMzB,OAAO0B,QAClE6C,QAAS,SAAS6D,GACdA,EAAA,aAA0B,EAC1BnV,EAAEsM,KAAK6I,EAAA,WAAwB,SAAA8/D,GACJ,QAAnBA,EAAUpqE,QACVoqE,EAAU1sE,QAAU,SAAA9B,GAChB1E,EAAKmzE,gBAAgBzuE,OAIjC1E,EAAK+H,MAAMF,IAAIuL,GACfpT,EAAKS,aAKjBA,OAAQ,WACJ,GAAIkuE,GAAO,GAAA5vB,GAAArgD,QAAaW,KAAK0I,MAAMmI,WACnC7Q,MAAKsB,IAAIS,QAAQzB,OAAOgvE,EAAKhuE,MAGjCwyE,gBAAiB,SAASzuE,GACtB,GAAIyjB,GAAU,GAAIsyC,GAAA/7D,QAAagpB,SAAUhjB,GAAIA,GAC7CyjB,GACK4B,QACAlL,KAAK,WACFxI,MAAM,mEAETyI,KAAK,YACF,EAAAsyC,EAAA1yD,SAAkBypB,MAAarJ,KAAK,WAC5B/I,OAAOrW,QAAUqW,OAAOrW,OAAOsL,QAAU+K,OAAOrW,OAAOsL,OAAO+9B,kBAC9DhzB,OAAOrW,OAAOsL,OAAO+9B,iBAAiBsnB,qBAE1Ct6C,OAAO6lB,SAASw3C,QAAO,SvEmxjB3Ct1E,GAAQY,SuE5wjBJC,KAAMA,KvE+wjBmBwD,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,KAIzG,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUE,GAkB/C,QAAS8J,GAAuBxJ,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,GAhBvFL,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GwE70jBX,IAAAC,GAAAP,EAAA,GxEk1jBIQ,EAAUyJ,EAAuB1J,GwEj1jBrCyN,EAAAhO,EAAA,GxEq1jBIiO,EAAWhE,EAAuB+D,GwEp1jBtCgvB,EAAAh9B,EAAA,GxEw1jBIi9B,EAAahzB,EAAuB+yB,GwEt1jBpCp8B,EAAOX,EAASW,KAAKC,QACrBO,WAAY,WACRE,KAAKC,WAAW,UAChBD,KAAK0I,MAAQ,GAAI/J,GAAS0I,OACtBm0C,WAAY7vC,OAAO0B,OAAOmuC,aAE9Bx7C,KAAKoB,UAITA,OAAQ,WACJ,GAAI4yE,GAAcroE,OAAOqE,KAArB,gBAAyChQ,KAAK0I,MAAMsC,IAAI,cAExDrK,EAAOX,IAEXd,GAAAG,QAAM2L,KACF8B,IAAKknE,EACL9jE,QAAS,SAAS6tB,GACd,GAAIk2C,GAAatoE,OAAOqE,KAApB,YAAoC+tB,EAAQge,aAA5C,YACJ78C,GAAAG,QAAM2L,KACF8B,IAAKmnE,EACL/jE,QAAS,SAASgkE,GACGvoE,OAAOqE,KAAgB+tB,EAAQge,YAChDp7C,GAAKwzE,kBAAkBxzE,EAAMo9B,EAASm2C,IAE1C5jE,MAAO,SAASyD,GACZ,GAAIqgE,IACA3sE,OAAQ,QACR4G,QAAS,uCACTC,YAAY,EACZS,IAAK,eAETpO,GAAK0zE,gBAAgBD,EAAgBzzE,EAAK9B,EAAE,0BAIxDyR,MAAO,SAASyD,GACZ,GAAIqgE,IACA3sE,OAAQ,QACR4G,QAAS,2CACTC,YAAY,EACZS,IAAK,eAETpO,GAAK0zE,gBAAgBD,EAAgBzzE,EAAK9B,EAAE,0BAMxDs1E,kBAAmB,SAASxzE,EAAMo9B,EAASm2C,GACvCvzE,EAAKW,IAAIS,QAAQzB,OAAOK,EAAK8xE,mBAC7B9xE,EAAKW,IAAIhB,OAAO,0BAChBK,EAAKW,IAAIhB,OAAT,iDAAiE4zE,EAAIzrC,QAArE,aACA9nC,EAAKW,IAAIhB,OAAO,2DAChBK,EAAKW,IAAIhB,OAAT,qBAAqC4zE,EAAII,OAAzC,UACA3zE,EAAKW,IAAIhB,OAAO,+BAChBK,EAAKW,IAAIhB,OACL,oUAEJK,EAAKW,IAAIhB,OAAOK,EAAK4zE,oBAAoBx2C,EAASm2C,KAItDG,gBAAiB,SAAStgE,EAAUzS,EAAKkzE,EAAYC,GAC5CA,EAOGD,EACAlzE,EAAIhB,OAAO,GAAIqM,GAAAtN,QAAGq1E,iBAAiB3gE,GAAUzS,KAE7CA,EAAIS,QAAQV,KAAK,GAAIsL,GAAAtN,QAAGq1E,iBAAiB3gE,GAAUzS,KATnDkzE,EACAlzE,EAAIhB,OAAO,GAAIqM,GAAAtN,QAAG+O,QAAQ2F,GAAUzS,KAEpCA,EAAIS,QAAQV,KAAK,GAAIsL,GAAAtN,QAAG+O,QAAQ2F,GAAUzS,MAYtDmxE,gBAAiB,WACb,MAAO,oFAIX8B,oBAAqB,SAASx2C,EAASm2C,GACnC,GAAIvzE,GAAOX,KACP87B,IAEIsI,KAAM,qBACNrkC,WACA2jB,KAAM,OACN/V,KAAM,QACNlE,MAAO,aACPzK,MAAO2M,OAAOC,KAAKZ,IAAI,WAGvBo5B,KAAM,gGACNrkC,WACA2jB,KAAM,OACNsrD,MAAM,EACNrhE,KAAM,UACNlE,MAAO,YAmBXwJ,EAAO,GAAA0oB,GAAAt8B,SACPK,MAAO,eACPo8B,OAAQA,EACRC,SACIhwB,KAAM,GAAIY,GAAAtN,QAAG48B,QACTJ,KAAM,SACNn8B,MAAO,SACPqP,IAAK,4BACL4lE,SAAU,QACVxtE,QAAS,WACL,GAAIytE,GAAY3hE,EAAKlP,KAAK4qB,SACtB7hB,EAASnB,OAAOqE,KAAhB,YAAgCkkE,EAAI7uE,GAApC,QACJuvE,GAAUp5B,WAAazd,EAAQ14B,GAC/B1E,EAAKq7B,OAAO44C,EAAW9nE,QAKvC,OAAOmG,GAAK3R,KAIhB06B,OAAQ,SAAS44C,EAAW9nE,GACxB,GAAInM,GAAOX,IAEXnB,GAAEiH,MACE4d,KAAM,OACN5W,IAAKA,EACL/I,KAAM6wE,EACN1kE,QAAS,SAAS6D,GAEdpT,EAAKW,IAAIS,QAAQzB,OAAOK,EAAK8xE,mBAE7B1+D,EAASmxB,SAAS/oB,QAAQ,SAAA9N,GACtB1N,EAAK0zE,iBAEG5sE,OAAQ4G,EAAQ,GAChBA,QAASA,EAAQ,GACjBC,YAAY,GAEhB3N,EAAK9B,EAAE,sBACP,GACA,MAIZyR,MAAO,SAASyD,GACZ,GAAIqgE,IACA3sE,OAAQ,QACR4G,QAAS,iFACTC,YAAY,EACZS,IAAK,eAETpO,GAAK0zE,gBAAgBD,EAAgBzzE,EAAK9B,EAAE,2BxEu1jB5DJ,GAAQY,SwEh1jBJC,KAAMA,KxEm1jBmBwD,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,KAIjF,SAAUF,EAAQC,EAASC,GAEjC,cAC4B,SAASC,EAAUE,EAAGD,GAsBlD,QAAS+J,GAAuBxJ,GAAO,MAAOA,IAAOA,EAAIC,WAAaD,GAAQE,QAASF,GApBvFL,OAAOC,eAAeN,EAAS,cAC3BO,OAAO,GyErhkBX,IAAAC,GAAAP,EAAA,GACAgoD,GzEyhkBc/9C,EAAuB1J,GyEzhkBrCP,EAAA,KzE6hkBIioD,EAAWh+C,EAAuB+9C,GyE5hkBtCh6C,EAAAhO,EAAA,GzEgikBIiO,EAAWhE,EAAuB+D,GyE/hkBtCgvB,EAAAh9B,EAAA,GzEmikBIi9B,EAAahzB,EAAuB+yB,GyElikBpCp8B,EAAOX,EAASW,KAAKC,QACrBO,WAAY,WACRE,KAAKC,WAAW,UAChBD,KAAK0I,MAAQ,GAAI/J,GAAS0I,OACtBm0C,WAAY7vC,OAAO0B,OAAOmuC,aAE9Bx7C,KAAKqO,QAAU,GAAI1B,GAAAtN,QAAG+O,SAAUE,YAAY,IAC5CtO,KAAK8nD,KAAO9nD,KAAK60E,cACjB70E,KAAKsB,IACAhB,OAAOzB,EAAE,SAASyB,OAAO,4BACzBA,OAAON,KAAKqO,QAAQ/M,KACpBhB,OAAO,QACPA,OAAON,KAAK8nD,KAAKxmD,KACjBH,OACLnB,KAAKoB,UAITA,OAAQ,WACJ,GAAIT,GAAOX,IACXnB,GAAEiH,MACEgH,IAAQnB,OAAOqE,KAAf,+BAAkDrP,EAAK+H,MAAMsC,IAAI,cACjEkF,QAAS,SAAS6D,IACbpT,EAAKm0E,iBAAmBn0E,EAAK0N,QAAQ3I,OAAOqO,GAC7CpT,EAAKm0E,iBAAkB,EACvBl2E,EAAEsM,KAAKvK,EAAK+iC,MAAO,SAACzwB,EAAMtN,GACtBsN,EAAKvK,MAAMF,IAAI,SAAUuL,EAAYpO,EAAZ,YACzBsN,EAAKvK,MAAMF,IAAI,kBAAmBuL,EAAYpO,EAAZ,aAClCsN,EAAK7R,WAETT,EAAKW,IAAIK,QAEb2O,MAAO,SAASyD,GACZ,GAAII,GAAUJ,EAAS8L,cAAgB9L,EAAS8L,aAAa1L,OAC7DxT,GAAK0N,QAAQ3I,QACT+B,OAAQ,SACR4G,QAAS8F,GAAW,iDAOpCkoB,QAAS,SAASw3C,EAAW5gE,GACzB,GAAItS,GAAOX,KACP+D,EAAOkP,EAAKlP,KAAK4qB,QACrB5qB,GAAKy3C,WAAax7C,KAAK0I,MAAMsC,IAAI,cACjCjH,EAAK8vE,UAAYA,EACjBh1E,EAAEiH,MACE4d,KAAM,MACN5W,IAAQnB,OAAOqE,KAAf,mBACAjM,KAAMA,EACNmM,QAAS,SAAS6D,GACdpT,EAAK0N,QAAQ3I,OAAOqO,GACpBpT,EAAKS,SACLT,EAAKo0E,kBAETzkE,MAAO,SAASyD,GACZ,GAAII,GAAUJ,EAAS8L,cAAgB9L,EAAS8L,aAAa1L,OAC7DxT,GAAK0N,QAAQ3I,QACT+B,OAAQ,SACR4G,QAAS8F,GAAW,4DAOpC0gE,YAAa,WACT70E,KAAK0jC,OACDsxC,UAAWh1E,KAAKi1E,gBAChBC,WAAYl1E,KAAKm1E,iBACjBC,SAAUp1E,KAAKq1E,eACfC,WAAYt1E,KAAKu1E,iBAErB,IAAIztB,GAAO,GAAInB,GAAAtnD,QAAKC,IA6BpB,OA5BAwoD,GAAK3iD,KACDE,GAAI,YACJ3F,MAAO,aACPm8B,KAAM,aACN50B,QAAS,0BACT3F,IAAKtB,KAAK0jC,MAAMsxC,UAAU1zE,MAE9BwmD,EAAK3iD,KACDE,GAAI,UACJ3F,MAAO,UACPm8B,KAAM,UACN50B,QAAS,wBACT3F,IAAKtB,KAAK0jC,MAAMwxC,WAAW5zE,MAE/BwmD,EAAK3iD,KACDE,GAAI,WACJ3F,MAAO,YACPm8B,KAAM,cACN50B,QAAS,mBACT3F,IAAKtB,KAAK0jC,MAAM0xC,SAAS9zE,MAE7BwmD,EAAK3iD,KACDE,GAAI,cACJ3F,MAAO,cACPm8B,KAAM,UACN50B,QAAS,cACT3F,IAAKtB,KAAK0jC,MAAM4xC,WAAWh0E,MAExBwmD,GAIXmtB,cAAe,WACX,GAAIt0E,GAAOX,KACPiT,EAAO,GAAA0oB,GAAAt8B,SACPK,MAAO,kBACP81E,YACIC,kBAAmB,GAAI9oE,GAAAtN,QAAG0vE,YACtB9nE,QAAS,kCACT40B,KAAM,cACNn8B,MAAO,OACPyH,QAAS,WACLxG,EAAK07B,QAAQ,aAAcppB,MAGnCyiE,kBAAmB,GAAI/oE,GAAAtN,QAAG0vE,YACtB9nE,QACI,sGACJ40B,KAAM,UACNn8B,MAAO,cACPyH,QAAS,WACLxG,EAAK07B,QAAQ,aAAcppB,QAK3C,OAAOA,IAIXkiE,eAAgB,WACZ,GAAIx0E,GAAOX,KACPiT,EAAO,GAAA0oB,GAAAt8B,SACPK,MAAO,wBACP81E,YACIG,kBAAmB,GAAIhpE,GAAAtN,QAAG0vE,YACtB9nE,QAAS,wCACTvH,MAAO,mBACPm8B,KAAM,cACN10B,QAAS,WACLxG,EAAK07B,QAAQ,aAAcppB,QAK3C,OAAOA,IAIXoiE,aAAc,WACV,GAAI10E,GAAOX,KACPiT,EAAO,GAAA0oB,GAAAt8B,SACPK,MAAO,kBACP81E,YACII,gBAAiB,GAAIjpE,GAAAtN,QAAG0vE,YACpB9nE,QAAS,qCACTvH,MAAO,kBACPm8B,KAAM,cACN10B,QAAS,WACLxG,EAAK07B,QAAQ,WAAYppB,QAKzC,OAAOA,IAIXsiE,eAAgB,WACZ,GAAI50E,GAAOX,KACPiT,EAAO,GAAA0oB,GAAAt8B,SACPK,MAAO,6BACP81E,YACIK,kBAAmB,GAAIlpE,GAAAtN,QAAG0vE,YACtB9nE,QAAS,oBACTvH,MAAO,mBACPm8B,KAAM,eACN10B,QAAS,WACLxG,EAAK07B,QAAQ,aAAcppB,QAK3C,OAAOA,IAIX8hE,eAAgB,WACRr+D,OAAO/K,QACP+K,OAAO/K,OAAO+9B,iBAAiBsnB,uBzEsikB3CvyD,GAAQY,SyEhikBJC,KAAMA,KzEmikBmBwD,KAAKrE,EAASC,EAAoB,GAAIA,EAAoB,GAAIA,EAAoB,OAG5G","file":"analysis.bundled.js","sourcesContent":["webpackJsonp([0],[\n/* 0 */,\n/* 1 */,\n/* 2 */,\n/* 3 */,\n/* 4 */,\n/* 5 */,\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */,\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar View = Backbone.View.extend({\n optionsDefault: {\n with_close: true,\n title: null,\n placement: \"top\",\n container: \"body\",\n body: null\n },\n\n initialize: function initialize(options) {\n this.setElement(this._template());\n this.uid = _utils2.default.uid();\n this.options = _.defaults(options || {}, this.optionsDefault);\n this.options.container.parent().append(this.el);\n this.$title = this.$(\".popover-title-label\");\n this.$close = this.$(\".popover-close\");\n this.$body = this.$(\".popover-content\");\n\n // add initial content\n this.options.body && this.append(this.options.body);\n\n // add event to hide if click is outside of popup and not on container\n var self = this;\n $(\"body\").on(\"mousedown.\" + this.uid, function (e) {\n // the 'is' for buttons that trigger popups\n // the 'has' for icons within a button that triggers a popup\n self.visible && !$(self.options.container).is(e.target) && !$(self.el).is(e.target) && $(self.el).has(e.target).length === 0 && self.hide();\n });\n },\n\n /**\n * Render popover\n */\n render: function render() {\n this.$title.html(this.options.title);\n this.$el.removeClass().addClass(\"ui-popover popover fade in\").addClass(this.options.placement);\n this.$el.css(this._get_placement(this.options.placement));\n\n // configure close option\n var self = this;\n if (this.options.with_close) {\n this.$close.on(\"click\", function () {\n self.hide();\n }).show();\n } else {\n this.$close.off().hide();\n }\n },\n\n /**\n * Set the popover title\n * @params{ String } newTitle - New popover title\n */\n title: function title(newTitle) {\n if (newTitle !== undefined) {\n this.options.title = newTitle;\n this.$title.html(newTitle);\n }\n },\n\n /**\n * Show popover\n */\n show: function show() {\n this.render();\n this.$el.show();\n this.visible = true;\n },\n\n /**\n * Hide popover\n */\n hide: function hide() {\n this.$el.hide();\n this.visible = false;\n },\n\n /**\n * Append new content to the popover\n * @params{ Object } $el - Dom element\n */\n append: function append($el) {\n this.$body.append($el);\n },\n\n /**\n * Remove all content\n */\n empty: function empty() {\n this.$body.empty();\n },\n\n /**\n * Remove popover\n */\n remove: function remove() {\n $(\"body\").off(\"mousedown.\" + this.uid);\n this.$el.remove();\n },\n\n /**\n * Improve popover location/placement\n */\n _get_placement: function _get_placement(placement) {\n // get popover dimensions\n var width = this._get_width(this.$el);\n var height = this.$el.height();\n\n // get container details\n var $container = this.options.container;\n var container_width = this._get_width($container);\n var container_height = this._get_height($container);\n var container_position = $container.position();\n\n // get position\n var top;\n\n var left;\n top = left = 0;\n if ([\"top\", \"bottom\"].indexOf(placement) != -1) {\n left = container_position.left - width + (container_width + width) / 2;\n switch (placement) {\n case \"top\":\n top = container_position.top - height - 5;\n break;\n case \"bottom\":\n top = container_position.top + container_height + 5;\n break;\n }\n } else {\n top = container_position.top - height + (container_height + height) / 2;\n switch (placement) {\n case \"right\":\n left = container_position.left + container_width;\n break;\n }\n }\n return { top: top, left: left };\n },\n\n /**\n * Returns padding/margin corrected width\n */\n _get_width: function _get_width($el) {\n return $el.width() + parseInt($el.css(\"padding-left\")) + parseInt($el.css(\"margin-left\")) + parseInt($el.css(\"padding-right\")) + parseInt($el.css(\"margin-right\"));\n },\n\n /**\n * Returns padding corrected height\n */\n _get_height: function _get_height($el) {\n return $el.height() + parseInt($el.css(\"padding-top\")) + parseInt($el.css(\"padding-bottom\"));\n },\n\n /**\n * Return the popover template\n */\n _template: function _template(options) {\n return '
' + '
' + '
' + '
' + '' + \"
\" + '
' + \"
\";\n }\n}); /**\n * Popover wrapper\n */\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n//==============================================================================\n/** Map of possible HDA/collection/job states to their string equivalents.\n * A port of galaxy.model.Dataset.states.\n */\nvar STATES = {\n // NOT ready states\n /** is uploading and not ready */\n UPLOAD: \"upload\",\n /** the job that will produce the dataset queued in the runner */\n QUEUED: \"queued\",\n /** the job that will produce the dataset is running */\n RUNNING: \"running\",\n /** metadata for the dataset is being discovered/set */\n SETTING_METADATA: \"setting_metadata\",\n\n // ready states\n /** was created without a tool */\n NEW: \"new\",\n /** has no data */\n EMPTY: \"empty\",\n /** has successfully completed running */\n OK: \"ok\",\n\n /** the job that will produce the dataset paused */\n PAUSED: \"paused\",\n /** metadata discovery/setting failed or errored (but otherwise ok) */\n FAILED_METADATA: \"failed_metadata\",\n //TODO: not in trans.app.model.Dataset.states - is in database\n /** not accessible to the current user (i.e. due to permissions) */\n NOT_VIEWABLE: \"noPermission\",\n /** deleted while uploading */\n DISCARDED: \"discarded\",\n /** the tool producing this dataset failed */\n ERROR: \"error\"\n};\n\nSTATES.READY_STATES = [STATES.OK, STATES.EMPTY, STATES.PAUSED, STATES.FAILED_METADATA, STATES.NOT_VIEWABLE, STATES.DISCARDED, STATES.ERROR];\n\nSTATES.NOT_READY_STATES = [STATES.UPLOAD, STATES.QUEUED, STATES.RUNNING, STATES.SETTING_METADATA, STATES.NEW];\n\n//==============================================================================\nexports.default = STATES;\n\n/***/ }),\n/* 12 */,\n/* 13 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * A plugin for initializing select2 input items.\n * Make sure the select2 library itself is loaded beforehand.\n * Also the element to which select2 will be appended has to\n * be created before select2 initialization (and passed as option).\n */\nvar View = Backbone.View.extend({\n // options\n optionsDefault: {\n css: \"\",\n placeholder: \"No data available\",\n data: [],\n value: null,\n multiple: false,\n minimumInputLength: 0,\n // example format of initial data: \"id:name,55:anotherrole@role.com,27:role@role.com\"\n initialData: \"\"\n },\n\n // initialize\n initialize: function initialize(options) {\n // configure options\n this.options = _utils2.default.merge(options, this.optionsDefault);\n\n // create new element\n this.setElement(this._template(this.options));\n\n // check if container exists\n if (!this.options.container) {\n console.log(\"ui-select::initialize() : container not specified.\");\n return;\n }\n\n // add to dom\n this.options.container.append(this.$el);\n\n // link selection dictionary\n this.select_data = this.options.data;\n\n // refresh\n this._refresh();\n\n if (!this.options.multiple) {\n // initial value\n if (this.options.value) {\n this._setValue(this.options.value);\n }\n\n // add change event\n var self = this;\n if (this.options.onchange) {\n this.$el.on(\"change\", function () {\n self.options.onchange(self.value());\n });\n }\n }\n },\n\n // value\n value: function value(new_value) {\n // get current id/value\n var before = this._getValue();\n\n // check if new_value is defined\n if (new_value !== undefined) {\n this._setValue(new_value);\n }\n\n // get current id/value\n var after = this._getValue();\n\n // fire onchange\n if (after != before && this.options.onchange) {\n this.options.onchange(after);\n }\n\n // return current value\n return after;\n },\n\n // label\n text: function text() {\n return this.$el.select2(\"data\").text;\n },\n\n // disabled\n disabled: function disabled() {\n return !this.$el.select2(\"enable\");\n },\n\n // enable\n enable: function enable() {\n this.$el.select2(\"enable\", true);\n },\n\n // disable\n disable: function disable() {\n this.$el.select2(\"enable\", false);\n },\n\n // add\n add: function add(options) {\n // add options\n this.select_data.push({\n id: options.id,\n text: options.text\n });\n\n // refresh\n this._refresh();\n },\n\n // remove\n del: function del(id) {\n // search option\n var index = this._getIndex(id);\n\n // check if found\n if (index != -1) {\n // remove options\n this.select_data.splice(index, 1);\n\n // refresh\n this._refresh();\n }\n },\n\n // remove\n remove: function remove() {\n this.$el.select2(\"destroy\");\n },\n\n // update\n update: function update(options) {\n // copy options\n this.select_data = [];\n for (var key in options.data) {\n this.select_data.push(options.data[key]);\n }\n\n // refresh\n this._refresh();\n },\n\n // refresh\n _refresh: function _refresh() {\n // add select2 data based on type of input\n if (!this.options.multiple) {\n var selected = this._getValue();\n var select_opt = {\n data: this.select_data,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n dropdownAutoWidth: true\n };\n this.$el.select2(select_opt);\n // select previous value (if exists)\n this._setValue(selected);\n } else {\n var select_opt = {\n multiple: this.options.multiple,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n minimumInputLength: this.options.minimumInputLength,\n ajax: this.options.ajax,\n dropdownCssClass: this.options.dropdownCssClass,\n escapeMarkup: this.options.escapeMarkup,\n formatResult: this.options.formatResult,\n formatSelection: this.options.formatSelection,\n initSelection: this.options.initSelection,\n initialData: this.options.initialData\n };\n this.$el.select2(select_opt);\n }\n },\n\n // get index\n _getIndex: function _getIndex(value) {\n // returns the index of the searched value\n _.findIndex(this.select_data, { id: value });\n },\n\n // get value\n _getValue: function _getValue() {\n return this.$el.select2(\"val\");\n },\n\n // set value\n _setValue: function _setValue(new_value) {\n var index = this._getIndex(new_value);\n if (index == -1) {\n if (this.select_data.length > 0) {\n new_value = this.select_data[0].id;\n }\n }\n this.$el.select2(\"val\", new_value);\n },\n\n // element\n _template: function _template(options) {\n return \"\";\n }\n}); // dependencies\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n\"use_strict\";\n\nvar $ = _jquery2.default;\n//============================================================================\n/** Returns a jQuery object containing a clickable font-awesome button.\n * options:\n * tooltipConfig : option map for bootstrap tool tip\n * classes : array of class names (will always be classed as icon-btn)\n * disabled : T/F - add the 'disabled' class?\n * title : tooltip/title string\n * target : optional href target\n * href : optional href\n * faIcon : which font awesome icon to use\n * onclick : function to call when the button is clicked\n */\nvar faIconButton = function faIconButton(options) {\n options = options || {};\n options.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n\n options.classes = [\"icon-btn\"].concat(options.classes || []);\n if (options.disabled) {\n options.classes.push(\"disabled\");\n }\n\n var html = ['',\n // could go with something less specific here - like 'html'\n '', \"\"].join(\"\");\n var $button = $(html).tooltip(options.tooltipConfig);\n if (_.isFunction(options.onclick)) {\n $button.click(options.onclick);\n }\n return $button;\n};\n\n//============================================================================\nexports.default = faIconButton;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 15 */,\n/* 16 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nvar Model = Backbone.Model.extend({\n defaults: {\n extension: \"auto\",\n genome: \"?\",\n url_paste: \"\",\n status: \"init\",\n info: null,\n file_name: \"\",\n file_mode: \"\",\n file_size: 0,\n file_type: null,\n file_path: \"\",\n file_data: null,\n percentage: 0,\n space_to_tab: false,\n to_posix_lines: true,\n enabled: true\n },\n reset: function reset(attr) {\n this.clear().set(this.defaults).set(attr);\n }\n});\nvar Collection = Backbone.Collection.extend({ model: Model });\nexports.default = { Model: Model, Collection: Collection };\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 17 */,\n/* 18 */,\n/* 19 */,\n/* 20 */,\n/* 21 */,\n/* 22 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// =============================================================================\n/** A view on any model that has a 'tags' attribute (a list of tag strings)\n * Incorporates the select2 jQuery plugin for tags display/editing:\n * http://ivaynberg.github.io/select2/\n */\nvar TagsEditor = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.HiddenUntilActivatedViewMixin).extend({\n tagName: \"div\",\n className: \"tags-display\",\n select_width: \"100%\",\n events: {},\n\n /** Set up listeners, parse options */\n initialize: function initialize(options) {\n //console.debug( this, options );\n // only listen to the model only for changes to tags - re-render\n this.show_editor = false;\n if (options.usePrompt === false) {\n this.label = \"\";\n } else {\n this.label = \"\";\n }\n this.workflow_mode = options.workflow_mode || false;\n if (this.workflow_mode) {\n this.events.click = \"showEditor\";\n this.events.keydown = \"keydownHandler\";\n }\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function render() {\n var self = this;\n if (this.workflow_mode) {\n this.$el.html(this._workflowTemplate());\n } else {\n this.$el.html(this._defaultTemplate());\n }\n this.$input().select2({\n placeholder: \"Add tags\",\n width: this.workflow_mode ? this.width : this.select_width,\n tags: function tags() {\n // initialize possible tags in the dropdown based on all the tags the user has used so far\n return self._getTagsUsed();\n }\n });\n\n this._setUpBehaviors();\n return this;\n },\n\n _hashToName: function _hashToName(tag) {\n if (tag.startsWith(\"#\")) {\n return \"name:\" + tag.slice(1);\n }\n return tag;\n },\n\n _nameToHash: function _nameToHash(tag) {\n if (tag.startsWith(\"name:\")) {\n tag = \"#\" + tag.slice(5);\n }\n return tag;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _defaultTemplate: function _defaultTemplate() {\n return [this.label, this._renderEditor()].join(\"\");\n },\n\n _workflowTemplate: function _workflowTemplate() {\n // Shows labels by default, event handler controls whether we show tags or editor\n return [this.show_editor ? this._renderEditor() : this._renderTags()].join(\" \");\n },\n\n keydownHandler: function keydownHandler(e) {\n switch (e.which) {\n // esc\n case 27:\n // hide the tag editor when pressing escape\n this.hideEditor();\n break;\n }\n },\n\n showEditor: function showEditor() {\n this.show_editor = true;\n this.render();\n },\n\n hideEditor: function hideEditor() {\n this.show_editor = false;\n this.render();\n },\n\n _renderEditor: function _renderEditor() {\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n return \"\";\n },\n\n _renderTags: function _renderTags() {\n var tags = this.model.get(\"tags\");\n var addButton = \"static/images/fugue/tag--plus.png\";\n var renderedArray = [];\n _.each(tags, function (tag) {\n tag = tag.indexOf(\"name:\") == 0 ? tag.slice(5) : tag;\n var renderString = \"\" + tag + \"\";\n renderedArray.push(renderString);\n });\n if (renderedArray.length === 0) {\n // If there are no tags to render we just show the add-tag-button\n renderedArray.push(\"\");\n }\n return renderedArray.join(\" \");\n },\n\n /** @returns {String} the sorted, comma-separated tags from the model */\n tagsToCSV: function tagsToCSV() {\n var self = this;\n var tagsArray = this.model.get(\"tags\");\n if (!_.isArray(tagsArray) || _.isEmpty(tagsArray)) {\n return \"\";\n }\n return tagsArray.map(function (tag) {\n return _.escape(self._nameToHash(tag));\n }).sort().join(\",\");\n },\n\n /** @returns {jQuery} the input for this view */\n $input: function $input() {\n return this.$el.find(\"input.tags-input\");\n },\n\n /** @returns {String[]} all tags used by the current user */\n _getTagsUsed: function _getTagsUsed() {\n //TODO: global\n var self = this;\n return _.map(Galaxy.user.get(\"tags_used\"), self._nameToHash);\n },\n\n /** set up any event listeners on the view's DOM (mostly handled by select2) */\n _setUpBehaviors: function _setUpBehaviors() {\n var self = this;\n this.$input().on(\"change\", function (event) {\n // Modify any 'hashtag' 'nametags'\n event.val = _.map(event.val, self._hashToName);\n // save the model's tags in either remove or added event\n self.model.save({ tags: event.val });\n // if it's new, add the tag to the users tags\n if (event.added) {\n //??: solve weird behavior in FF on test.galaxyproject.org where\n // event.added.text is string object: 'String{ 0=\"o\", 1=\"n\", 2=\"e\" }'\n self._addNewTagToTagsUsed(\"\" + event.added.text);\n }\n });\n },\n\n /** add a new tag (if not already there) to the list of all tags used by the user\n * @param {String} newTag the tag to add to the list of used\n */\n _addNewTagToTagsUsed: function _addNewTagToTagsUsed(newTag) {\n //TODO: global\n var tagsUsed = Galaxy.user.get(\"tags_used\");\n if (!_.contains(tagsUsed, newTag)) {\n tagsUsed.push(newTag);\n tagsUsed.sort();\n Galaxy.user.set(\"tags_used\", tagsUsed);\n }\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function remove() {\n this.$input.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function toString() {\n return [\"TagsEditor(\", \"\" + this.model, \")\"].join(\"\");\n }\n});\n\nexports.default = {\n TagsEditor: TagsEditor\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 23 */,\n/* 24 */,\n/* 25 */,\n/* 26 */,\n/* 27 */,\n/* 28 */,\n/* 29 */,\n/* 30 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nvar _queryStringParsing = __webpack_require__(8);\n\nvar _queryStringParsing2 = _interopRequireDefault(_queryStringParsing);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar $ = _jquery2.default;\n\n\nvar Router = Backbone.Router.extend({\n // TODO: not many client routes at this point - fill and remove from server.\n // since we're at root here, this may be the last to be routed entirely on the client.\n initialize: function initialize(page, options) {\n this.page = page;\n this.options = options;\n },\n\n /** helper to push a new navigation state */\n push: function push(url, data) {\n data = data || {};\n data.__identifer = Math.random().toString(36).substr(2);\n if (!$.isEmptyObject(data)) {\n url += url.indexOf(\"?\") == -1 ? \"?\" : \"&\";\n url += $.param(data, true);\n }\n Galaxy.params = data;\n this.navigate(url, { trigger: true });\n },\n\n /** override to parse query string into obj and send to each route */\n execute: function execute(callback, args, name) {\n Galaxy.debug(\"router execute:\", callback, args, name);\n var queryObj = _queryStringParsing2.default.parse(args.pop());\n args.push(queryObj);\n if (callback) {\n if (this.authenticate(args, name)) {\n callback.apply(this, args);\n } else {\n this.access_denied();\n }\n }\n },\n\n authenticate: function authenticate(args, name) {\n return true;\n },\n\n access_denied: function access_denied() {\n this.page.display(new _uiMisc2.default.Message({\n status: \"danger\",\n message: \"You must be logged in with proper credentials to make this request.\",\n persistent: true\n }));\n }\n});\n\nexports.default = Router;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 31 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n options: {\n class_check: \"fa-check-square-o\",\n class_uncheck: \"fa-square-o\",\n parameters: [{\n id: \"space_to_tab\",\n title: \"Convert spaces to tabs\"\n }, {\n id: \"to_posix_lines\",\n title: \"Use POSIX standard\"\n }]\n },\n\n initialize: function initialize(options) {\n var self = this;\n this.model = options.model;\n this.setElement($(\"\").addClass(\"upload-settings\"));\n this.$el.append($(\"\").addClass(\"upload-settings-cover\"));\n this.$el.append($(\"
\";\n },\n\n /** Template of main view */\n _template: function _template() {\n return \"
\" + this.model.get(\"help_text\") + \"
Available files:
Name
Size
Created
Your FTP directory does not contain any files.
\";\n \"
\";\n }\n}); /** This renders the content of the ftp popup **/\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 33 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** This renders a popover with extension details **/\nexports.default = Backbone.View.extend({\n initialize: function initialize(options) {\n this.model = new Backbone.Model(options);\n this.setElement(\"\");\n this.render();\n },\n\n render: function render() {\n var self = this;\n var options = this.model.attributes;\n var description = _.findWhere(options.list, {\n id: options.extension\n });\n this.extension_popup && this.extension_popup.remove();\n this.extension_popup = new _uiPopover2.default.View({\n placement: options.placement || \"bottom\",\n container: options.$el\n });\n this.extension_popup.title(options.title);\n this.extension_popup.empty();\n this.extension_popup.append(this._templateDescription(description));\n this.extension_popup.show();\n },\n\n /** Template for extensions description */\n _templateDescription: function _templateDescription(options) {\n if (options.description) {\n var tmpl = options.description;\n if (options.description_url) {\n tmpl += \" (read more)\";\n }\n return tmpl;\n } else {\n return \"There is no description available for this file extension.\";\n }\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 34 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery, _) {\n\n/*\n galaxy upload plugins - requires FormData and XMLHttpRequest\n*/\n(function ($) {\n // add event properties\n jQuery.event.props.push(\"dataTransfer\");\n\n /**\n Posts file data to the API\n */\n $.uploadpost = function (config) {\n // parse options\n var cnf = $.extend({}, {\n data: {},\n success: function success() {},\n error: function error() {},\n progress: function progress() {},\n url: null,\n maxfilesize: 2048,\n error_filesize: \"File exceeds 2GB. Please use a FTP client.\",\n error_default: \"Please make sure the file is available.\",\n error_server: \"Upload request failed.\",\n error_login: \"Uploads require you to log in.\"\n }, config);\n\n // link data\n var data = cnf.data;\n\n // check errors\n if (data.error_message) {\n cnf.error(data.error_message);\n return;\n }\n\n // construct form data\n var form = new FormData();\n for (var key in data.payload) {\n form.append(key, data.payload[key]);\n }\n\n // add files to submission\n var sizes = 0;\n for (var key in data.files) {\n var d = data.files[key];\n form.append(d.name, d.file, d.file.name);\n sizes += d.file.size;\n }\n\n // check file size, unless it's an ftp file\n if (sizes > 1048576 * cnf.maxfilesize) {\n cnf.error(cnf.error_filesize);\n return;\n }\n\n // prepare request\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", cnf.url, true);\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n\n // captures state changes\n xhr.onreadystatechange = function () {\n // check for request completed, server connection closed\n if (xhr.readyState == xhr.DONE) {\n // parse response\n var response = null;\n var extra_info = \"\";\n if (xhr.responseText) {\n try {\n response = jQuery.parseJSON(xhr.responseText);\n extra_info = response.err_msg;\n } catch (e) {\n response = xhr.responseText;\n extra_info = response;\n }\n }\n // pass any error to the error option\n if (xhr.status < 200 || xhr.status > 299) {\n var text = xhr.statusText;\n if (xhr.status == 403) {\n text = cnf.error_login;\n } else if (xhr.status == 0) {\n text = cnf.error_server;\n } else if (!text) {\n text = cnf.error_default;\n }\n cnf.error(text + \" (\" + xhr.status + \"). \" + extra_info);\n } else {\n cnf.success(response);\n }\n }\n };\n\n // prepare upload progress\n xhr.upload.addEventListener(\"progress\", function (e) {\n if (e.lengthComputable) {\n cnf.progress(Math.round(e.loaded * 100 / e.total));\n }\n }, false);\n\n // send request\n Galaxy.emit.debug(\"uploadbox::uploadpost()\", \"Posting following data.\", cnf);\n xhr.send(form);\n };\n\n /**\n Handles the upload events drag/drop etc.\n */\n $.fn.uploadinput = function (options) {\n // initialize\n var el = this;\n var opts = $.extend({}, {\n ondragover: function ondragover() {},\n ondragleave: function ondragleave() {},\n onchange: function onchange() {},\n multiple: false\n }, options);\n\n // append hidden upload field\n var $input = $(\"\");\n el.append($input.change(function (e) {\n opts.onchange(e.target.files);\n $(this).val(\"\");\n }));\n\n // drag/drop events\n el.on(\"drop\", function (e) {\n opts.ondragleave(e);\n if (e.dataTransfer) {\n opts.onchange(e.dataTransfer.files);\n e.preventDefault();\n }\n });\n el.on(\"dragover\", function (e) {\n e.preventDefault();\n opts.ondragover(e);\n });\n el.on(\"dragleave\", function (e) {\n e.stopPropagation();\n opts.ondragleave(e);\n });\n\n // exports\n return {\n dialog: function dialog() {\n $input.trigger(\"click\");\n }\n };\n };\n\n /**\n Handles the upload queue and events such as drag/drop etc.\n */\n $.fn.uploadbox = function (options) {\n // parse options\n var opts = $.extend({}, {\n dragover: function dragover() {},\n dragleave: function dragleave() {},\n announce: function announce(d) {},\n initialize: function initialize(d) {},\n progress: function progress(d, m) {},\n success: function success(d, m) {},\n error: function error(d, m) {\n alert(m);\n },\n complete: function complete() {}\n }, options);\n\n // file queue\n var queue = {};\n\n // queue index/length counter\n var queue_index = 0;\n var queue_length = 0;\n\n // indicates if queue is currently running\n var queue_running = false;\n var queue_stop = false;\n\n // element\n var uploadinput = $(this).uploadinput({\n multiple: true,\n onchange: function onchange(files) {\n add(files);\n },\n ondragover: options.ondragover,\n ondragleave: options.ondragleave\n });\n\n // add new files to upload queue\n function add(files) {\n if (files && files.length && !queue_running) {\n var index = undefined;\n _.each(files, function (file, key) {\n if (file.mode !== \"new\" && _.filter(queue, function (f) {\n return f.name === file.name && f.size === file.size;\n }).length) {\n file.duplicate = true;\n }\n });\n _.each(files, function (file) {\n if (!file.duplicate) {\n index = String(queue_index++);\n queue[index] = file;\n opts.announce(index, queue[index]);\n queue_length++;\n }\n });\n return index;\n }\n }\n\n // remove file from queue\n function remove(index) {\n if (queue[index]) {\n delete queue[index];\n queue_length--;\n }\n }\n\n // process an upload, recursive\n function process() {\n // validate\n if (queue_length == 0 || queue_stop) {\n queue_stop = false;\n queue_running = false;\n opts.complete();\n return;\n } else {\n queue_running = true;\n }\n\n // get an identifier from the queue\n var index = -1;\n for (var key in queue) {\n index = key;\n break;\n }\n\n // get current file from queue\n var file = queue[index];\n\n // remove from queue\n remove(index);\n\n // create and submit data\n $.uploadpost({\n url: opts.url,\n data: opts.initialize(index),\n success: function success(message) {\n opts.success(index, message);\n process();\n },\n error: function error(message) {\n opts.error(index, message);\n process();\n },\n progress: function progress(percentage) {\n opts.progress(index, percentage);\n }\n });\n }\n\n /*\n public interface\n */\n\n // open file browser for selection\n function select() {\n uploadinput.dialog();\n }\n\n // remove all entries from queue\n function reset(index) {\n for (index in queue) {\n remove(index);\n }\n }\n\n // initiate upload process\n function start() {\n if (!queue_running) {\n queue_running = true;\n process();\n }\n }\n\n // stop upload process\n function stop() {\n queue_stop = true;\n }\n\n // set options\n function configure(options) {\n opts = $.extend({}, opts, options);\n return opts;\n }\n\n // verify browser compatibility\n function compatible() {\n return window.File && window.FormData && window.XMLHttpRequest && window.FileList;\n }\n\n // export functions\n return {\n select: select,\n add: add,\n remove: remove,\n start: start,\n stop: stop,\n reset: reset,\n configure: configure,\n compatible: compatible\n };\n };\n})(jQuery);\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 35 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _hdcaModel = __webpack_require__(36);\n\nvar _hdcaModel2 = _interopRequireDefault(_hdcaModel);\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _baseCreator = __webpack_require__(74);\n\nvar _baseCreator2 = _interopRequireDefault(_baseCreator);\n\nvar _uiModal = __webpack_require__(7);\n\nvar _uiModal2 = _interopRequireDefault(_uiModal);\n\nvar _naturalSort = __webpack_require__(75);\n\nvar _naturalSort2 = _interopRequireDefault(_naturalSort);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(76);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"collections\";\n\n/*==============================================================================\nTODO:\n use proper Element model and not just json\n straighten out createFn, collection.createHDCA\n possibly stop using modals for this\n It would be neat to do a drag and drop\n\n==============================================================================*/\n/** A view for both DatasetDCEs and NestedDCDCEs\n * (things that implement collection-model:DatasetCollectionElementMixin)\n */\nvar DatasetCollectionElementView = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))\n tagName: \"li\",\n className: \"collection-element\",\n\n initialize: function initialize(attributes) {\n this.element = attributes.element || {};\n this.selected = attributes.selected || false;\n },\n\n render: function render() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el.attr(\"data-element-id\", this.element.id).attr(\"draggable\", true).html(this.template({ element: this.element })).get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n if (this.selected) {\n this.$el.addClass(\"selected\");\n }\n return this;\n },\n\n //TODO: lots of unused space in the element - possibly load details and display them horiz.\n template: _.template(['', \"<%- element.name %>\", \"\", '\"].join(\"\")),\n\n /** select this element and pub */\n select: function select(toggle) {\n this.$el.toggleClass(\"selected\", toggle);\n this.trigger(\"select\", {\n source: this,\n selected: this.$el.hasClass(\"selected\")\n });\n },\n\n /** animate the removal of this element and pub */\n discard: function discard() {\n var view = this;\n var parentWidth = this.$el.parent().width();\n this.$el.animate({ \"margin-right\": parentWidth }, \"fast\", function () {\n view.trigger(\"discard\", {\n source: view\n });\n view.destroy();\n });\n },\n\n /** remove the DOM and any listeners */\n destroy: function destroy() {\n this.off();\n this.$el.remove();\n },\n\n events: {\n click: \"_click\",\n \"click .name\": \"_clickName\",\n \"click .discard\": \"_clickDiscard\",\n\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** select when the li is clicked */\n _click: function _click(ev) {\n ev.stopPropagation();\n this.select(ev);\n },\n\n /** rename a pair when the name is clicked */\n _clickName: function _clickName(ev) {\n ev.stopPropagation();\n ev.preventDefault();\n\n var promptString = [(0, _localization2.default)(\"Enter a new name for the element\"), \":\\n(\", (0, _localization2.default)(\"Note that changing the name here will not rename the dataset\"), \")\"].join(\"\");\n\n var response = prompt((0, _localization2.default)(\"Enter a new name for the element\") + \":\", this.element.name);\n\n if (response) {\n this.element.name = response;\n this.render();\n }\n //TODO: cancelling with ESC leads to closure of the creator...\n },\n\n /** discard when the discard button is clicked */\n _clickDiscard: function _clickDiscard(ev) {\n ev.stopPropagation();\n this.discard();\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function _dragstart(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.element));\n\n this.$el.addClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragstart\", [this]);\n },\n\n /** dragging for re-ordering */\n _dragend: function _dragend(ev) {\n this.$el.removeClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function _sendToParent(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function toString() {\n return \"DatasetCollectionElementView()\";\n }\n});\n\n// ============================================================================\n/** An interface for building collections.\n */\nvar ListCollectionCreator = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseCreator2.default.CollectionCreatorMixin).extend({\n _logNamespace: logNamespace,\n\n /** the class used to display individual elements */\n elementViewClass: DatasetCollectionElementView,\n /** the class this creator will create and save */\n collectionClass: _hdcaModel2.default.HistoryListDatasetCollection,\n className: \"list-collection-creator collection-creator flex-row-container\",\n\n /** minimum number of valid elements to start with in order to build a collection of this type */\n minElements: 1,\n\n defaultAttributes: {\n //TODO: remove - use new collectionClass().save()\n /** takes elements and creates the proper collection - returns a promise */\n creationFn: function creationFn() {\n throw new TypeError(\"no creation fn for creator\");\n },\n /** fn to call when the collection is created (scoped to this) */\n oncreate: function oncreate() {},\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n oncancel: function oncancel() {},\n /** distance from list edge to begin autoscrolling list */\n autoscrollDist: 24,\n /** Color passed to hoverhighlight */\n highlightClr: \"rgba( 64, 255, 255, 1.0 )\"\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\"\n },\n\n /** set up initial options, instance vars, behaviors */\n initialize: function initialize(attributes) {\n this.metric(\"ListCollectionCreator.initialize\", attributes);\n var creator = this;\n _.each(this.defaultAttributes, function (value, key) {\n value = attributes[key] || value;\n creator[key] = value;\n });\n\n /** unordered, original list - cache to allow reversal */\n creator.initialElements = attributes.elements || [];\n\n this._setUpCommonSettings(attributes);\n this._instanceSetUp();\n this._elementsSetUp();\n this._setUpBehaviors();\n },\n\n /** set up instance vars */\n _instanceSetUp: function _instanceSetUp() {\n /** Ids of elements that have been selected by the user - to preserve over renders */\n this.selectedIds = {};\n /** DOM elements currently being dragged */\n this.$dragging = null;\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n },\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data */\n _elementsSetUp: function _elementsSetUp() {\n //this.debug( '-- _dataSetUp' );\n /** a list of invalid elements and the reasons they aren't valid */\n this.invalidElements = [];\n //TODO: handle fundamental problem of syncing DOM, views, and list here\n /** data for list in progress */\n this.workingElements = [];\n /** views for workingElements */\n this.elementViews = [];\n\n // copy initial list, sort, add ids if needed\n this.workingElements = this.initialElements.slice(0);\n this._ensureElementIds();\n this._validateElements();\n this._mangleDuplicateNames();\n this._sortElements();\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureElementIds: function _ensureElementIds() {\n this.workingElements.forEach(function (element) {\n if (!element.hasOwnProperty(\"id\")) {\n element.id = _.uniqueId();\n }\n });\n return this.workingElements;\n },\n\n /** separate working list into valid and invalid elements for this collection */\n _validateElements: function _validateElements() {\n var creator = this;\n var existingNames = {};\n creator.invalidElements = [];\n\n this.workingElements = this.workingElements.filter(function (element) {\n var problem = creator._isElementInvalid(element);\n if (problem) {\n creator.invalidElements.push({\n element: element,\n text: problem\n });\n }\n return !problem;\n });\n return this.workingElements;\n },\n\n /** describe what is wrong with a particular element if anything */\n _isElementInvalid: function _isElementInvalid(element) {\n if (element.history_content_type !== \"dataset\") {\n return (0, _localization2.default)(\"is not a dataset\");\n }\n var validState = element.state === _states2.default.OK || _.contains(_states2.default.NOT_READY_STATES, element.state);\n if (!validState) {\n return (0, _localization2.default)(\"has errored, is paused, or is not accessible\");\n }\n if (element.deleted || element.purged) {\n return (0, _localization2.default)(\"has been deleted or purged\");\n }\n return null;\n },\n\n /** mangle duplicate names using a mac-like '(counter)' addition to any duplicates */\n _mangleDuplicateNames: function _mangleDuplicateNames() {\n var SAFETY = 900;\n var counter = 1;\n var existingNames = {};\n this.workingElements.forEach(function (element) {\n var currName = element.name;\n while (existingNames.hasOwnProperty(currName)) {\n currName = element.name + \" (\" + counter + \")\";\n counter += 1;\n if (counter >= SAFETY) {\n throw new Error(\"Safety hit in while loop - thats impressive\");\n }\n }\n element.name = currName;\n existingNames[element.name] = true;\n });\n },\n\n /** sort a list of elements */\n _sortElements: function _sortElements(list) {\n // // currently only natural sort by name\n // this.workingElements.sort( function( a, b ){ return naturalSort( a.name, b.name ); });\n // return this.workingElements;\n },\n\n // ------------------------------------------------------------------------ rendering\n // templates : ListCollectionCreator.templates,\n /** render the entire interface */\n render: function render(speed, callback) {\n //this.debug( '-- _render' );\n if (this.workingElements.length < this.minElements) {\n return this._renderInvalid(speed, callback);\n }\n\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.$(\".collection-name\").focus();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render a simplified interface aimed at telling the user why they can't move forward */\n _renderInvalid: function _renderInvalid(speed, callback) {\n //this.debug( '-- _render' );\n this.$el.empty().html(this.templates.invalidInitial({\n problems: this.invalidElements,\n elements: this.workingElements\n }));\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function _renderHeader(speed, callback) {\n var $header = this.$(\".header\").empty().html(this.templates.header()).find(\".help-content\").prepend($(this.templates.helpContent()));\n //TODO: should only show once despite calling _renderHeader again\n if (this.invalidElements.length) {\n this._invalidElementsAlert();\n }\n return $header;\n },\n\n /** render the middle including the elements */\n _renderMiddle: function _renderMiddle(speed, callback) {\n var $middle = this.$(\".middle\").empty().html(this.templates.middle());\n this._renderList(speed);\n return $middle;\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function _addPluginComponents() {\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", this.highlightClr);\n },\n\n /** build and show an alert describing any elements that could not be included due to problems */\n _invalidElementsAlert: function _invalidElementsAlert() {\n this._showAlert(this.templates.invalidElements({\n problems: this.invalidElements\n }), \"alert-warning\");\n },\n\n _disableNameAndCreate: function _disableNameAndCreate(disable) {\n disable = !_.isUndefined(disable) ? disable : true;\n if (disable) {\n this.$(\".collection-name\").prop(\"disabled\", true);\n this.$(\".create-collection\").toggleClass(\"disabled\", true);\n // } else {\n // this.$( '.collection-name' ).prop( 'disabled', false );\n // this.$( '.create-collection' ).removeClass( 'disable' );\n }\n },\n\n // ------------------------------------------------------------------------ rendering elements\n /** conv. to the main list display DOM */\n $list: function $list() {\n return this.$(\".collection-elements\");\n },\n\n /** show or hide the clear selected control based on the num of selected elements */\n _renderClearSelected: function _renderClearSelected() {\n if (_.size(this.selectedIds)) {\n this.$(\".collection-elements-controls > .clear-selected\").show();\n } else {\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n }\n },\n\n /** render the elements in order (or a warning if no elements found) */\n _renderList: function _renderList(speed, callback) {\n //this.debug( '-- _renderList' );\n var creator = this;\n\n var $tmp = jQuery(\"\");\n var $list = creator.$list();\n\n _.each(this.elementViews, function (view) {\n view.destroy();\n creator.removeElementView(view);\n });\n\n // if( !this.workingElements.length ){\n // this._renderNoValidElements();\n // return;\n // }\n\n creator.workingElements.forEach(function (element) {\n var elementView = creator._createElementView(element);\n $tmp.append(elementView.$el);\n });\n\n creator._renderClearSelected();\n $list.empty().append($tmp.children());\n _.invoke(creator.elementViews, \"render\");\n\n if ($list.height() > $list.css(\"max-height\")) {\n $list.css(\"border-width\", \"1px 0px 1px 0px\");\n } else {\n $list.css(\"border-width\", \"0px\");\n }\n },\n\n /** create an element view, cache in elementViews, set up listeners, and return */\n _createElementView: function _createElementView(element) {\n var elementView = new this.elementViewClass({\n //TODO: use non-generic class or not all\n // model : COLLECTION.DatasetDCE( element )\n element: element,\n selected: _.has(this.selectedIds, element.id)\n });\n this.elementViews.push(elementView);\n this._listenToElementView(elementView);\n return elementView;\n },\n\n /** listen to any element events */\n _listenToElementView: function _listenToElementView(view) {\n var creator = this;\n creator.listenTo(view, {\n select: function select(data) {\n var element = data.source.element;\n if (data.selected) {\n creator.selectedIds[element.id] = true;\n } else {\n delete creator.selectedIds[element.id];\n }\n creator.trigger(\"elements:select\", data);\n },\n discard: function discard(data) {\n creator.trigger(\"elements:discard\", data);\n }\n });\n },\n\n /** add a new element view based on the json in element */\n addElementView: function addElementView(element) {\n //TODO: workingElements is sorted, add element in appropo index\n // add element, sort elements, find element index\n // var view = this._createElementView( element );\n // return view;\n },\n\n /** stop listening to view and remove from caches */\n removeElementView: function removeElementView(view) {\n delete this.selectedIds[view.element.id];\n this._renderClearSelected();\n\n this.elementViews = _.without(this.elementViews, view);\n this.stopListening(view);\n },\n\n /** render a message in the list that no elements remain to create a collection */\n _renderNoElementsLeft: function _renderNoElementsLeft() {\n this._disableNameAndCreate(true);\n this.$(\".collection-elements\").append(this.templates.noElementsLeft());\n },\n\n // /** render a message in the list that no valid elements were found to create a collection */\n // _renderNoValidElements : function(){\n // this._disableNameAndCreate( true );\n // this.$( '.collection-elements' ).append( this.templates.noValidElements() );\n // },\n\n // ------------------------------------------------------------------------ API\n /** convert element into JSON compatible with the collections API */\n _elementToJSON: function _elementToJSON(element) {\n // return element.toJSON();\n return element;\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function createList(name) {\n if (!this.workingElements.length) {\n var message = (0, _localization2.default)(\"No valid elements for final list\") + \". \";\n message += \"\" + (0, _localization2.default)(\"Cancel\") + \" \";\n message += (0, _localization2.default)(\"or\");\n message += \" \" + (0, _localization2.default)(\"start over\") + \".\";\n this._showAlert(message);\n return;\n }\n\n var creator = this;\n\n var elements = this.workingElements.map(function (element) {\n return creator._elementToJSON(element);\n });\n\n creator.blocking = true;\n return creator.creationFn(elements, name, creator.hideOriginals).always(function () {\n creator.blocking = false;\n }).fail(function (xhr, status, message) {\n creator.trigger(\"error\", {\n xhr: xhr,\n status: status,\n message: (0, _localization2.default)(\"An error occurred while creating this collection\")\n });\n }).done(function (response, message, xhr) {\n creator.trigger(\"collection:created\", response, message, xhr);\n creator.metric(\"collection:created\", response);\n if (typeof creator.oncreate === \"function\") {\n creator.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n // ------------------------------------------------------------------------ events\n /** set up event handlers on self */\n _setUpBehaviors: function _setUpBehaviors() {\n this.on(\"error\", this._errorHandler);\n\n this.once(\"rendered\", function () {\n this.trigger(\"rendered:initial\", this);\n });\n\n this.on(\"elements:select\", function (data) {\n this._renderClearSelected();\n });\n\n this.on(\"elements:discard\", function (data) {\n var element = data.source.element;\n this.removeElementView(data.source);\n\n this.workingElements = _.without(this.workingElements, element);\n if (!this.workingElements.length) {\n this._renderNoElementsLeft();\n }\n });\n\n //this.on( 'all', function(){\n // this.info( arguments );\n //});\n return this;\n },\n\n /** handle errors with feedback and details to the user (if available) */\n _errorHandler: function _errorHandler(data) {\n this.error(data);\n\n var creator = this;\n var content = data.message || (0, _localization2.default)(\"An error occurred\");\n if (data.xhr) {\n var xhr = data.xhr;\n var message = data.message;\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += \": \" + (0, _localization2.default)(\"Galaxy could not be reached and may be updating.\") + (0, _localization2.default)(\" Try again in a few minutes.\");\n } else if (xhr.responseJSON) {\n content += \":
\" + JSON.stringify(xhr.responseJSON) + \"
\";\n } else {\n content += \": \" + message;\n }\n }\n creator._showAlert(content, \"alert-danger\");\n },\n\n events: {\n // header\n \"click .more-help\": \"_clickMoreHelp\",\n \"click .less-help\": \"_clickLessHelp\",\n \"click .main-help\": \"_toggleHelp\",\n \"click .header .alert button\": \"_hideAlert\",\n\n \"click .reset\": \"reset\",\n \"click .clear-selected\": \"clearSelectedElements\",\n\n // elements - selection\n \"click .collection-elements\": \"clearSelectedElements\",\n\n // elements - drop target\n // 'dragenter .collection-elements': '_dragenterElements',\n // 'dragleave .collection-elements': '_dragleaveElements',\n \"dragover .collection-elements\": \"_dragoverElements\",\n \"drop .collection-elements\": \"_dropElements\",\n\n // these bubble up from the elements as custom events\n \"collection-element.dragstart .collection-elements\": \"_elementDragstart\",\n \"collection-element.dragend .collection-elements\": \"_elementDragend\",\n\n // footer\n \"change .collection-name\": \"_changeName\",\n \"keydown .collection-name\": \"_nameCheckForEnter\",\n \"change .hide-originals\": \"_changeHideOriginals\",\n \"click .cancel-create\": \"_cancelCreate\",\n \"click .create-collection\": \"_clickCreate\" //,\n },\n\n // ........................................................................ elements\n /** reset all data to the initial state */\n reset: function reset() {\n this._instanceSetUp();\n this._elementsSetUp();\n this.render();\n },\n\n /** deselect all elements */\n clearSelectedElements: function clearSelectedElements(ev) {\n this.$(\".collection-elements .collection-element\").removeClass(\"selected\");\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n },\n\n //_dragenterElements : function( ev ){\n // //this.debug( '_dragenterElements:', ev );\n //},\n //TODO: if selected are dragged out of the list area - remove the placeholder - cuz it won't work anyway\n // _dragleaveElements : function( ev ){\n // //this.debug( '_dragleaveElements:', ev );\n // },\n\n /** track the mouse drag over the list adding a placeholder to show where the drop would occur */\n _dragoverElements: function _dragoverElements(ev) {\n //this.debug( '_dragoverElements:', ev );\n ev.preventDefault();\n\n var $list = this.$list();\n this._checkForAutoscroll($list, ev.originalEvent.clientY);\n var $nearest = this._getNearestElement(ev.originalEvent.clientY);\n\n //TODO: no need to re-create - move instead\n this.$(\".element-drop-placeholder\").remove();\n var $placeholder = $('');\n if (!$nearest.length) {\n $list.append($placeholder);\n } else {\n $nearest.before($placeholder);\n }\n },\n\n /** If the mouse is near enough to the list's top or bottom, scroll the list */\n _checkForAutoscroll: function _checkForAutoscroll($element, y) {\n var AUTOSCROLL_SPEED = 2;\n var offset = $element.offset();\n var scrollTop = $element.scrollTop();\n var upperDist = y - offset.top;\n var lowerDist = offset.top + $element.outerHeight() - y;\n if (upperDist >= 0 && upperDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop - AUTOSCROLL_SPEED);\n } else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop + AUTOSCROLL_SPEED);\n }\n },\n\n /** get the nearest element based on the mouse's Y coordinate.\n * If the y is at the end of the list, return an empty jQuery object.\n */\n _getNearestElement: function _getNearestElement(y) {\n var WIGGLE = 4;\n\n var lis = this.$(\".collection-elements li.collection-element\").toArray();\n\n for (var i = 0; i < lis.length; i++) {\n var $li = $(lis[i]);\n var top = $li.offset().top;\n var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;\n if (top + halfHeight > y && top - halfHeight < y) {\n return $li;\n }\n }\n return $();\n },\n\n /** drop (dragged/selected elements) onto the list, re-ordering the internal list */\n _dropElements: function _dropElements(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n // both required for firefox\n ev.preventDefault();\n ev.dataTransfer.dropEffect = \"move\";\n\n // insert before the nearest element or after the last.\n var $nearest = this._getNearestElement(ev.clientY);\n if ($nearest.length) {\n this.$dragging.insertBefore($nearest);\n } else {\n // no nearest before - insert after last element\n this.$dragging.insertAfter(this.$(\".collection-elements .collection-element\").last());\n }\n // resync the creator's list based on the new DOM order\n this._syncOrderToDom();\n return false;\n },\n\n /** resync the creator's list of elements based on the DOM order */\n _syncOrderToDom: function _syncOrderToDom() {\n var creator = this;\n var newElements = [];\n //TODO: doesn't seem wise to use the dom to store these - can't we sync another way?\n this.$(\".collection-elements .collection-element\").each(function () {\n var id = $(this).attr(\"data-element-id\");\n\n var element = _.findWhere(creator.workingElements, {\n id: id\n });\n\n if (element) {\n newElements.push(element);\n } else {\n console.error(\"missing element: \", id);\n }\n });\n this.workingElements = newElements;\n this._renderList();\n },\n\n /** drag communication with element sub-views: dragstart */\n _elementDragstart: function _elementDragstart(ev, element) {\n // auto select the element causing the event and move all selected\n element.select(true);\n this.$dragging = this.$(\".collection-elements .collection-element.selected\");\n },\n\n /** drag communication with element sub-views: dragend - remove the placeholder */\n _elementDragend: function _elementDragend(ev, element) {\n $(\".element-drop-placeholder\").remove();\n this.$dragging = null;\n },\n\n // ------------------------------------------------------------------------ templates\n //TODO: move to require text plugin and load these as text\n //TODO: underscore currently unnecc. bc no vars are used\n //TODO: better way of localizing text-nodes in long strings\n /** underscore template fns attached to class */\n templates: _.extend({}, _baseCreator2.default.CollectionCreatorMixin._creatorTemplates, {\n /** the header (not including help text) */\n header: _.template(['
\"].join(\"\")),\n\n /** help content */\n helpContent: _.template([\"
\", (0, _localization2.default)([\"Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and \", \"workflows in order to have analyses done on each member of the entire group. This interface allows \", \"you to create a collection and re-order the final collection.\"].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)([\"Rename elements in the list by clicking on \", 'the existing name.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)([\"Discard elements from the final created list by clicking on the \", '\"Discard\" button.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)([\"Reorder the list by clicking and dragging elements. Select multiple elements by clicking on \", 'them and you can then move those selected by dragging the ', \"entire group. Deselect them by clicking them again or by clicking the \", 'the \"Clear selected\" link.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Click the \"Start over\" link to begin again as if you had just opened ', \"the interface.\"].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Click the \"Cancel\" button to exit the interface.'].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)(['Once your collection is complete, enter a name and ', 'click \"Create list\".'].join(\"\")), \"
\"].join(\"\")),\n\n /** shown in list when all elements are discarded */\n invalidElements: _.template([(0, _localization2.default)(\"The following selections could not be included due to problems:\"), \"
<% _.each( problems, function( problem ){ %>\", \"
<%- problem.element.name %>: <%- problem.text %>
\", \"<% }); %>
\"].join(\"\")),\n\n /** shown in list when all elements are discarded */\n noElementsLeft: _.template(['
\"].join(\"\")),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(['
', '
', '', \"<% if( _.size( problems ) ){ %>\", (0, _localization2.default)(\"The following selections could not be included due to problems\"), \":\", \"
<% _.each( problems, function( problem ){ %>\", \"
<%- problem.element.name %>: <%- problem.text %>
\", \"<% }); %>
\", \"<% } else if( _.size( elements ) < 1 ){ %>\", (0, _localization2.default)(\"No datasets were selected\"), \".\", \"<% } %>\", \" \", (0, _localization2.default)(\"At least one element is needed for the collection\"), \". \", (0, _localization2.default)(\"You may need to \"), '', (0, _localization2.default)(\"cancel\"), \" \", (0, _localization2.default)(\"and reselect new elements\"), \".\", \"\", \"
\", \"
\", '\"].join(\"\"))\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function toString() {\n return \"ListCollectionCreator\";\n }\n});\n\n//=============================================================================\n/** Create a modal and load its body with the given CreatorClass creator type\n * @returns {Deferred} resolved when creator has built a collection.\n */\nvar collectionCreatorModal = function _collectionCreatorModal(elements, options, CreatorClass) {\n var deferred = jQuery.Deferred();\n var modal = Galaxy.modal || new _uiModal2.default.View();\n var creator;\n\n options = _.defaults(options || {}, {\n elements: elements,\n oncancel: function oncancel() {\n modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function oncreate(creator, response) {\n modal.hide();\n deferred.resolve(response);\n }\n });\n\n creator = new CreatorClass(options);\n modal.show({\n title: options.title || (0, _localization2.default)(\"Create a collection\"),\n body: creator.$el,\n width: \"80%\",\n height: \"100%\",\n closing_events: true\n });\n creator.render();\n window._collectionCreator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n/** List collection flavor of collectionCreatorModal. */\nvar listCollectionCreatorModal = function _listCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = (0, _localization2.default)(\"Create a collection from a list of datasets\");\n return collectionCreatorModal(elements, options, ListCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a list collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createListCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = listCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function creationFn(elements, name, hideSourceItems) {\n elements = elements.map(function (element) {\n return {\n id: element.id,\n name: element.name,\n\n //TODO: this allows for list:list even if the filter above does not - reconcile\n src: element.history_content_type === \"dataset\" ? \"hda\" : \"hdca\"\n };\n });\n return contents.createHDCA(elements, \"list\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexports.default = {\n DatasetCollectionElementView: DatasetCollectionElementView,\n ListCollectionCreator: ListCollectionCreator,\n\n collectionCreatorModal: collectionCreatorModal,\n listCollectionCreatorModal: listCollectionCreatorModal,\n createListCollection: createListCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 36 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _collectionModel = __webpack_require__(37);\n\nvar _collectionModel2 = _interopRequireDefault(_collectionModel);\n\nvar _historyContentModel = __webpack_require__(73);\n\nvar _historyContentModel2 = _interopRequireDefault(_historyContentModel);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/*==============================================================================\n\nModels for DatasetCollections contained within a history.\n\nTODO:\n these might be compactable to one class if some duplication with\n collection-model is used.\n\n==============================================================================*/\nvar hcontentMixin = _historyContentModel2.default.HistoryContentMixin;\n\nvar ListDC = _collectionModel2.default.ListDatasetCollection;\nvar PairDC = _collectionModel2.default.PairDatasetCollection;\nvar ListPairedDC = _collectionModel2.default.ListPairedDatasetCollection;\nvar ListOfListsDC = _collectionModel2.default.ListOfListsDatasetCollection;\n\n//==============================================================================\n/** Override to post to contents route w/o id. */\nfunction buildHDCASave(_super) {\n return function _save(attributes, options) {\n if (this.isNew()) {\n options = options || {};\n options.url = this.urlRoot + this.get(\"history_id\") + \"/contents\";\n attributes = attributes || {};\n attributes.type = \"dataset_collection\";\n }\n return _super.call(this, attributes, options);\n };\n}\n\n//==============================================================================\n/** @class Backbone model for List Dataset Collection within a History.\n */\nvar HistoryListDatasetCollection = ListDC.extend(hcontentMixin).extend(\n/** @lends HistoryListDatasetCollection.prototype */{\n defaults: _.extend(_.clone(ListDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"History\" + ListDC.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** @class Backbone model for Pair Dataset Collection within a History.\n * @constructs\n */\nvar HistoryPairDatasetCollection = PairDC.extend(hcontentMixin).extend(\n/** @lends HistoryPairDatasetCollection.prototype */{\n defaults: _.extend(_.clone(PairDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(PairDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"History\" + PairDC.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Pairs Dataset Collection within a History. */\nvar HistoryListPairedDatasetCollection = ListPairedDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListPairedDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListPairedDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"History\" + ListPairedDC.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Lists Dataset Collection within a History. */\nvar HistoryListOfListsDatasetCollection = ListOfListsDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListOfListsDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListOfListsDC.prototype.save),\n\n /** String representation. */\n toString: function toString() {\n return \"HistoryListOfListsDatasetCollection(\" + this.get(\"name\") + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n HistoryListDatasetCollection: HistoryListDatasetCollection,\n HistoryPairDatasetCollection: HistoryPairDatasetCollection,\n HistoryListPairedDatasetCollection: HistoryListPairedDatasetCollection,\n HistoryListOfListsDatasetCollection: HistoryListOfListsDatasetCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 37 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, Backbone, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _datasetModel = __webpack_require__(72);\n\nvar _datasetModel2 = _interopRequireDefault(_datasetModel);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/*\nNotes:\n\nTerminology:\n DatasetCollection/DC : a container of datasets or nested DatasetCollections\n Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection\n HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history\n\n\nThis all seems too complex unfortunately:\n\n- Terminology collision between DatasetCollections (DCs) and Backbone Collections.\n- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*\n either a dataset or a nested DC. This would make the hierarchy much taller. I've\n decided to merge the contained JSON with the DC element json - making the 'has a'\n relation into an 'is a' relation. This seems simpler to me and allowed a lot of\n DRY in both models and views, but may make tracking or tracing within these models\n more difficult (since DatasetCollectionElements are now *also* DatasetAssociations\n or DatasetCollections (nested)). This also violates the rule of thumb about\n favoring aggregation over inheritance.\n- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.\n These each should a) be usable on their own, b) be usable in the context of\n nesting within a collection model (at least in the case of ListPaired), and\n c) be usable within the context of other container models (like History or\n LibraryFolder, etc.). I've tried to separate/extract classes in order to\n handle those three situations, but it's proven difficult to do in a simple,\n readable manner.\n- Ideally, histories and libraries would inherit from the same server models as\n dataset collections do since they are (in essence) dataset collections themselves -\n making the whole nested structure simpler. This would be a large, error-prone\n refactoring and migration.\n\nMany of the classes and heirarchy are meant as extension points so, while the\nrelations and flow may be difficult to understand initially, they'll allow us to\nhandle the growth or flux dataset collection in the future (w/o actually implementing\nany YAGNI).\n\n*/\n//_________________________________________________________________________________________________ ELEMENTS\n/** @class mixin for Dataset collection elements.\n * When collection elements are passed from the API, the underlying element is\n * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).\n * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues\n * effectively changing a DCE from a container to a subclass (has a --> is a).\n */\nvar DatasetCollectionElementMixin = {\n /** default attributes used by elements in a dataset collection */\n defaults: {\n model_class: \"DatasetCollectionElement\",\n element_identifier: null,\n element_index: null,\n element_type: null\n },\n\n /** merge the attributes of the sub-object 'object' into this model */\n _mergeObject: function _mergeObject(attributes) {\n // if we don't preserve and correct ids here, the element id becomes the object id\n // and collision in backbone's _byId will occur and only\n _.extend(attributes, attributes.object, {\n element_id: attributes.id\n });\n delete attributes.object;\n return attributes;\n },\n\n /** override to merge this.object into this */\n constructor: function constructor(attributes, options) {\n // console.debug( '\\t DatasetCollectionElement.constructor:', attributes, options );\n attributes = this._mergeObject(attributes);\n this.idAttribute = \"element_id\";\n Backbone.Model.apply(this, arguments);\n },\n\n /** when the model is fetched, merge this.object into this */\n parse: function parse(response, options) {\n var attributes = response;\n attributes = this._mergeObject(attributes);\n return attributes;\n }\n};\n\n/** @class Concrete class of Generic DatasetCollectionElement */\nvar DatasetCollectionElement = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(DatasetCollectionElementMixin).extend({ _logNamespace: \"collections\" });\n\n//==============================================================================\n/** @class Base/Abstract Backbone collection for Generic DCEs. */\nvar DCECollection = Backbone.Collection.extend(_baseMvc2.default.LoggableMixin).extend(\n/** @lends DCECollection.prototype */{\n _logNamespace: \"collections\",\n\n model: DatasetCollectionElement,\n\n /** String representation. */\n toString: function toString() {\n return [\"DatasetCollectionElementCollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone model for a dataset collection element that is a dataset (HDA).\n */\nvar DatasetDCE = _datasetModel2.default.DatasetAssociation.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends DatasetDCE.prototype */{\n /** url fn */\n url: function url() {\n // won't always be an hda\n if (!this.has(\"history_id\")) {\n console.warn(\"no endpoint for non-hdas within a collection yet\");\n // (a little silly since this api endpoint *also* points at hdas)\n return Galaxy.root + \"api/datasets\";\n }\n return Galaxy.root + \"api/histories/\" + this.get(\"history_id\") + \"/contents/\" + this.get(\"id\");\n },\n\n defaults: _.extend({}, _datasetModel2.default.DatasetAssociation.prototype.defaults, DatasetCollectionElementMixin.defaults),\n\n _downloadQueryParameters: function _downloadQueryParameters() {\n var fileExt = this.get(\"file_ext\");\n var elementIdentifier = this.get(\"element_identifier\");\n var parentHdcaId = this.get(\"parent_hdca_id\");\n return \"?to_ext=\" + fileExt + \"&hdca_id=\" + parentHdcaId + \"&element_identifier=\" + elementIdentifier;\n },\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually for now\n /** call the mixin constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t DatasetDCE.constructor:\", attributes, options);\n //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function hasDetails() {\n return this.elements && this.elements.length;\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.get(\"element_identifier\");\n return \"DatasetDCE({objStr})\";\n }\n}));\n\n//==============================================================================\n/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).\n */\nvar DatasetDCECollection = DCECollection.extend(\n/** @lends DatasetDCECollection.prototype */{\n model: DatasetDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"DatasetDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//_________________________________________________________________________________________________ COLLECTIONS\n/** @class Backbone model for Dataset Collections.\n * The DC API returns an array of JSON objects under the attribute elements.\n * This model:\n * - removes that array/attribute ('elements') from the model,\n * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),\n * - passes that json onto the bbone collection\n * - caches the bbone collection in this.elements\n */\nvar DatasetCollection = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.SearchableModelMixin).extend(\n/** @lends DatasetCollection.prototype */{\n _logNamespace: \"collections\",\n\n /** default attributes for a model */\n defaults: {\n /* 'list', 'paired', or 'list:paired' */\n collection_type: null,\n //??\n deleted: false\n },\n\n /** Which class to use for elements */\n collectionClass: DCECollection,\n\n /** set up: create elements instance var and (on changes to elements) update them */\n initialize: function initialize(model, options) {\n this.debug(this + \"(DatasetCollection).initialize:\", model, options, this);\n this.elements = this._createElementsModel();\n this.on(\"change:elements\", function () {\n this.log(\"change:elements\");\n //TODO: prob. better to update the collection instead of re-creating it\n this.elements = this._createElementsModel();\n });\n },\n\n /** move elements model attribute to full collection */\n _createElementsModel: function _createElementsModel() {\n this.debug(this + \"._createElementsModel\", this.collectionClass, this.get(\"elements\"), this.elements);\n //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?\n var elements = this.get(\"elements\") || [];\n this.unset(\"elements\", { silent: true });\n var self = this;\n _.each(elements, function (element, index) {\n _.extend(element, {\n parent_hdca_id: self.get(\"id\")\n });\n });\n this.elements = new this.collectionClass(elements);\n //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );\n return this.elements;\n },\n\n // ........................................................................ common queries\n /** pass the elements back within the model json when this is serialized */\n toJSON: function toJSON() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n if (this.elements) {\n json.elements = this.elements.toJSON();\n }\n return json;\n },\n\n /** Is this collection in a 'ready' state no processing (for the collection) is left\n * to do on the server.\n */\n inReadyState: function inReadyState() {\n var populated = this.get(\"populated\");\n return this.isDeletedOrPurged() || populated;\n },\n\n //TODO:?? the following are the same interface as DatasetAssociation - can we combine?\n /** Does the DC contain any elements yet? Is a fetch() required? */\n hasDetails: function hasDetails() {\n return this.elements.length !== 0;\n },\n\n /** Given the filters, what models in this.elements would be returned? */\n getVisibleContents: function getVisibleContents(filters) {\n // filters unused for now\n return this.elements;\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function parse(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function _delete(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function undelete(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Is this collection deleted or purged? */\n isDeletedOrPurged: function isDeletedOrPurged() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n // ........................................................................ searchable\n /** searchable attributes for collections */\n searchAttributes: [\"name\", \"tags\"],\n\n // ........................................................................ misc\n /** String representation */\n toString: function toString() {\n var idAndName = [this.get(\"id\"), this.get(\"name\") || this.get(\"element_identifier\")];\n return \"DatasetCollection(\" + idAndName.join(\",\") + \")\";\n }\n});\n\n//==============================================================================\n/** Model for a DatasetCollection containing datasets (non-nested).\n */\nvar ListDatasetCollection = DatasetCollection.extend(\n/** @lends ListDatasetCollection.prototype */{\n /** override since we know the collection will only contain datasets */\n collectionClass: DatasetDCECollection,\n\n /** String representation. */\n toString: function toString() {\n return \"List\" + DatasetCollection.prototype.toString.call(this);\n }\n});\n\n//==============================================================================\n/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).\n */\nvar PairDatasetCollection = ListDatasetCollection.extend(\n/** @lends PairDatasetCollection.prototype */{\n /** String representation. */\n toString: function toString() {\n return \"Pair\" + DatasetCollection.prototype.toString.call(this);\n }\n});\n\n//_________________________________________________________________________________________________ NESTED COLLECTIONS\n// this is where things get weird, man. Weird.\n//TODO: it might be possible to compact all the following...I think.\n//==============================================================================\n/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection\n * (a nested collection). Currently only list:paired.\n */\nvar NestedDCDCE = DatasetCollection.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends NestedDCDCE.prototype */{\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** call the mixin constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t NestedDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.object ? \"\" + this.object : this.get(\"element_identifier\");\n return [\"NestedDCDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).\n */\nvar NestedDCDCECollection = DCECollection.extend(\n/** @lends NestedDCDCECollection.prototype */{\n /** This is a collection of nested collections */\n model: NestedDCDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"NestedDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.\n */\nvar NestedPairDCDCE = PairDatasetCollection.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends NestedPairDCDCE.prototype */{\n //TODO:?? possibly rename to NestedDatasetCollection?\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** This is both a collection and a collection element - call the constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t NestedPairDCDCE.constructor:\", attributes, options);\n //DatasetCollection.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.object ? \"\" + this.object : this.get(\"element_identifier\");\n return [\"NestedPairDCDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection for a backbone collection containing paired dataset collections.\n */\nvar NestedPairDCDCECollection = NestedDCDCECollection.extend(\n/** @lends PairDCDCECollection.prototype */{\n /** We know this collection is composed of only nested pair collections */\n model: NestedPairDCDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"NestedPairDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).\n */\nvar ListPairedDatasetCollection = DatasetCollection.extend(\n/** @lends ListPairedDatasetCollection.prototype */{\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedPairDCDCECollection,\n\n /** String representation. */\n toString: function toString() {\n return [\"ListPairedDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone model for a list dataset collection within a list:list dataset collection. */\nvar NestedListDCDCE = ListDatasetCollection.extend(_baseMvc2.default.mixin(DatasetCollectionElementMixin,\n/** @lends NestedListDCDCE.prototype */{\n /** This is both a collection and a collection element - call the constructor */\n constructor: function constructor(attributes, options) {\n this.debug(\"\\t NestedListDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function toString() {\n var objStr = this.object ? \"\" + this.object : this.get(\"element_identifier\");\n return [\"NestedListDCDCE(\", objStr, \")\"].join(\"\");\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection containing list dataset collections. */\nvar NestedListDCDCECollection = NestedDCDCECollection.extend({\n /** We know this collection is composed of only nested pair collections */\n model: NestedListDCDCE,\n\n /** String representation. */\n toString: function toString() {\n return [\"NestedListDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains other lists. */\nvar ListOfListsDatasetCollection = DatasetCollection.extend({\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedListDCDCECollection,\n\n /** String representation. */\n toString: function toString() {\n return [\"ListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n ListDatasetCollection: ListDatasetCollection,\n PairDatasetCollection: PairDatasetCollection,\n ListPairedDatasetCollection: ListPairedDatasetCollection,\n ListOfListsDatasetCollection: ListOfListsDatasetCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 38 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, jQuery, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _historyContents = __webpack_require__(39);\n\nvar _historyContents2 = _interopRequireDefault(_historyContents);\n\nvar _historyPreferences = __webpack_require__(40);\n\nvar _historyPreferences2 = _interopRequireDefault(_historyPreferences);\n\nvar _controlledFetchCollection = __webpack_require__(80);\n\nvar _controlledFetchCollection2 = _interopRequireDefault(_controlledFetchCollection);\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/** @class Model for a Galaxy history resource - both a record of user\n * tool use and a collection of the datasets those tools produced.\n * @name History\n * @augments Backbone.Model\n */\nvar History = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.mixin(_baseMvc2.default.SearchableModelMixin,\n/** @lends History.prototype */{\n _logNamespace: \"history\",\n\n /** ms between fetches when checking running jobs/datasets for updates */\n UPDATE_DELAY: 4000,\n\n // values from api (may need more)\n defaults: {\n model_class: \"History\",\n id: null,\n name: \"Unnamed History\",\n state: \"new\",\n\n deleted: false,\n contents_active: {},\n contents_states: {}\n },\n\n urlRoot: Galaxy.root + \"api/histories\",\n\n contentsClass: _historyContents2.default.HistoryContents,\n\n /** What model fields to search with */\n searchAttributes: [\"name\", \"annotation\", \"tags\"],\n\n /** Adding title and singular tag */\n searchAliases: {\n title: \"name\",\n tag: \"tags\"\n },\n\n // ........................................................................ set up/tear down\n /** Set up the model\n * @param {Object} historyJSON model data for this History\n * @param {Object} options any extra settings including logger\n */\n initialize: function initialize(historyJSON, options) {\n options = options || {};\n this.logger = options.logger || null;\n this.log(this + \".initialize:\", historyJSON, options);\n\n /** HistoryContents collection of the HDAs contained in this history. */\n this.contents = new this.contentsClass([], {\n history: this,\n historyId: this.get(\"id\"),\n order: options.order\n });\n\n this._setUpListeners();\n this._setUpCollectionListeners();\n\n /** cached timeout id for the dataset updater */\n this.updateTimeoutId = null;\n },\n\n /** set up any event listeners for this history including those to the contained HDAs\n * events: error:contents if an error occurred with the contents collection\n */\n _setUpListeners: function _setUpListeners() {\n // if the model's id changes ('current' or null -> an actual id), update the contents history_id\n return this.on({\n error: function error(model, xhr, options, msg, details) {\n this.clearUpdateTimeout();\n },\n \"change:id\": function changeId(model, newId) {\n if (this.contents) {\n this.contents.historyId = newId;\n }\n }\n });\n },\n\n /** event handlers for the contents submodels */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n if (!this.contents) {\n return this;\n }\n // bubble up errors\n return this.listenTo(this.contents, {\n error: function error() {\n this.trigger.apply(this, jQuery.makeArray(arguments));\n }\n });\n },\n\n // ........................................................................ derived attributes\n /** */\n contentsShown: function contentsShown() {\n var contentsActive = this.get(\"contents_active\");\n var shown = contentsActive.active || 0;\n shown += this.contents.includeDeleted ? contentsActive.deleted : 0;\n shown += this.contents.includeHidden ? contentsActive.hidden : 0;\n return shown;\n },\n\n /** convert size in bytes to a more human readable version */\n nice_size: function nice_size() {\n var size = this.get(\"size\");\n return size ? _utils2.default.bytesToString(size, true, 2) : (0, _localization2.default)(\"(empty)\");\n },\n\n /** override to add nice_size */\n toJSON: function toJSON() {\n return _.extend(Backbone.Model.prototype.toJSON.call(this), {\n nice_size: this.nice_size()\n });\n },\n\n /** override to allow getting nice_size */\n get: function get(key) {\n if (key === \"nice_size\") {\n return this.nice_size();\n }\n return Backbone.Model.prototype.get.apply(this, arguments);\n },\n\n // ........................................................................ common queries\n /** T/F is this history owned by the current user (Galaxy.user)\n * Note: that this will return false for an anon user even if the history is theirs.\n */\n ownedByCurrUser: function ownedByCurrUser() {\n // no currUser\n if (!Galaxy || !Galaxy.user) {\n return false;\n }\n // user is anon or history isn't owned\n if (Galaxy.user.isAnonymous() || Galaxy.user.id !== this.get(\"user_id\")) {\n return false;\n }\n return true;\n },\n\n /** Return the number of running jobs assoc with this history (note: unknown === 0) */\n numOfUnfinishedJobs: function numOfUnfinishedJobs() {\n var unfinishedJobIds = this.get(\"non_ready_jobs\");\n return unfinishedJobIds ? unfinishedJobIds.length : 0;\n },\n\n /** Return the number of running hda/hdcas in this history (note: unknown === 0) */\n numOfUnfinishedShownContents: function numOfUnfinishedShownContents() {\n return this.contents.runningAndActive().length || 0;\n },\n\n // ........................................................................ updates\n _fetchContentRelatedAttributes: function _fetchContentRelatedAttributes() {\n var contentRelatedAttrs = [\"size\", \"non_ready_jobs\", \"contents_active\", \"hid_counter\"];\n return this.fetch({\n data: $.param({\n keys: contentRelatedAttrs.join(\",\")\n })\n });\n },\n\n /** check for any changes since the last time we updated (or fetch all if ) */\n refresh: function refresh(options) {\n var _this = this;\n\n // console.log( this + '.refresh' );\n options = options || {};\n\n // note if there was no previous update time, all summary contents will be fetched\n var lastUpdateTime = this.lastUpdateTime;\n // if we don't flip this, then a fully-fetched list will not be re-checked via fetch\n this.contents.allFetched = false;\n var fetchFn = this.contents.currentPage !== 0 ? function () {\n return _this.contents.fetchPage(_this.contents.currentPage);\n } : function () {\n return _this.contents.fetchUpdated(lastUpdateTime);\n };\n // note: if there was no previous update time, all summary contents will be fetched\n return fetchFn().done(function (response, status, xhr) {\n var serverResponseDatetime;\n try {\n serverResponseDatetime = new Date(xhr.getResponseHeader(\"Date\"));\n } catch (err) {}\n _this.lastUpdateTime = serverResponseDatetime || new Date();\n _this.checkForUpdates(options);\n });\n },\n\n /** continuously fetch updated contents every UPDATE_DELAY ms if this history's datasets or jobs are unfinished */\n checkForUpdates: function checkForUpdates(options) {\n var _this2 = this;\n\n // console.log( this + '.checkForUpdates' );\n options = options || {};\n var delay = this.UPDATE_DELAY;\n if (!this.id) {\n return;\n }\n\n var _delayThenUpdate = function _delayThenUpdate() {\n // prevent buildup of updater timeouts by clearing previous if any, then set new and cache id\n _this2.clearUpdateTimeout();\n _this2.updateTimeoutId = setTimeout(function () {\n _this2.refresh(options);\n }, delay);\n };\n\n // if there are still datasets in the non-ready state, recurse into this function with the new time\n var nonReadyContentCount = this.numOfUnfinishedShownContents();\n // console.log( 'nonReadyContentCount:', nonReadyContentCount );\n if (nonReadyContentCount > 0) {\n _delayThenUpdate();\n } else {\n // no datasets are running, but currently runnning jobs may still produce new datasets\n // see if the history has any running jobs and continue to update if so\n // (also update the size for the user in either case)\n this._fetchContentRelatedAttributes().done(function (historyData) {\n // console.log( 'non_ready_jobs:', historyData.non_ready_jobs );\n if (_this2.numOfUnfinishedJobs() > 0) {\n _delayThenUpdate();\n } else {\n // otherwise, let listeners know that all updates have stopped\n _this2.trigger(\"ready\");\n }\n });\n }\n },\n\n /** clear the timeout and the cached timeout id */\n clearUpdateTimeout: function clearUpdateTimeout() {\n if (this.updateTimeoutId) {\n clearTimeout(this.updateTimeoutId);\n this.updateTimeoutId = null;\n }\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function parse(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** fetch this histories data (using options) then it's contents (using contentsOptions) */\n fetchWithContents: function fetchWithContents(options, contentsOptions) {\n options = options || {};\n var self = this;\n\n // console.log( this + '.fetchWithContents' );\n // TODO: push down to a base class\n options.view = \"dev-detailed\";\n\n // fetch history then use history data to fetch (paginated) contents\n return this.fetch(options).then(function getContents(history) {\n self.contents.history = self;\n self.contents.setHistoryId(history.id);\n return self.fetchContents(contentsOptions);\n });\n },\n\n /** fetch this histories contents, adjusting options based on the stored history preferences */\n fetchContents: function fetchContents(options) {\n options = options || {};\n var self = this;\n\n // we're updating, reset the update time\n self.lastUpdateTime = new Date();\n return self.contents.fetchCurrentPage(options);\n },\n\n /** save this history, _Mark_ing it as deleted (just a flag) */\n _delete: function _delete(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */\n purge: function purge(options) {\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true, purged: true }, options);\n },\n /** save this history, _Mark_ing it as undeleted */\n undelete: function undelete(options) {\n if (!this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Make a copy of this history on the server\n * @param {Boolean} current if true, set the copy as the new current history (default: true)\n * @param {String} name name of new history (default: none - server sets to: Copy of )\n * @fires copied passed this history and the response JSON from the copy\n * @returns {xhr}\n */\n copy: function copy(current, name, allDatasets) {\n current = current !== undefined ? current : true;\n if (!this.id) {\n throw new Error(\"You must set the history ID before copying it.\");\n }\n\n var postData = { history_id: this.id };\n if (current) {\n postData.current = true;\n }\n if (name) {\n postData.name = name;\n }\n if (!allDatasets) {\n postData.all_datasets = false;\n }\n postData.view = \"dev-detailed\";\n\n var history = this;\n var copy = jQuery.post(this.urlRoot, postData);\n // if current - queue to setAsCurrent before firing 'copied'\n if (current) {\n return copy.then(function (response) {\n var newHistory = new History(response);\n return newHistory.setAsCurrent().done(function () {\n history.trigger(\"copied\", history, response);\n });\n });\n }\n return copy.done(function (response) {\n history.trigger(\"copied\", history, response);\n });\n },\n\n setAsCurrent: function setAsCurrent() {\n var history = this;\n\n var xhr = jQuery.getJSON(Galaxy.root + \"history/set_as_current?id=\" + this.id);\n\n xhr.done(function () {\n history.trigger(\"set-as-current\", history);\n });\n return xhr;\n },\n\n // ........................................................................ misc\n toString: function toString() {\n return \"History(\" + this.get(\"id\") + \",\" + this.get(\"name\") + \")\";\n }\n}));\n\n//==============================================================================\nvar _collectionSuper = _controlledFetchCollection2.default.InfinitelyScrollingCollection;\n/** @class A collection of histories (per user)\n * that maintains the current history as the first in the collection.\n * New or copied histories become the current history.\n */\nvar HistoryCollection = _collectionSuper.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n model: History,\n /** @type {String} initial order used by collection */\n order: \"update_time\",\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: 10,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 10,\n\n initialize: function initialize(models, options) {\n options = options || {};\n this.log(\"HistoryCollection.initialize\", models, options);\n _collectionSuper.prototype.initialize.call(this, models, options);\n\n /** @type {boolean} should deleted histories be included */\n this.includeDeleted = options.includeDeleted || false;\n\n /** @type {String} encoded id of the history that's current */\n this.currentHistoryId = options.currentHistoryId;\n\n this.setUpListeners();\n // note: models are sent to reset *after* this fn ends; up to this point\n // the collection *is empty*\n },\n\n urlRoot: Galaxy.root + \"api/histories\",\n url: function url() {\n return this.urlRoot;\n },\n\n /** set up reflexive event handlers */\n setUpListeners: function setUpListeners() {\n return this.on({\n // when a history is deleted, remove it from the collection (if optionally set to do so)\n \"change:deleted\": function changeDeleted(history) {\n // TODO: this becomes complicated when more filters are used\n this.debug(\"change:deleted\", this.includeDeleted, history.get(\"deleted\"));\n if (!this.includeDeleted && history.get(\"deleted\")) {\n this.remove(history);\n }\n },\n // listen for a history copy, setting it to current\n copied: function copied(original, newData) {\n this.setCurrent(new History(newData, []));\n },\n // when a history is made current, track the id in the collection\n \"set-as-current\": function setAsCurrent(history) {\n var oldCurrentId = this.currentHistoryId;\n this.trigger(\"no-longer-current\", oldCurrentId);\n this.currentHistoryId = history.id;\n }\n });\n },\n\n /** override to change view */\n _buildFetchData: function _buildFetchData(options) {\n return _.extend(_collectionSuper.prototype._buildFetchData.call(this, options), {\n view: \"dev-detailed\"\n });\n },\n\n /** override to filter out deleted and purged */\n _buildFetchFilters: function _buildFetchFilters(options) {\n var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n } else {\n // force API to return both deleted and non\n //TODO: when the API is updated, remove this\n filters.deleted = null;\n }\n return _.defaults(superFilters, filters);\n },\n\n /** override to fetch current as well (as it may be outside the first 10, etc.) */\n fetchFirst: function fetchFirst(options) {\n var self = this;\n // TODO: batch?\n var xhr = $.when();\n if (this.currentHistoryId) {\n xhr = _collectionSuper.prototype.fetchFirst.call(self, {\n silent: true,\n limit: 1,\n filters: {\n // without these a deleted current history will return [] here and block the other xhr\n purged: \"\",\n deleted: \"\",\n \"encoded_id-in\": this.currentHistoryId\n }\n });\n }\n return xhr.then(function () {\n options = options || {};\n options.offset = 0;\n return self.fetchMore(options);\n });\n },\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_collectionSuper.prototype.comparators), {\n name: _baseMvc2.default.buildComparator(\"name\", {\n ascending: true\n }),\n \"name-dsc\": _baseMvc2.default.buildComparator(\"name\", {\n ascending: false\n }),\n size: _baseMvc2.default.buildComparator(\"size\", {\n ascending: false\n }),\n \"size-asc\": _baseMvc2.default.buildComparator(\"size\", {\n ascending: true\n })\n }),\n\n /** override to always have the current history first */\n sort: function sort(options) {\n options = options || {};\n var silent = options.silent;\n var currentHistory = this.remove(this.get(this.currentHistoryId));\n _collectionSuper.prototype.sort.call(this, _.defaults({ silent: true }, options));\n this.unshift(currentHistory, { silent: true });\n if (!silent) {\n this.trigger(\"sort\", this, options);\n }\n return this;\n },\n\n /** create a new history and by default set it to be the current history */\n create: function create(data, hdas, historyOptions, xhrOptions) {\n //TODO: .create is actually a collection function that's overridden here\n var collection = this;\n\n var xhr = jQuery.getJSON(Galaxy.root + \"history/create_new_current\");\n return xhr.done(function (newData) {\n collection.setCurrent(new History(newData, [], historyOptions || {}));\n });\n },\n\n /** set the current history to the given history, placing it first in the collection.\n * Pass standard bbone options for use in unshift.\n * @triggers new-current passed history and this collection\n */\n setCurrent: function setCurrent(history, options) {\n options = options || {};\n // new histories go in the front\n this.unshift(history, options);\n this.currentHistoryId = history.get(\"id\");\n if (!options.silent) {\n this.trigger(\"new-current\", history, this);\n }\n return this;\n },\n\n toString: function toString() {\n return \"HistoryCollection(\" + this.length + \",current:\" + this.currentHistoryId + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n History: History,\n HistoryCollection: HistoryCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 39 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, jQuery, Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _controlledFetchCollection = __webpack_require__(80);\n\nvar _controlledFetchCollection2 = _interopRequireDefault(_controlledFetchCollection);\n\nvar _hdaModel = __webpack_require__(81);\n\nvar _hdaModel2 = _interopRequireDefault(_hdaModel);\n\nvar _hdcaModel = __webpack_require__(36);\n\nvar _hdcaModel2 = _interopRequireDefault(_hdcaModel);\n\nvar _historyPreferences = __webpack_require__(40);\n\nvar _historyPreferences2 = _interopRequireDefault(_historyPreferences);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _ajaxQueue = __webpack_require__(153);\n\nvar _ajaxQueue2 = _interopRequireDefault(_ajaxQueue);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _controlledFetchCollection2.default.PaginatedCollection;\n/** @class Backbone collection for history content.\n * NOTE: history content seems like a dataset collection, but differs in that it is mixed:\n * each element can be either an HDA (dataset) or a DatasetCollection and co-exist on\n * the same level.\n * Dataset collections on the other hand are not mixed and (so far) can only contain either\n * HDAs or child dataset collections on one level.\n * This is why this does not inherit from any of the DatasetCollections (currently).\n */\nvar HistoryContents = _super.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n // ........................................................................ set up\n limitPerPage: 500,\n\n /** @type {Integer} how many contents per call to fetch when using progressivelyFetchDetails */\n limitPerProgressiveFetch: 500,\n\n /** @type {String} order used here and when fetching from server */\n order: \"hid\",\n\n /** root api url */\n urlRoot: Galaxy.root + \"api/histories\",\n\n /** complete api url */\n url: function url() {\n return this.urlRoot + \"/\" + this.historyId + \"/contents\";\n },\n\n /** Set up */\n initialize: function initialize(models, options) {\n options = options || {};\n _super.prototype.initialize.call(this, models, options);\n\n this.history = options.history || null;\n this.setHistoryId(options.historyId || null);\n /** @type {Boolean} does this collection contain and fetch deleted elements */\n this.includeDeleted = options.includeDeleted || this.includeDeleted;\n /** @type {Boolean} does this collection contain and fetch non-visible elements */\n this.includeHidden = options.includeHidden || this.includeHidden;\n\n // backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection\n // and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute\n // manually here - if we don't, contents will not merge but be replaced/swapped.\n this.model.prototype.idAttribute = \"type_id\";\n },\n\n // ........................................................................ composite collection\n /** since history content is a mix, override model fn into a factory, creating based on history_content_type */\n model: function model(attrs, options) {\n if (attrs.history_content_type === \"dataset\") {\n return new _hdaModel2.default.HistoryDatasetAssociation(attrs, options);\n } else if (attrs.history_content_type === \"dataset_collection\") {\n switch (attrs.collection_type) {\n case \"list\":\n return new _hdcaModel2.default.HistoryListDatasetCollection(attrs, options);\n case \"paired\":\n return new _hdcaModel2.default.HistoryPairDatasetCollection(attrs, options);\n case \"list:paired\":\n return new _hdcaModel2.default.HistoryListPairedDatasetCollection(attrs, options);\n case \"list:list\":\n return new _hdcaModel2.default.HistoryListOfListsDatasetCollection(attrs, options);\n }\n // This is a hack inside a hack:\n // Raise a plain object with validationError to fake a model.validationError\n // (since we don't have a model to use validate with)\n // (the outer hack being the mixed content/model function in this collection)\n var msg = \"Unknown collection_type: \" + attrs.collection_type;\n console.warn(msg, attrs);\n return { validationError: msg };\n }\n return {\n validationError: \"Unknown history_content_type: \" + attrs.history_content_type\n };\n },\n\n setHistoryId: function setHistoryId(newId) {\n this.historyId = newId;\n this._setUpWebStorage();\n },\n\n /** Set up client side storage. Currently PersistanStorage keyed under 'history:' */\n _setUpWebStorage: function _setUpWebStorage(initialSettings) {\n // TODO: use initialSettings\n if (!this.historyId) {\n return;\n }\n this.storage = new _historyPreferences2.default.HistoryPrefs({\n id: _historyPreferences2.default.HistoryPrefs.historyStorageKey(this.historyId)\n });\n this.trigger(\"new-storage\", this.storage, this);\n\n this.on({\n \"include-deleted\": function includeDeleted(newVal) {\n this.storage.includeDeleted(newVal);\n },\n \"include-hidden\": function includeHidden(newVal) {\n this.storage.includeHidden(newVal);\n }\n });\n\n this.includeDeleted = this.storage.includeDeleted() || false;\n this.includeHidden = this.storage.includeHidden() || false;\n return this;\n },\n\n // ........................................................................ common queries\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_super.prototype.comparators), {\n name: _baseMvc2.default.buildComparator(\"name\", { ascending: true }),\n \"name-dsc\": _baseMvc2.default.buildComparator(\"name\", {\n ascending: false\n }),\n hid: _baseMvc2.default.buildComparator(\"hid\", { ascending: false }),\n \"hid-asc\": _baseMvc2.default.buildComparator(\"hid\", { ascending: true })\n }),\n\n /** Get every model in this collection not in a 'ready' state (running). */\n running: function running() {\n return this.filter(function (c) {\n return !c.inReadyState();\n });\n },\n\n /** return contents that are not ready and not deleted/hidden */\n runningAndActive: function runningAndActive() {\n return this.filter(function (c) {\n return !c.inReadyState() && c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\");\n });\n },\n\n /** Get the model with the given hid\n * @param {Int} hid the hid to search for\n * @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found\n */\n getByHid: function getByHid(hid) {\n // note: there *can* be more than one content with a given hid, this finds the first based on order\n return this.findWhere({ hid: hid });\n },\n\n /** return true if all contents have details */\n haveDetails: function haveDetails() {\n return this.all(function (c) {\n return c.hasDetails();\n });\n },\n\n // ........................................................................ hidden / deleted\n /** return a new contents collection of only hidden items */\n hidden: function hidden() {\n return this.filter(function (c) {\n return c.hidden();\n });\n },\n\n /** return a new contents collection of only hidden items */\n deleted: function deleted() {\n return this.filter(function (c) {\n return c.get(\"deleted\");\n });\n },\n\n /** return a new contents collection of only hidden items */\n visibleAndUndeleted: function visibleAndUndeleted() {\n return this.filter(function (c) {\n return c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\");\n });\n },\n\n /** create a setter in order to publish the change */\n setIncludeDeleted: function setIncludeDeleted(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeDeleted) {\n this.includeDeleted = setting;\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-deleted\", setting, this);\n }\n },\n\n /** create a setter in order to publish the change */\n setIncludeHidden: function setIncludeHidden(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeHidden) {\n this.includeHidden = setting;\n options = options || {};\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-hidden\", setting, this);\n }\n },\n\n // ........................................................................ ajax\n // ............ controlled fetch collection\n /** override to get expanded ids from sessionStorage and pass to API as details */\n fetch: function fetch(options) {\n options = options || {};\n if (this.historyId && !options.details) {\n var prefs = _historyPreferences2.default.HistoryPrefs.get(this.historyId).toJSON();\n if (!_.isEmpty(prefs.expandedIds)) {\n options.details = _.values(prefs.expandedIds).join(\",\");\n }\n }\n return _super.prototype.fetch.call(this, options);\n },\n\n // ............. ControlledFetch stuff\n /** override to include the API versioning flag */\n _buildFetchData: function _buildFetchData(options) {\n return _.extend(_super.prototype._buildFetchData.call(this, options), {\n v: \"dev\"\n });\n },\n\n /** Extend to include details and version */\n _fetchParams: _super.prototype._fetchParams.concat([\n // TODO: remove (the need for) both\n /** version */\n \"v\",\n /** dataset ids to get full details of */\n \"details\"]),\n\n /** override to add deleted/hidden filters */\n _buildFetchFilters: function _buildFetchFilters(options) {\n var superFilters = _super.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n }\n if (!this.includeHidden) {\n filters.visible = true;\n }\n return _.defaults(superFilters, filters);\n },\n\n // ............ paginated collection\n getTotalItemCount: function getTotalItemCount() {\n return this.history.contentsShown();\n },\n\n // ............ history contents specific ajax\n /** override to filter requested contents to those updated after the Date 'since' */\n fetchUpdated: function fetchUpdated(since, options) {\n if (since) {\n options = options || { filters: {} };\n options.remove = false;\n options.filters = {\n \"update_time-ge\": since.toISOString(),\n // workflows will produce hidden datasets (non-output datasets) that still\n // need to be updated in the collection or they'll update forever\n // we can remove the default visible filter by using an 'empty' value\n visible: \"\"\n };\n }\n return this.fetch(options);\n },\n\n /** fetch all the deleted==true contents of this collection */\n fetchDeleted: function fetchDeleted(options) {\n var _this = this;\n\n options = options || {};\n options.filters = _.extend(options.filters, {\n // all deleted, purged or not\n deleted: true,\n purged: undefined\n });\n options.remove = false;\n\n this.trigger(\"fetching-deleted\", this);\n return this.fetch(options).always(function () {\n _this.trigger(\"fetching-deleted-done\", _this);\n });\n },\n\n /** fetch all the visible==false contents of this collection */\n fetchHidden: function fetchHidden(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n visible: false\n });\n options.remove = false;\n\n self.trigger(\"fetching-hidden\", self);\n return self.fetch(options).always(function () {\n self.trigger(\"fetching-hidden-done\", self);\n });\n },\n\n /** fetch detailed model data for all contents in this collection */\n fetchAllDetails: function fetchAllDetails(options) {\n options = options || {};\n var detailsFlag = { details: \"all\" };\n options.data = _.extend(options.data || {}, detailsFlag);\n return this.fetch(options);\n },\n\n /** specialty fetch method for retrieving the element_counts of all hdcas in the history */\n fetchCollectionCounts: function fetchCollectionCounts(options) {\n options = options || {};\n options.keys = [\"type_id\", \"element_count\"].join(\",\");\n options.filters = _.extend(options.filters || {}, {\n history_content_type: \"dataset_collection\"\n });\n options.remove = false;\n return this.fetch(options);\n },\n\n // ............. quasi-batch ops\n // TODO: to batch\n /** helper that fetches using filterParams then calls save on each fetched using updateWhat as the save params */\n _filterAndUpdate: function _filterAndUpdate(filterParams, updateWhat) {\n var self = this;\n var idAttribute = self.model.prototype.idAttribute;\n var updateArgs = [updateWhat];\n\n return self.fetch({ filters: filterParams, remove: false }).then(function (fetched) {\n // convert filtered json array to model array\n fetched = fetched.reduce(function (modelArray, currJson, i) {\n var model = self.get(currJson[idAttribute]);\n return model ? modelArray.concat(model) : modelArray;\n }, []);\n return self.ajaxQueue(\"save\", updateArgs, fetched);\n });\n },\n\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function ajaxQueue(ajaxFn, args, collection) {\n collection = collection || this.models;\n return new _ajaxQueue2.default.AjaxQueue(collection.slice().reverse().map(function (content, i) {\n var fn = _.isString(ajaxFn) ? content[ajaxFn] : ajaxFn;\n return function () {\n return fn.apply(content, args);\n };\n })).deferred;\n },\n\n /** fetch contents' details in batches of limitPerCall - note: only get searchable details here */\n progressivelyFetchDetails: function progressivelyFetchDetails(options) {\n options = options || {};\n var deferred = jQuery.Deferred();\n var self = this;\n var limit = options.limitPerCall || self.limitPerProgressiveFetch;\n // TODO: only fetch tags and annotations if specifically requested\n var searchAttributes = _hdaModel2.default.HistoryDatasetAssociation.prototype.searchAttributes;\n var detailKeys = searchAttributes.join(\",\");\n\n function _recursivelyFetch(offset) {\n offset = offset || 0;\n var _options = _.extend(_.clone(options), {\n view: \"summary\",\n keys: detailKeys,\n limit: limit,\n offset: offset,\n reset: offset === 0,\n remove: false\n });\n\n _.defer(function () {\n self.fetch.call(self, _options).fail(deferred.reject).done(function (response) {\n deferred.notify(response, limit, offset);\n if (response.length !== limit) {\n self.allFetched = true;\n deferred.resolve(response, limit, offset);\n } else {\n _recursivelyFetch(offset + limit);\n }\n });\n });\n }\n _recursivelyFetch();\n return deferred;\n },\n\n /** does some bit of JSON represent something that can be copied into this contents collection */\n isCopyable: function isCopyable(contentsJSON) {\n var copyableModelClasses = [\"HistoryDatasetAssociation\", \"HistoryDatasetCollectionAssociation\"];\n return _.isObject(contentsJSON) && contentsJSON.id && _.contains(copyableModelClasses, contentsJSON.model_class);\n },\n\n /** copy an existing, accessible hda into this collection */\n copy: function copy(json) {\n // TODO: somehow showhorn all this into 'save'\n var id;\n\n var type;\n var contentType;\n if (_.isString(json)) {\n id = json;\n contentType = \"hda\";\n type = \"dataset\";\n } else {\n id = json.id;\n contentType = {\n HistoryDatasetAssociation: \"hda\",\n LibraryDatasetDatasetAssociation: \"ldda\",\n HistoryDatasetCollectionAssociation: \"hdca\"\n }[json.model_class] || \"hda\";\n type = contentType === \"hdca\" ? \"dataset_collection\" : \"dataset\";\n }\n var collection = this;\n\n var xhr = jQuery.ajax(this.url(), {\n method: \"POST\",\n contentType: \"application/json\",\n data: JSON.stringify({\n content: id,\n source: contentType,\n type: type\n })\n }).done(function (response) {\n collection.add([response], { parse: true });\n }).fail(function (error, status, message) {\n collection.trigger(\"error\", collection, xhr, {}, \"Error copying contents\", {\n type: type,\n id: id,\n source: contentType\n });\n });\n\n return xhr;\n },\n\n /** create a new HDCA in this collection */\n createHDCA: function createHDCA(elementIdentifiers, collectionType, name, hideSourceItems, options) {\n // normally collection.create returns the new model, but we need the promise from the ajax, so we fake create\n //precondition: elementIdentifiers is an array of plain js objects\n // in the proper form to create the collectionType\n var hdca = this.model({\n history_content_type: \"dataset_collection\",\n collection_type: collectionType,\n history_id: this.historyId,\n name: name,\n hide_source_items: hideSourceItems || false,\n // should probably be able to just send in a bunch of json here and restruct per class\n // note: element_identifiers is now (incorrectly) an attribute\n element_identifiers: elementIdentifiers\n // do not create the model on the client until the ajax returns\n });\n return hdca.save(options);\n },\n\n // ........................................................................ searching\n /** return true if all contents have the searchable attributes */\n haveSearchDetails: function haveSearchDetails() {\n return this.allFetched && this.all(function (content // null (which is a valid returned annotation value)\n ) {\n return (\n // will return false when using content.has( 'annotation' )\n //TODO: a bit hacky - formalize\n _.has(content.attributes, \"annotation\")\n );\n });\n },\n\n /** return a new collection of contents whose attributes contain the substring matchesWhat */\n matches: function matches(matchesWhat) {\n return this.filter(function (content) {\n return content.matches(matchesWhat);\n });\n },\n\n // ........................................................................ misc\n /** In this override, copy the historyId to the clone */\n clone: function clone() {\n var clone = Backbone.Collection.prototype.clone.call(this);\n clone.historyId = this.historyId;\n return clone;\n },\n\n /** String representation. */\n toString: function toString() {\n return [\"HistoryContents(\", [this.historyId, this.length].join(), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n HistoryContents: HistoryContents\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(2)))\n\n/***/ }),\n/* 40 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"history\";\n\n// ============================================================================\n/** session storage for individual history preferences */\nvar HistoryPrefs = _baseMvc2.default.SessionStorageModel.extend(\n/** @lends HistoryPrefs.prototype */{\n //TODO:?? move to user prefs?\n defaults: {\n //TODO:?? expandedIds to array?\n expandedIds: {},\n show_deleted: false,\n show_hidden: false\n },\n\n /** add an hda id to the hash of expanded hdas */\n addExpanded: function addExpanded(model) {\n //TODO: use type_id and not model\n var current = this.get(\"expandedIds\");\n current[model.id] = model.get(\"id\");\n this.save(\"expandedIds\", current);\n },\n\n /** remove an hda id from the hash of expanded hdas */\n removeExpanded: function removeExpanded(model) {\n var current = this.get(\"expandedIds\");\n delete current[model.id];\n this.save(\"expandedIds\", current);\n },\n\n isExpanded: function isExpanded(contentId) {\n return _.result(this.get(\"expandedIds\"), contentId, false);\n },\n\n allExpanded: function allExpanded() {\n return _.values(this.get(\"expandedIds\"));\n },\n\n clearExpanded: function clearExpanded() {\n this.set(\"expandedIds\", {});\n },\n\n includeDeleted: function includeDeleted(val) {\n // moving the invocation here so other components don't need to know the key\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_deleted\", val);\n }\n return this.get(\"show_deleted\");\n },\n\n includeHidden: function includeHidden(val) {\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_hidden\", val);\n }\n return this.get(\"show_hidden\");\n },\n\n toString: function toString() {\n return \"HistoryPrefs(\" + this.id + \")\";\n }\n}, {\n // ........................................................................ class vars\n // class lvl for access w/o instantiation\n storageKeyPrefix: \"history:\",\n\n /** key string to store each histories settings under */\n historyStorageKey: function historyStorageKey(historyId) {\n if (!historyId) {\n throw new Error(\"HistoryPrefs.historyStorageKey needs valid id: \" + historyId);\n }\n // single point of change\n return HistoryPrefs.storageKeyPrefix + historyId;\n },\n\n /** return the existing storage for the history with the given id (or create one if it doesn't exist) */\n get: function get(historyId) {\n return new HistoryPrefs({\n id: HistoryPrefs.historyStorageKey(historyId)\n });\n },\n\n /** clear all history related items in sessionStorage */\n clearAll: function clearAll(historyId) {\n for (var key in sessionStorage) {\n if (key.indexOf(HistoryPrefs.storageKeyPrefix) === 0) {\n sessionStorage.removeItem(key);\n }\n }\n }\n});\n\n//==============================================================================\nexports.default = {\n HistoryPrefs: HistoryPrefs\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 41 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"list\";\n//==============================================================================\n/** A view which, when first rendered, shows only summary data/attributes, but\n * can be expanded to show further details (and optionally fetch those\n * details from the server).\n */\nvar ExpandableView = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: Although the reasoning behind them is different, this shares a lot with HiddenUntilActivated above: combine them\n //PRECONDITION: model must have method hasDetails\n //PRECONDITION: subclasses must have templates.el and templates.details\n\n initialize: function initialize(attributes) {\n /** are the details of this view expanded/shown or not? */\n this.expanded = attributes.expanded || false;\n this.log(\"\\t expanded:\", this.expanded);\n this.fxSpeed = attributes.fxSpeed !== undefined ? attributes.fxSpeed : this.fxSpeed;\n },\n\n // ........................................................................ render main\n /** jq fx speed */\n fxSpeed: \"fast\",\n\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function render(speed) {\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n * If the view is already expanded, build the details as well.\n */\n _buildNewRender: function _buildNewRender() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = $(this.templates.el(this.model.toJSON(), this));\n if (this.expanded) {\n this.$details($newRender).replaceWith(this._renderDetails().show());\n }\n return $newRender;\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function _queueNewRender($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var view = this;\n\n if (speed === 0) {\n view._swapNewRender($newRender);\n view.trigger(\"rendered\", view);\n } else {\n $(view).queue(\"fx\", [function (next) {\n view.$el.fadeOut(speed, next);\n }, function (next) {\n view._swapNewRender($newRender);\n next();\n }, function (next) {\n view.$el.fadeIn(speed, next);\n }, function (next) {\n view.trigger(\"rendered\", view);\n next();\n }]);\n }\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function _swapNewRender($newRender) {\n return this.$el.empty().attr(\"class\", _.isFunction(this.className) ? this.className() : this.className).append($newRender.children());\n },\n\n /** set up js behaviors, event handlers for elements within the given container\n * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)\n */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)\n //make_popup_menus( $where );\n $where.find(\"[title]\").tooltip({ placement: \"bottom\" });\n },\n\n // ......................................................................... details\n /** shortcut to details DOM (as jQ) */\n $details: function $details($where) {\n $where = $where || this.$el;\n return $where.find(\"> .details\");\n },\n\n /** build the DOM for the details and set up behaviors on it */\n _renderDetails: function _renderDetails() {\n var $newDetails = $(this.templates.details(this.model.toJSON(), this));\n this._setUpBehaviors($newDetails);\n return $newDetails;\n },\n\n // ......................................................................... expansion/details\n /** Show or hide the details\n * @param {Boolean} expand if true, expand; if false, collapse\n */\n toggleExpanded: function toggleExpanded(expand) {\n expand = expand === undefined ? !this.expanded : expand;\n if (expand) {\n this.expand();\n } else {\n this.collapse();\n }\n return this;\n },\n\n /** Render and show the full, detailed body of this view including extra data and controls.\n * note: if the model does not have detailed data, fetch that data before showing the body\n * @fires expanded when a body has been expanded\n */\n expand: function expand() {\n var view = this;\n return view._fetchModelDetails().always(function () {\n view._expand();\n });\n },\n\n /** Check for model details and, if none, fetch them.\n * @returns {jQuery.promise} the model.fetch.xhr if details are being fetched, an empty promise if not\n */\n _fetchModelDetails: function _fetchModelDetails() {\n if (!this.model.hasDetails()) {\n return this.model.fetch();\n }\n return jQuery.when();\n },\n\n /** Inner fn called when expand (public) has fetched the details */\n _expand: function _expand() {\n var view = this;\n var $newDetails = view._renderDetails();\n view.$details().replaceWith($newDetails);\n // needs to be set after the above or the slide will not show\n view.expanded = true;\n view.$details().slideDown(view.fxSpeed, function () {\n view.trigger(\"expanded\", view);\n });\n },\n\n /** Hide the body/details of an HDA.\n * @fires collapsed when a body has been collapsed\n */\n collapse: function collapse() {\n this.debug(this + \"(ExpandableView).collapse\");\n var view = this;\n view.expanded = false;\n this.$details().slideUp(view.fxSpeed, function () {\n view.trigger(\"collapsed\", view);\n });\n }\n});\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * Inherits from Expandable, Selectable, Draggable.\n * The DOM contains warnings, a title bar, and a series of primary action controls.\n * Primary actions are meant to be easily accessible item functions (such as delete)\n * that are rendered in the title bar.\n *\n * Details are rendered when the user clicks the title bar or presses enter/space when\n * the title bar is in focus.\n *\n * Designed as a base class for history panel contents - but usable elsewhere (I hope).\n */\nvar ListItemView = ExpandableView.extend(_baseMvc2.default.mixin(_baseMvc2.default.SelectableViewMixin, _baseMvc2.default.DraggableViewMixin, {\n tagName: \"div\",\n className: \"list-item\",\n\n /** Set up the base class and all mixins */\n initialize: function initialize(attributes) {\n ExpandableView.prototype.initialize.call(this, attributes);\n _baseMvc2.default.SelectableViewMixin.initialize.call(this, attributes);\n _baseMvc2.default.DraggableViewMixin.initialize.call(this, attributes);\n this._setUpListeners();\n },\n\n /** event listeners */\n _setUpListeners: function _setUpListeners() {\n // hide the primary actions in the title bar when selectable and narrow\n this.on(\"selectable\", function (isSelectable) {\n if (isSelectable) {\n this.$(\".primary-actions\").hide();\n } else {\n this.$(\".primary-actions\").show();\n }\n }, this);\n return this;\n },\n\n // ........................................................................ rendering\n /** In this override, call methods to build warnings, titlebar and primary actions */\n _buildNewRender: function _buildNewRender() {\n var $newRender = ExpandableView.prototype._buildNewRender.call(this);\n $newRender.children(\".warnings\").replaceWith(this._renderWarnings());\n $newRender.children(\".title-bar\").replaceWith(this._renderTitleBar());\n $newRender.children(\".primary-actions\").append(this._renderPrimaryActions());\n $newRender.find(\"> .title-bar .subtitle\").replaceWith(this._renderSubtitle());\n return $newRender;\n },\n\n /** In this override, render the selector controls and set up dragging before the swap */\n _swapNewRender: function _swapNewRender($newRender) {\n ExpandableView.prototype._swapNewRender.call(this, $newRender);\n if (this.selectable) {\n this.showSelector(0);\n }\n if (this.draggable) {\n this.draggableOn();\n }\n return this.$el;\n },\n\n /** Render any warnings the item may need to show (e.g. \"I'm deleted\") */\n _renderWarnings: function _renderWarnings() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.warnings, function (templateFn) {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderTitleBar: function _renderTitleBar() {\n return $(this.templates.titleBar(this.model.toJSON(), this));\n },\n\n /** Return an array of jQ objects containing common/easily-accessible item controls */\n _renderPrimaryActions: function _renderPrimaryActions() {\n // override this\n return [];\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderSubtitle: function _renderSubtitle() {\n return $(this.templates.subtitle(this.model.toJSON(), this));\n },\n\n // ......................................................................... events\n /** event map */\n events: {\n // expand the body when the title is clicked or when in focus and space or enter is pressed\n \"click .title-bar\": \"_clickTitleBar\",\n \"keydown .title-bar\": \"_keyDownTitleBar\",\n \"click .selector\": \"toggleSelect\"\n },\n\n /** expand when the title bar is clicked */\n _clickTitleBar: function _clickTitleBar(event) {\n event.stopPropagation();\n if (event.altKey) {\n this.toggleSelect(event);\n if (!this.selectable) {\n this.showSelector();\n }\n } else {\n this.toggleExpanded();\n }\n },\n\n /** expand when the title bar is in focus and enter or space is pressed */\n _keyDownTitleBar: function _keyDownTitleBar(event) {\n // bail (with propagation) if keydown and not space or enter\n var KEYCODE_SPACE = 32;\n\n var KEYCODE_RETURN = 13;\n if (event && event.type === \"keydown\" && (event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN)) {\n this.toggleExpanded();\n event.stopPropagation();\n return false;\n }\n return true;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"ListItemView(\" + modelString + \")\";\n }\n}));\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListItemView.prototype.templates = function () {\n var elTemplato = _baseMvc2.default.wrapTemplate(['
\",\n // space for title bar buttons - gen. floated to the right\n '', '',\n\n // expandable area for more details\n '', \"
\"]);\n\n var warnings = {};\n\n var titleBarTemplate = _baseMvc2.default.wrapTemplate([\n // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display\n '
',\n //TODO: prob. belongs in dataset-list-item\n '', '
', '<%- element.name %>', \"
\", '', \"
\"], \"element\");\n\n var subtitleTemplate = _baseMvc2.default.wrapTemplate([\n // override this\n '']);\n\n var detailsTemplate = _baseMvc2.default.wrapTemplate([\n // override this\n '']);\n\n return {\n el: elTemplato,\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate,\n details: detailsTemplate\n };\n}();\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * *AND* can display some sub-list of it's own when expanded (e.g. dataset collections).\n * This list will 'foldout' when the item is expanded depending on this.foldoutStyle:\n * If 'foldout': will expand vertically to show the nested list\n * If 'drilldown': will overlay the parent list\n *\n * Inherits from ListItemView.\n *\n * _renderDetails does the work of creating this.details: a sub-view that shows the nested list\n */\nvar FoldoutListItemView = ListItemView.extend({\n /** If 'foldout': show the sub-panel inside the expanded item\n * If 'drilldown': only fire events and handle by pub-sub\n * (allow the panel containing this item to attach it, hide itself, etc.)\n */\n foldoutStyle: \"foldout\",\n /** Panel view class to instantiate for the sub-panel */\n foldoutPanelClass: null,\n\n /** override to:\n * add attributes foldoutStyle and foldoutPanelClass for config poly\n * disrespect attributes.expanded if drilldown\n */\n initialize: function initialize(attributes) {\n if (this.foldoutStyle === \"drilldown\") {\n this.expanded = false;\n }\n this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;\n this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;\n\n ListItemView.prototype.initialize.call(this, attributes);\n this.foldout = this._createFoldoutPanel();\n },\n\n /** in this override, attach the foldout panel when rendering details */\n _renderDetails: function _renderDetails() {\n if (this.foldoutStyle === \"drilldown\") {\n return $();\n }\n var $newDetails = ListItemView.prototype._renderDetails.call(this);\n return this._attachFoldout(this.foldout, $newDetails);\n },\n\n /** In this override, handle collection expansion. */\n _createFoldoutPanel: function _createFoldoutPanel() {\n var model = this.model;\n var FoldoutClass = this._getFoldoutPanelClass(model);\n var options = this._getFoldoutPanelOptions(model);\n\n var foldout = new FoldoutClass(_.extend(options, {\n model: model\n }));\n\n return foldout;\n },\n\n /** Stub to return proper foldout panel class */\n _getFoldoutPanelClass: function _getFoldoutPanelClass() {\n // override\n return this.foldoutPanelClass;\n },\n\n /** Stub to return proper foldout panel options */\n _getFoldoutPanelOptions: function _getFoldoutPanelOptions() {\n return {\n // propagate foldout style down\n foldoutStyle: this.foldoutStyle,\n fxSpeed: this.fxSpeed\n };\n },\n\n /** Render the foldout panel inside the view, hiding controls */\n _attachFoldout: function _attachFoldout(foldout, $whereTo) {\n $whereTo = $whereTo || this.$(\"> .details\");\n this.foldout = foldout.render(0);\n foldout.$(\"> .controls\").hide();\n return $whereTo.append(foldout.$el);\n },\n\n /** In this override, branch on foldoutStyle to show expanded */\n expand: function expand() {\n var view = this;\n return view._fetchModelDetails().always(function () {\n if (view.foldoutStyle === \"foldout\") {\n view._expand();\n } else if (view.foldoutStyle === \"drilldown\") {\n view._expandByDrilldown();\n }\n });\n },\n\n /** For drilldown, set up close handler and fire expanded:drilldown\n * containing views can listen to this and handle other things\n * (like hiding themselves) by listening for expanded/collapsed:drilldown\n */\n _expandByDrilldown: function _expandByDrilldown() {\n var view = this;\n // attachment and rendering done by listener\n view.listenTo(view.foldout, \"close\", function () {\n view.trigger(\"collapsed:drilldown\", view, view.foldout);\n });\n view.trigger(\"expanded:drilldown\", view, view.foldout);\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nFoldoutListItemView.prototype.templates = function () {\n var detailsTemplate = _baseMvc2.default.wrapTemplate(['
',\n // override with more info (that goes above the panel)\n \"
\"], \"collection\");\n\n return _.extend({}, ListItemView.prototype.templates, {\n details: detailsTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n ExpandableView: ExpandableView,\n ListItemView: ListItemView,\n FoldoutListItemView: FoldoutListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 42 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, jQuery, Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listItem = __webpack_require__(41);\n\nvar _listItem2 = _interopRequireDefault(_listItem);\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"dataset\";\n/*==============================================================================\nTODO:\n straighten out state rendering and templates used\n inaccessible/STATES.NOT_VIEWABLE is a special case\n simplify button rendering\n\n==============================================================================*/\nvar _super = _listItem2.default.ListItemView;\n/** @class Read only list view for either LDDAs, HDAs, or HDADCEs.\n * Roughly, any DatasetInstance (and not a raw Dataset).\n */\nvar DatasetListItemView = _super.extend(\n/** @lends DatasetListItemView.prototype */{\n _logNamespace: logNamespace,\n\n className: _super.prototype.className + \" dataset\",\n //TODO:?? doesn't exactly match an hda's type_id\n id: function id() {\n return [\"dataset\", this.model.get(\"id\")].join(\"-\");\n },\n\n /** Set up: instance vars, options, and event handlers */\n initialize: function initialize(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(this + \".initialize:\", attributes);\n _super.prototype.initialize.call(this, attributes);\n\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n },\n\n /** event listeners */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n var self = this;\n\n // re-rendering on any model changes\n return self.listenTo(self.model, {\n change: function change(model) {\n // if the model moved into the ready state and is expanded without details, fetch those details now\n if (self.model.changedAttributes().state && self.model.inReadyState() && self.expanded && !self.model.hasDetails()) {\n // normally, will render automatically (due to fetch -> change),\n // but! setting_metadata sometimes doesn't cause any other changes besides state\n // so, not rendering causes it to seem frozen in setting_metadata state\n self.model.fetch({ silent: true }).done(function () {\n self.render();\n });\n } else {\n if (_.has(model.changed, \"tags\") && _.keys(model.changed).length === 1) {\n // If only the tags have changed, rerender specifically\n // the titlebar region. Otherwise default to the full\n // render.\n self.$(\".nametags\").html(self._renderNametags());\n } else {\n self.render();\n }\n }\n }\n });\n },\n\n // ......................................................................... expandable\n /** In this override, only get details if in the ready state, get rerunnable if in other states.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function _fetchModelDetails() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... removal\n /** Remove this view's html from the DOM and remove all event listeners.\n * @param {Number or String} speed jq effect speed\n * @param {Function} callback an optional function called when removal is done (scoped to this view)\n */\n remove: function remove(speed, callback) {\n var view = this;\n speed = speed || this.fxSpeed;\n this.$el.fadeOut(speed, function () {\n Backbone.View.prototype.remove.call(view);\n if (callback) {\n callback.call(view);\n }\n });\n },\n\n // ......................................................................... rendering\n /* TODO:\n dataset states are the issue primarily making dataset rendering complex\n each state should have it's own way of displaying/set of details\n often with different actions that can be applied\n throw in deleted/purged/visible and things get complicated easily\n I've considered (a couple of times) - creating a view for each state\n - but recreating the view during an update...seems wrong\n */\n /** In this override, add the dataset state as a class for use with state-based CSS */\n _swapNewRender: function _swapNewRender($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n if (this.model.has(\"state\")) {\n this.$el.addClass(\"state-\" + this.model.get(\"state\"));\n }\n return this.$el;\n },\n\n // ................................................................................ titlebar\n /** In this override, add the dataset display button. */\n _renderPrimaryActions: function _renderPrimaryActions() {\n // render just the display for read-only\n return [this._renderDisplayButton()];\n },\n\n /** Render icon-button to display dataset data */\n _renderDisplayButton: function _renderDisplayButton() {\n // don't show display if not viewable or not accessible\n var state = this.model.get(\"state\");\n if (state === _states2.default.NOT_VIEWABLE || state === _states2.default.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n\n var displayBtnData = {\n target: this.linkTarget,\n classes: \"display-btn\"\n };\n\n // show a disabled display if the data's been purged\n if (this.model.get(\"purged\")) {\n displayBtnData.disabled = true;\n displayBtnData.title = (0, _localization2.default)(\"Cannot display datasets removed from disk\");\n\n // disable if still uploading\n } else if (state === _states2.default.UPLOAD) {\n displayBtnData.disabled = true;\n displayBtnData.title = (0, _localization2.default)(\"This dataset must finish uploading before it can be viewed\");\n\n // disable if still new\n } else if (state === _states2.default.NEW) {\n displayBtnData.disabled = true;\n displayBtnData.title = (0, _localization2.default)(\"This dataset is not yet viewable\");\n } else {\n displayBtnData.title = (0, _localization2.default)(\"View data\");\n\n // default link for dataset\n displayBtnData.href = this.model.urls.display;\n\n // add frame manager option onclick event\n var self = this;\n displayBtnData.onclick = function (ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n // Add dataset to frames.\n Galaxy.frame.addDataset(self.model.get(\"id\"));\n ev.preventDefault();\n }\n };\n }\n displayBtnData.faIcon = \"fa-eye\";\n return (0, _faIconButton2.default)(displayBtnData);\n },\n\n // ......................................................................... rendering details\n /** Render the enclosing div of the hda body and, if expanded, the html in the body\n * @returns {jQuery} rendered DOM\n */\n _renderDetails: function _renderDetails() {\n //TODO: generalize to be allow different details for each state\n\n // no access - render nothing but a message\n if (this.model.get(\"state\") === _states2.default.NOT_VIEWABLE) {\n return $(this.templates.noAccess(this.model.toJSON(), this));\n }\n\n var $details = _super.prototype._renderDetails.call(this);\n $details.find(\".actions .left\").empty().append(this._renderSecondaryActions());\n $details.find(\".summary\").html(this._renderSummary()).prepend(this._renderDetailMessages());\n $details.find(\".display-applications\").html(this._renderDisplayApplications());\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /** Defer to the appropo summary rendering fn based on state */\n _renderSummary: function _renderSummary() {\n var json = this.model.toJSON();\n var summaryRenderFn = this.templates.summaries[json.state];\n summaryRenderFn = summaryRenderFn || this.templates.summaries.unknown;\n return summaryRenderFn(json, this);\n },\n\n /** Render messages to be displayed only when the details are shown */\n _renderDetailMessages: function _renderDetailMessages() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.detailMessages, function (templateFn) {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the external display application links */\n _renderDisplayApplications: function _renderDisplayApplications() {\n if (this.model.isDeletedOrPurged()) {\n return \"\";\n }\n // render both old and new display apps using the same template\n return [this.templates.displayApplications(this.model.get(\"display_apps\"), this), this.templates.displayApplications(this.model.get(\"display_types\"), this)].join(\"\");\n },\n\n // ......................................................................... secondary/details actions\n /** A series of links/buttons for less commonly used actions: re-run, info, etc. */\n _renderSecondaryActions: function _renderSecondaryActions() {\n this.debug(\"_renderSecondaryActions\");\n switch (this.model.get(\"state\")) {\n case _states2.default.NOT_VIEWABLE:\n return [];\n case _states2.default.OK:\n case _states2.default.FAILED_METADATA:\n case _states2.default.ERROR:\n return [this._renderDownloadButton(), this._renderShowParamsButton()];\n }\n return [this._renderShowParamsButton()];\n },\n\n /** Render icon-button to show the input and output (stdout/err) for the job that created this.\n * @returns {jQuery} rendered DOM\n */\n _renderShowParamsButton: function _renderShowParamsButton() {\n // gen. safe to show in all cases\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"View details\"),\n classes: \"params-btn\",\n href: this.model.urls.show_params,\n target: this.linkTarget,\n faIcon: \"fa-info-circle\",\n onclick: function onclick(ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Dataset details\",\n url: this.href\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n }\n });\n },\n\n /** Render icon-button/popupmenu to download the data (and/or the associated meta files (bai, etc.)) for this.\n * @returns {jQuery} rendered DOM\n */\n _renderDownloadButton: function _renderDownloadButton() {\n // don't show anything if the data's been purged\n if (this.model.get(\"purged\") || !this.model.hasData()) {\n return null;\n }\n\n // return either: a popupmenu with links to download assoc. meta files (if there are meta files)\n // or a single download icon-button (if there are no meta files)\n if (!_.isEmpty(this.model.get(\"meta_files\"))) {\n return this._renderMetaFileDownloadButton();\n }\n\n return $(['\", '', \"\"].join(\"\"));\n },\n\n /** Render the download button which opens a dropdown with links to download assoc. meta files (indeces, etc.) */\n _renderMetaFileDownloadButton: function _renderMetaFileDownloadButton() {\n var urls = this.model.urls;\n return $(['
'], \"dataset\");\n\n // messages to be displayed only within the details section ('below the fold')\n var detailMessageTemplates = {\n resubmitted: _baseMvc2.default.wrapTemplate([\n // deleted not purged\n \"<% if( model.resubmitted ){ %>\", '
', (0, _localization2.default)(\"The job creating this dataset has been resubmitted\"), \"
\", \"<% } %>\"])\n };\n\n // this is applied to both old and new style display apps\n var displayApplicationsTemplate = _baseMvc2.default.wrapTemplate([\"<% _.each( apps, function( app ){ %>\", '
\"], \"collection\");\n\n return _.extend({}, FoldoutListItemView.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate\n });\n}();\n\n//==============================================================================\n/** @class Read only view for DatasetCollectionElement.\n */\nvar DCEListItemView = ListItemView.extend(\n/** @lends DCEListItemView.prototype */{\n /** add the DCE class to the list item */\n className: ListItemView.prototype.className + \" dataset-collection-element\",\n\n /** set up */\n initialize: function initialize(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DCEListItemView.initialize:\", attributes);\n ListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"DCEListItemView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDCEListItemView.prototype.templates = function () {\n // use the element identifier here - since that will persist and the user will need it\n var titleBarTemplate = _baseMvc2.default.wrapTemplate(['
', '
', '<%- element.element_identifier %>', \"
\", '', \"
\"], \"element\");\n\n return _.extend({}, ListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n}();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation\n * (a dataset contained in a dataset collection).\n */\nvar DatasetDCEListItemView = _datasetLi2.default.DatasetListItemView.extend(\n/** @lends DatasetDCEListItemView.prototype */{\n className: _datasetLi2.default.DatasetListItemView.prototype.className + \" dataset-collection-element\",\n\n /** set up */\n initialize: function initialize(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DatasetDCEListItemView.initialize:\", attributes);\n _datasetLi2.default.DatasetListItemView.prototype.initialize.call(this, attributes);\n },\n\n /** In this override, only get details if in the ready state.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function _fetchModelDetails() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"DatasetDCEListItemView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetDCEListItemView.prototype.templates = function () {\n // use the element identifier here and not the dataset name\n //TODO:?? can we steal the DCE titlebar?\n var titleBarTemplate = _baseMvc2.default.wrapTemplate(['
', '', '
', '<%- element.element_identifier %>', \"
\", \"
\"], \"element\");\n\n return _.extend({}, _datasetLi2.default.DatasetListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n}();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection\n * (a nested DC).\n */\nvar NestedDCDCEListItemView = DCListItemView.extend(\n/** @lends NestedDCDCEListItemView.prototype */{\n className: DCListItemView.prototype.className + \" dataset-collection-element\",\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function _swapNewRender($newRender) {\n DCListItemView.prototype._swapNewRender.call(this, $newRender);\n var state = this.model.get(\"state\") || \"ok\";\n this.$el.addClass(\"state-\" + state);\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"NestedDCDCEListItemView(\" + modelString + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n DCListItemView: DCListItemView,\n DCEListItemView: DCEListItemView,\n DatasetDCEListItemView: DatasetDCEListItemView,\n NestedDCDCEListItemView: NestedDCDCEListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 44 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Generic form view */\nvar View = Backbone.View.extend({\n initialize: function initialize(options) {\n this.model = new Backbone.Model(options);\n this.url = this.model.get(\"url\");\n this.redirect = this.model.get(\"redirect\");\n this.setElement(\"\");\n this.render();\n },\n\n render: function render() {\n var self = this;\n $.ajax({\n url: Galaxy.root + this.url,\n type: \"GET\"\n }).done(function (response) {\n var options = $.extend({}, self.model.attributes, response);\n var form = new _formView2.default({\n title: options.title,\n message: options.message,\n status: options.status || \"warning\",\n icon: options.icon,\n inputs: options.inputs,\n buttons: {\n submit: new _uiMisc2.default.Button({\n tooltip: options.submit_tooltip,\n title: options.submit_title || \"Save\",\n icon: options.submit_icon || \"fa-save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function onclick() {\n self._submit(form);\n }\n })\n }\n });\n self.$el.empty().append(form.$el);\n }).fail(function (response) {\n self.$el.empty().append(new _uiMisc2.default.Message({\n message: \"Failed to load resource \" + self.url + \".\",\n status: \"danger\",\n persistent: true\n }).$el);\n });\n },\n\n _submit: function _submit(form) {\n var self = this;\n $.ajax({\n url: Galaxy.root + self.url,\n data: JSON.stringify(form.data.create()),\n type: \"PUT\",\n contentType: \"application/json\"\n }).done(function (response) {\n var success_message = {\n message: response.message,\n status: \"success\",\n persistent: false\n };\n if (self.redirect) {\n window.location = Galaxy.root + self.redirect + \"?\" + $.param(success_message);\n } else {\n form.data.matchModel(response, function (input, input_id) {\n form.field_list[input_id].value(input.value);\n });\n self._showMessage(form, success_message);\n }\n }).fail(function (response) {\n self._showMessage(form, {\n message: response.responseJSON.err_msg,\n status: \"danger\",\n persistent: false\n });\n });\n },\n\n _showMessage: function _showMessage(form, options) {\n var $panel = form.$el.parents().filter(function () {\n return [\"auto\", \"scroll\"].indexOf($(this).css(\"overflow\")) != -1;\n }).first();\n $panel.animate({ scrollTop: 0 }, 500);\n form.message.update(options);\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 45 */,\n/* 46 */,\n/* 47 */,\n/* 48 */,\n/* 49 */,\n/* 50 */,\n/* 51 */,\n/* 52 */,\n/* 53 */,\n/* 54 */,\n/* 55 */,\n/* 56 */,\n/* 57 */,\n/* 58 */,\n/* 59 */,\n/* 60 */,\n/* 61 */,\n/* 62 */,\n/* 63 */,\n/* 64 */,\n/* 65 */,\n/* 66 */,\n/* 67 */,\n/* 68 */,\n/* 69 */,\n/* 70 */,\n/* 71 */,\n/* 72 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"dataset\";\n//==============================================================================\nvar searchableMixin = _baseMvc2.default.SearchableModelMixin;\n/** @class base model for any DatasetAssociation (HDAs, LDDAs, DatasetCollectionDAs).\n * No knowledge of what type (HDA/LDDA/DCDA) should be needed here.\n * The DA's are made searchable (by attribute) by mixing in SearchableModelMixin.\n */\nvar DatasetAssociation = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.mixin(searchableMixin,\n/** @lends DatasetAssociation.prototype */{\n _logNamespace: logNamespace,\n\n /** default attributes for a model */\n defaults: {\n state: _states2.default.NEW,\n deleted: false,\n purged: false,\n name: \"(unnamed dataset)\",\n accessible: true,\n // sniffed datatype (sam, tabular, bed, etc.)\n data_type: \"\",\n file_ext: \"\",\n file_size: 0,\n\n // array of associated file types (eg. [ 'bam_index', ... ])\n meta_files: [],\n\n misc_blurb: \"\",\n misc_info: \"\",\n\n tags: []\n // do NOT default on annotation, as this default is valid and will be passed on 'save'\n // which is incorrect behavior when the model is only partially fetched (annos are not passed in summary data)\n //annotation : ''\n },\n\n /** instance vars and listeners */\n initialize: function initialize(attributes, options) {\n this.debug(this + \"(Dataset).initialize\", attributes, options);\n\n //!! this state is not in trans.app.model.Dataset.states - set it here -\n if (!this.get(\"accessible\")) {\n this.set(\"state\", _states2.default.NOT_VIEWABLE);\n }\n\n /** Datasets rely/use some web controllers - have the model generate those URLs on startup */\n this.urls = this._generateUrls();\n\n this._setUpListeners();\n },\n\n /** returns misc. web urls for rendering things like re-run, display, etc. */\n _generateUrls: function _generateUrls() {\n var id = this.get(\"id\");\n if (!id) {\n return {};\n }\n var urls = {\n purge: \"datasets/\" + id + \"/purge_async\",\n display: \"datasets/\" + id + \"/display/?preview=True\",\n edit: \"datasets/edit?dataset_id=\" + id,\n download: \"datasets/\" + id + \"/display\" + this._downloadQueryParameters(),\n report_error: \"dataset/errors?id=\" + id,\n rerun: \"tool_runner/rerun?id=\" + id,\n show_params: \"datasets/\" + id + \"/show_params\",\n visualization: \"visualization\",\n meta_download: \"dataset/get_metadata_file?hda_id=\" + id + \"&metadata_name=\"\n };\n _.each(urls, function (value, key) {\n urls[key] = Galaxy.root + value;\n });\n this.urls = urls;\n return urls;\n },\n\n _downloadQueryParameters: function _downloadQueryParameters() {\n return \"?to_ext=\" + this.get(\"file_ext\");\n },\n\n /** set up any event listeners\n * event: state:ready fired when this DA moves into/is already in a ready state\n */\n _setUpListeners: function _setUpListeners() {\n // if the state has changed and the new state is a ready state, fire an event\n this.on(\"change:state\", function (currModel, newState) {\n this.log(this + \" has changed state:\", currModel, newState);\n if (this.inReadyState()) {\n this.trigger(\"state:ready\", currModel, newState, this.previous(\"state\"));\n }\n });\n // the download url (currently) relies on having a correct file extension\n this.on(\"change:id change:file_ext\", function (currModel) {\n this._generateUrls();\n });\n },\n\n // ........................................................................ common queries\n /** override to add urls */\n toJSON: function toJSON() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n //console.warn( 'returning json?' );\n //return json;\n return _.extend(json, {\n urls: this.urls\n });\n },\n\n /** Is this dataset deleted or purged? */\n isDeletedOrPurged: function isDeletedOrPurged() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n /** Is this dataset in a 'ready' state; where 'Ready' states are states where no\n * processing (for the ds) is left to do on the server.\n */\n inReadyState: function inReadyState() {\n var ready = _.contains(_states2.default.READY_STATES, this.get(\"state\"));\n return this.isDeletedOrPurged() || ready;\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function hasDetails() {\n // if it's inaccessible assume it has everything it needs\n if (!this.get(\"accessible\")) {\n return true;\n }\n return this.has(\"annotation\");\n },\n\n /** Convenience function to match dataset.has_data. */\n hasData: function hasData() {\n return this.get(\"file_size\") > 0;\n },\n\n // ........................................................................ ajax\n fetch: function fetch(options) {\n var dataset = this;\n return Backbone.Model.prototype.fetch.call(this, options).always(function () {\n dataset._generateUrls();\n });\n },\n\n /** override to use actual Dates objects for create/update times */\n parse: function parse(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** override to wait by default */\n save: function save(attrs, options) {\n options = options || {};\n options.wait = _.isUndefined(options.wait) ? true : options.wait;\n return Backbone.Model.prototype.save.call(this, attrs, options);\n },\n\n //NOTE: subclasses of DA's will need to implement url and urlRoot in order to have these work properly\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function _delete(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function undelete(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** remove the file behind this dataset from the filesystem (if permitted) */\n purge: function _purge(options) {\n //TODO: use, override model.destroy, HDA.delete({ purge: true })\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n options = options || {};\n options.url = this.urls.purge;\n\n //TODO: ideally this would be a DELETE call to the api\n // using purge async for now\n var hda = this;\n\n var xhr = jQuery.ajax(options);\n xhr.done(function (message, status, responseObj) {\n hda.set({ deleted: true, purged: true });\n });\n xhr.fail(function (xhr, status, message) {\n // Exception messages are hidden within error page including: '...not allowed in this Galaxy instance.'\n // unbury and re-add to xhr\n var error = (0, _localization2.default)(\"Unable to purge dataset\");\n var messageBuriedInUnfortunatelyFormattedError = \"Removal of datasets by users \" + \"is not allowed in this Galaxy instance\";\n if (xhr.responseJSON && xhr.responseJSON.error) {\n error = xhr.responseJSON.error;\n } else if (xhr.responseText.indexOf(messageBuriedInUnfortunatelyFormattedError) !== -1) {\n error = messageBuriedInUnfortunatelyFormattedError;\n }\n xhr.responseText = error;\n hda.trigger(\"error\", hda, xhr, options, (0, _localization2.default)(error), {\n error: error\n });\n });\n return xhr;\n },\n\n // ........................................................................ searching\n /** what attributes of an HDA will be used in a text search */\n searchAttributes: [\"name\", \"file_ext\", \"genome_build\", \"misc_blurb\", \"misc_info\", \"annotation\", \"tags\"],\n\n /** our attr keys don't often match the labels we display to the user - so, when using\n * attribute specifiers ('name=\"bler\"') in a term, allow passing in aliases for the\n * following attr keys.\n */\n searchAliases: {\n title: \"name\",\n format: \"file_ext\",\n database: \"genome_build\",\n blurb: \"misc_blurb\",\n description: \"misc_blurb\",\n info: \"misc_info\",\n tag: \"tags\"\n },\n\n // ........................................................................ misc\n /** String representation */\n toString: function toString() {\n var nameAndId = this.get(\"id\") || \"\";\n if (this.get(\"name\")) {\n nameAndId = \"\\\"\" + this.get(\"name\") + \"\\\",\" + nameAndId;\n }\n return \"Dataset(\" + nameAndId + \")\";\n }\n}));\n\n//==============================================================================\n/** @class Backbone collection for dataset associations.\n */\nvar DatasetAssociationCollection = Backbone.Collection.extend(_baseMvc2.default.LoggableMixin).extend(\n/** @lends HistoryContents.prototype */{\n _logNamespace: logNamespace,\n\n model: DatasetAssociation,\n\n /** root api url */\n urlRoot: Galaxy.root + \"api/datasets\",\n\n /** url fn */\n url: function url() {\n return this.urlRoot;\n },\n\n // ........................................................................ common queries\n /** Get the ids of every item in this collection\n * @returns array of encoded ids\n */\n ids: function ids() {\n return this.map(function (item) {\n return item.get(\"id\");\n });\n },\n\n /** Get contents that are not ready\n * @returns array of content models\n */\n notReady: function notReady() {\n return this.filter(function (content) {\n return !content.inReadyState();\n });\n },\n\n /** return true if any datasets don't have details */\n haveDetails: function haveDetails() {\n return this.all(function (dataset) {\n return dataset.hasDetails();\n });\n },\n\n // ........................................................................ ajax\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function ajaxQueue(ajaxFn, options) {\n var deferred = jQuery.Deferred();\n var startingLength = this.length;\n var responses = [];\n\n if (!startingLength) {\n deferred.resolve([]);\n return deferred;\n }\n\n // use reverse order (stylistic choice)\n var ajaxFns = this.chain().reverse().map(function (dataset, i) {\n return function () {\n var xhr = ajaxFn.call(dataset, options);\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(function (response) {\n deferred.notify({\n curr: i,\n total: startingLength,\n response: response,\n model: dataset\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(function (response) {\n responses.push(response);\n if (ajaxFns.length) {\n ajaxFns.shift()();\n } else {\n deferred.resolve(responses);\n }\n });\n };\n }).value();\n // start the queue\n ajaxFns.shift()();\n\n return deferred;\n },\n\n // ........................................................................ sorting/filtering\n /** return a new collection of datasets whose attributes contain the substring matchesWhat */\n matches: function matches(matchesWhat) {\n return this.filter(function (dataset) {\n return dataset.matches(matchesWhat);\n });\n },\n\n /** String representation. */\n toString: function toString() {\n return [\"DatasetAssociationCollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexports.default = {\n DatasetAssociation: DatasetAssociation,\n DatasetAssociationCollection: DatasetAssociationCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 73 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/** @class Mixin for HistoryContents content (HDAs, HDCAs).\n */\nvar HistoryContentMixin = {\n /** default attributes for a model */\n defaults: {\n /** parent (containing) history */\n history_id: null,\n /** some content_type (HistoryContents can contain mixed model classes) */\n history_content_type: null,\n /** indicating when/what order the content was generated in the context of the history */\n hid: null,\n /** whether the user wants the content shown (visible) */\n visible: true\n },\n\n // ........................................................................ mixed content element\n // In order to be part of a MIXED bbone collection, we can't rely on the id\n // (which may collide btwn models of different classes)\n // Instead, use type_id which prefixes the history_content_type so the bbone collection can differentiate\n idAttribute: \"type_id\",\n\n // ........................................................................ common queries\n /** the more common alias of visible */\n hidden: function hidden() {\n return !this.get(\"visible\");\n },\n\n //TODO: remove\n /** based on includeDeleted, includeHidden (gen. from the container control),\n * would this ds show in the list of ds's?\n * @param {Boolean} includeDeleted are we showing deleted hdas?\n * @param {Boolean} includeHidden are we showing hidden hdas?\n */\n isVisible: function isVisible(includeDeleted, includeHidden) {\n var isVisible = true;\n if (!includeDeleted && (this.get(\"deleted\") || this.get(\"purged\"))) {\n isVisible = false;\n }\n if (!includeHidden && !this.get(\"visible\")) {\n isVisible = false;\n }\n return isVisible;\n },\n\n // ........................................................................ ajax\n //TODO?: these are probably better done on the leaf classes\n /** history content goes through the 'api/histories' API */\n urlRoot: Galaxy.root + \"api/histories/\",\n\n /** full url spec. for this content */\n url: function url() {\n var historyContentType = this.get(\"history_content_type\");\n var historyId = this.get(\"history_id\");\n var historyContentId = this.get(\"id\");\n var url = this.urlRoot + \"{this.get(\\\"historyId\\\")}/contents/\" + historyContentType + \"s/\" + historyContentId;\n return url;\n },\n\n /** save this content as not visible */\n hide: function hide(options) {\n if (!this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: false }, options);\n },\n /** save this content as visible */\n unhide: function unhide(options) {\n if (this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: true }, options);\n },\n\n // ........................................................................ misc\n toString: function toString() {\n return [this.get(\"type_id\"), this.get(\"hid\"), this.get(\"name\")].join(\":\");\n }\n};\n\n//==============================================================================\nexports.default = {\n HistoryContentMixin: HistoryContentMixin\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n\n/***/ }),\n/* 74 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/* For presentation-related functionality shared across collection creators.\n Particularily overlapping functionality related to name processing and help.\n*/\nvar CollectionCreatorMixin = {\n /** add (or clear if clear is truthy) a validation warning to the DOM element described in what */\n _validationWarning: function _validationWarning(what, clear) {\n var VALIDATION_CLASS = \"validation-warning\";\n if (what === \"name\") {\n what = this.$(\".collection-name\").add(this.$(\".collection-name-prompt\"));\n this.$(\".collection-name\").focus().select();\n }\n if (clear) {\n what = what || this.$(\".\" + VALIDATION_CLASS);\n what.removeClass(VALIDATION_CLASS);\n } else {\n what.addClass(VALIDATION_CLASS);\n }\n },\n\n _changeHideOriginals: function _changeHideOriginals(ev) {\n this.hideOriginals = this.$(\".hide-originals\").prop(\"checked\");\n },\n\n // ........................................................................ footer\n /** handle a collection name change */\n _changeName: function _changeName(ev) {\n this._validationWarning(\"name\", !!this._getName());\n },\n\n /** check for enter key press when in the collection name and submit */\n _nameCheckForEnter: function _nameCheckForEnter(ev) {\n if (ev.keyCode === 13 && !this.blocking) {\n this._clickCreate();\n }\n },\n\n /** get the current collection name */\n _getName: function _getName() {\n return _.escape(this.$(\".collection-name\").val());\n },\n\n // ........................................................................ header\n /** expand help */\n _clickMoreHelp: function _clickMoreHelp(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").addClass(\"expanded\");\n this.$(\".more-help\").hide();\n },\n /** collapse help */\n _clickLessHelp: function _clickLessHelp(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").removeClass(\"expanded\");\n this.$(\".more-help\").show();\n },\n /** toggle help */\n _toggleHelp: function _toggleHelp(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").toggleClass(\"expanded\");\n this.$(\".more-help\").toggle();\n },\n\n /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */\n _showAlert: function _showAlert(message, alertClass) {\n alertClass = alertClass || \"alert-danger\";\n this.$(\".main-help\").hide();\n this.$(\".header .alert\").attr(\"class\", \"alert alert-dismissable\").addClass(alertClass).show().find(\".alert-message\").html(message);\n },\n /** hide the alerts at the top */\n _hideAlert: function _hideAlert(message) {\n this.$(\".main-help\").show();\n this.$(\".header .alert\").hide();\n },\n\n _cancelCreate: function _cancelCreate(ev) {\n if (typeof this.oncancel === \"function\") {\n this.oncancel.call(this);\n }\n },\n\n /** attempt to create the current collection */\n _clickCreate: function _clickCreate(ev) {\n var name = this._getName();\n if (!name) {\n this._validationWarning(\"name\");\n } else if (!this.blocking) {\n this.createList(name);\n }\n },\n\n _setUpCommonSettings: function _setUpCommonSettings(attributes) {\n this.hideOriginals = attributes.defaultHideSourceItems || false;\n },\n\n /** render the footer, completion controls, and cancel controls */\n _renderFooter: function _renderFooter(speed, callback) {\n var self = this;\n var $footer = this.$(\".footer\").empty().html(this.templates.footer());\n _.each(this.footerSettings, function (property, selector) {\n self.$(selector).prop(\"checked\", self[property]);\n });\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n return $footer;\n },\n\n _creatorTemplates: {\n main: _.template(['', '', ''].join(\"\"))\n }\n};\n\n//==============================================================================\nexports.default = {\n CollectionCreatorMixin: CollectionCreatorMixin\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 75 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n// Alphanumeric/natural sort fn\nfunction naturalSort(a, b) {\n // setup temp-scope variables for comparison evauluation\n var re = /(-?[0-9\\.]+)/g;\n\n var x = a.toString().toLowerCase() || \"\";\n var y = b.toString().toLowerCase() || \"\";\n var nC = String.fromCharCode(0);\n var xN = x.replace(re, nC + \"$1\" + nC).split(nC);\n var yN = y.replace(re, nC + \"$1\" + nC).split(nC);\n var xD = new Date(x).getTime();\n var yD = xD ? new Date(y).getTime() : null;\n // natural sorting of dates\n if (yD) {\n if (xD < yD) {\n return -1;\n } else if (xD > yD) {\n return 1;\n }\n }\n\n // natural sorting through split numeric strings and default strings\n var oFxNcL;\n\n var oFyNcL;\n for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {\n oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];\n oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];\n if (oFxNcL < oFyNcL) {\n return -1;\n } else if (oFxNcL > oFyNcL) {\n return 1;\n }\n }\n return 0;\n}\n\nexports.default = naturalSort;\n\n/***/ }),\n/* 76 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n\"use_strict\";\n\nvar $ = _jquery2.default;\n//=============================================================================\n\n_jquery2.default.fn.extend({\n hoverhighlight: function $hoverhighlight(scope, color) {\n scope = scope || \"body\";\n if (!this.length) {\n return this;\n }\n\n $(this).each(function () {\n var $this = $(this);\n var targetSelector = $this.data(\"target\");\n\n if (targetSelector) {\n $this.mouseover(function (ev) {\n $(targetSelector, scope).css({\n background: color\n });\n }).mouseout(function (ev) {\n $(targetSelector).css({\n background: \"\"\n });\n });\n }\n });\n return this;\n }\n});\n\n/***/ }),\n/* 77 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _deferred = __webpack_require__(67);\n\nvar _deferred2 = _interopRequireDefault(_deferred);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _formData = __webpack_require__(70);\n\nvar _formData2 = _interopRequireDefault(_formData);\n\nvar _toolFormBase = __webpack_require__(66);\n\nvar _toolFormBase2 = _interopRequireDefault(_toolFormBase);\n\nvar _uiModal = __webpack_require__(7);\n\nvar _uiModal2 = _interopRequireDefault(_uiModal);\n\nvar _webhooks = __webpack_require__(17);\n\nvar _webhooks2 = _interopRequireDefault(_webhooks);\n\nvar _workflowIcons = __webpack_require__(149);\n\nvar _workflowIcons2 = _interopRequireDefault(_workflowIcons);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar View = Backbone.View.extend({\n initialize: function initialize(options) {\n var self = this;\n this.modal = parent.Galaxy.modal || new _uiModal2.default.View();\n this.model = options && options.model || new Backbone.Model(options);\n this.deferred = new _deferred2.default();\n this.setElement($(\"\").addClass(\"ui-form-composite\").append(this.$message = $(\"\")).append(this.$header = $(\"\")).append(this.$steps = $(\"\")));\n $(\"body\").append(this.$el);\n this._configure();\n this.render();\n $(window).resize(function () {\n self._refresh();\n });\n },\n\n /** Refresh height of scrollable div below header, handle scrolling by lazy loading steps */\n _refresh: function _refresh(step_index) {\n var margin = _.reduce(this.$el.children(), function (memo, child) {\n return memo + $(child).outerHeight();\n }, 0) - this.$steps.height() + 90;\n this.$steps.css(\"height\", $(window).height() - margin);\n },\n\n /** Configures form/step options for each workflow step */\n _configure: function _configure() {\n var self = this;\n this.forms = [];\n this.steps = [];\n this.links = [];\n this.parms = [];\n _.each(this.model.get(\"steps\"), function (step, i) {\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", i + \" : Preparing workflow step.\");\n var icon = _workflowIcons2.default[step.step_type];\n var title = parseInt(i + 1) + \": \" + (step.step_label || step.step_name);\n if (step.annotation) {\n title += \" - \" + step.annotation;\n }\n if (step.step_version) {\n title += \" (Galaxy Version \" + step.step_version + \")\";\n }\n step = _utils2.default.merge({\n index: i,\n fixed_title: _.escape(title),\n icon: icon || \"\",\n help: null,\n citations: null,\n collapsible: true,\n collapsed: i > 0 && !self._isDataStep(step),\n sustain_version: true,\n sustain_repeats: true,\n sustain_conditionals: true,\n narrow: true,\n text_enable: \"Edit\",\n text_disable: \"Undo\",\n cls_enable: \"fa fa-edit\",\n cls_disable: \"fa fa-undo\",\n errors: step.messages,\n initial_errors: true,\n cls: \"ui-portlet-narrow\",\n hide_operations: true,\n needs_refresh: false,\n always_refresh: step.step_type != \"tool\"\n }, step);\n self.steps[i] = step;\n self.links[i] = [];\n self.parms[i] = {};\n });\n\n // build linear index of step input pairs\n _.each(this.steps, function (step, i) {\n _formData2.default.visitInputs(step.inputs, function (input, name) {\n self.parms[i][name] = input;\n });\n });\n\n // iterate through data input modules and collect linked sub steps\n _.each(this.steps, function (step, i) {\n _.each(step.output_connections, function (output_connection) {\n _.each(self.steps, function (sub_step, j) {\n sub_step.step_index === output_connection.input_step_index && self.links[i].push(sub_step);\n });\n });\n });\n\n // convert all connected data inputs to hidden fields with proper labels,\n // and track the linked source step\n _.each(this.steps, function (step, i) {\n _.each(self.steps, function (sub_step, j) {\n var connections_by_name = {};\n _.each(step.output_connections, function (connection) {\n sub_step.step_index === connection.input_step_index && (connections_by_name[connection.input_name] = connection);\n });\n _.each(self.parms[j], function (input, name) {\n var connection = connections_by_name[name];\n if (connection) {\n input.type = \"hidden\";\n input.help = input.step_linked ? input.help + \", \" : \"\";\n input.help += \"Output dataset '\" + connection.output_name + \"' from step \" + (parseInt(i) + 1);\n input.step_linked = input.step_linked || [];\n input.step_linked.push(step);\n }\n });\n });\n });\n\n // identify and configure workflow parameters\n var wp_count = 0;\n this.wp_inputs = {};\n function _handleWorkflowParameter(value, callback) {\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while (match = re.exec(String(value))) {\n var wp_name = match[1];\n callback(self.wp_inputs[wp_name] = self.wp_inputs[wp_name] || {\n label: wp_name,\n name: wp_name,\n type: \"text\",\n color: \"hsl( \" + ++wp_count * 100 + \", 70%, 30% )\",\n style: \"ui-form-wp-source\",\n links: []\n });\n }\n }\n _.each(this.steps, function (step, i) {\n _.each(self.parms[i], function (input, name) {\n _handleWorkflowParameter(input.value, function (wp_input) {\n wp_input.links.push(step);\n input.wp_linked = true;\n input.type = \"text\";\n input.backdrop = true;\n input.style = \"ui-form-wp-target\";\n });\n });\n _.each(step.post_job_actions, function (pja) {\n _.each(pja.action_arguments, function (arg) {\n _handleWorkflowParameter(arg, function () {});\n });\n });\n });\n\n // select fields are shown for dynamic fields if all putative data inputs are available,\n // or if an explicit reference is specified as data_ref and available\n _.each(this.steps, function (step, i) {\n if (step.step_type == \"tool\") {\n var data_resolved = true;\n _formData2.default.visitInputs(step.inputs, function (input, name, context) {\n var is_runtime_value = input.value && input.value.__class__ == \"RuntimeValue\";\n var is_data_input = [\"data\", \"data_collection\"].indexOf(input.type) != -1;\n var data_ref = context[input.data_ref];\n input.step_linked && !self._isDataStep(input.step_linked) && (data_resolved = false);\n input.options && (input.options.length == 0 && !data_resolved || input.wp_linked) && (input.is_workflow = true);\n data_ref && (input.is_workflow = data_ref.step_linked && !self._isDataStep(data_ref.step_linked) || input.wp_linked);\n (is_data_input || input.value && input.value.__class__ == \"RuntimeValue\" && !input.step_linked) && (step.collapsed = false);\n is_runtime_value && (input.value = input.default_value);\n input.flavor = \"workflow\";\n if (!is_runtime_value && !is_data_input && input.type !== \"hidden\" && !input.wp_linked) {\n if (input.optional || !_utils2.default.isEmpty(input.value) && input.value !== \"\") {\n input.collapsible_value = input.value;\n input.collapsible_preview = true;\n }\n }\n });\n }\n });\n },\n\n render: function render() {\n var self = this;\n this.deferred.reset();\n this._renderHeader();\n this._renderMessage();\n this._renderParameters();\n this._renderHistory();\n _.each(this.steps, function (step) {\n self._renderStep(step);\n });\n },\n\n /** Render header */\n _renderHeader: function _renderHeader() {\n var self = this;\n this.execute_btn = new _uiMisc2.default.Button({\n icon: \"fa-check\",\n title: \"Run workflow\",\n cls: \"btn btn-primary\",\n onclick: function onclick() {\n self._execute();\n }\n });\n this.$header.addClass(\"ui-form-header\").empty().append(new _uiMisc2.default.Label({\n title: \"Workflow: \" + this.model.get(\"name\")\n }).$el).append(this.execute_btn.$el);\n },\n\n /** Render message */\n _renderMessage: function _renderMessage() {\n this.$message.empty();\n if (this.model.get(\"has_upgrade_messages\")) {\n this.$message.append(new _uiMisc2.default.Message({\n message: \"Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el);\n }\n var step_version_changes = this.model.get(\"step_version_changes\");\n if (step_version_changes && step_version_changes.length > 0) {\n this.$message.append(new _uiMisc2.default.Message({\n message: \"Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el);\n }\n },\n\n /** Render workflow parameters */\n _renderParameters: function _renderParameters() {\n var self = this;\n this.wp_form = null;\n if (!_.isEmpty(this.wp_inputs)) {\n this.wp_form = new _formView2.default({\n title: \"Workflow Parameters\",\n inputs: this.wp_inputs,\n cls: \"ui-portlet-narrow\",\n onchange: function onchange() {\n _.each(self.wp_form.input_list, function (input_def, i) {\n _.each(input_def.links, function (step) {\n self._refreshStep(step);\n });\n });\n }\n });\n this._append(this.$steps.empty(), this.wp_form.$el);\n }\n },\n\n /** Render workflow parameters */\n _renderHistory: function _renderHistory() {\n this.history_form = new _formView2.default({\n cls: \"ui-portlet-narrow\",\n title: \"History Options\",\n inputs: [{\n type: \"conditional\",\n name: \"new_history\",\n test_param: {\n name: \"check\",\n label: \"Send results to a new history\",\n type: \"boolean\",\n value: \"false\",\n help: \"\"\n },\n cases: [{\n value: \"true\",\n inputs: [{\n name: \"name\",\n label: \"History name\",\n type: \"text\",\n value: this.model.get(\"name\")\n }]\n }]\n }]\n });\n this._append(this.$steps, this.history_form.$el);\n },\n\n /** Render step */\n _renderStep: function _renderStep(step) {\n var self = this;\n var form = null;\n this.deferred.execute(function (promise) {\n self.$steps.addClass(\"ui-steps\");\n if (step.step_type == \"tool\") {\n step.postchange = function (process, form) {\n var self = this;\n var current_state = {\n tool_id: step.id,\n tool_version: step.version,\n inputs: $.extend(true, {}, form.data.create())\n };\n form.wait(true);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Sending current state.\", current_state);\n _utils2.default.request({\n type: \"POST\",\n url: Galaxy.root + \"api/tools/\" + step.id + \"/build\",\n data: current_state,\n success: function success(data) {\n form.update(data);\n form.wait(false);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Received new model.\", data);\n process.resolve();\n },\n error: function error(response) {\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Refresh request failed.\", response);\n process.reject();\n }\n });\n };\n form = new _toolFormBase2.default(step);\n if (step.post_job_actions && step.post_job_actions.length) {\n form.portlet.append($(\"\").addClass(\"ui-form-element-disabled\").append($(\"\").addClass(\"ui-form-title\").html(\"Job Post Actions\")).append($(\"\").addClass(\"ui-form-preview\").html(_.reduce(step.post_job_actions, function (memo, value) {\n return memo + \" \" + value.short_str;\n }, \"\"))));\n }\n } else {\n var is_simple_input = [\"data_input\", \"data_collection_input\"].indexOf(step.step_type) != -1;\n _.each(step.inputs, function (input) {\n input.flavor = \"module\";\n input.hide_label = is_simple_input;\n });\n form = new _formView2.default(_utils2.default.merge({\n title: step.fixed_title,\n onchange: function onchange() {\n _.each(self.links[step.index], function (link) {\n self._refreshStep(link);\n });\n },\n inputs: step.inputs && step.inputs.length > 0 ? step.inputs : [{\n type: \"hidden\",\n name: \"No options available.\",\n ignore: null\n }]\n }, step));\n }\n self.forms[step.index] = form;\n self._append(self.$steps, form.$el);\n self._refresh();\n step.needs_refresh && self._refreshStep(step);\n form.portlet[!self.show_progress ? \"enable\" : \"disable\"]();\n self.show_progress && self.execute_btn.model.set({\n wait: true,\n wait_text: \"Preparing...\",\n percentage: (step.index + 1) * 100.0 / self.steps.length\n });\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", step.index + \" : Workflow step state ready.\", step);\n setTimeout(function () {\n promise.resolve();\n }, 0);\n });\n },\n\n /** Refreshes step values from source step values */\n _refreshStep: function _refreshStep(step) {\n var self = this;\n var form = this.forms[step.index];\n if (form) {\n _.each(self.parms[step.index], function (input, name) {\n if (input.step_linked || input.wp_linked) {\n var field = form.field_list[form.data.match(name)];\n if (field) {\n var new_value = undefined;\n if (input.step_linked) {\n new_value = { values: [] };\n _.each(input.step_linked, function (source_step) {\n if (self._isDataStep(source_step)) {\n var value = self.forms[source_step.index].data.create().input;\n value && _.each(value.values, function (v) {\n new_value.values.push(v);\n });\n }\n });\n if (!input.multiple && new_value.values.length > 0) {\n new_value = {\n values: [new_value.values[0]]\n };\n }\n } else if (input.wp_linked) {\n new_value = input.value;\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while (match = re.exec(input.value)) {\n var wp_field = self.wp_form.field_list[self.wp_form.data.match(match[1])];\n var wp_value = wp_field && wp_field.value();\n if (wp_value) {\n new_value = new_value.split(match[0]).join(wp_value);\n }\n }\n }\n if (new_value !== undefined) {\n field.value(new_value);\n }\n }\n }\n });\n form.trigger(\"change\");\n } else {\n step.needs_refresh = true;\n }\n },\n\n /** Refresh the history after job submission while form is shown */\n _refreshHistory: function _refreshHistory() {\n var self = this;\n var history = parent.Galaxy && parent.Galaxy.currHistoryPanel && parent.Galaxy.currHistoryPanel.model;\n this._refresh_history && clearTimeout(this._refresh_history);\n if (history) {\n history.refresh().success(function () {\n if (history.numOfUnfinishedShownContents() === 0) {\n self._refresh_history = setTimeout(function () {\n self._refreshHistory();\n }, history.UPDATE_DELAY);\n }\n });\n }\n },\n\n /** Build remaining steps */\n _execute: function _execute() {\n var self = this;\n this.show_progress = true;\n this._enabled(false);\n this.deferred.execute(function (promise) {\n setTimeout(function () {\n promise.resolve();\n self._submit();\n }, 0);\n });\n },\n\n /** Validate and submit workflow */\n _submit: function _submit() {\n var self = this;\n var history_form_data = this.history_form.data.create();\n var job_def = {\n new_history_name: history_form_data[\"new_history|name\"] ? history_form_data[\"new_history|name\"] : null,\n history_id: !history_form_data[\"new_history|name\"] ? this.model.get(\"history_id\") : null,\n replacement_params: this.wp_form ? this.wp_form.data.create() : {},\n parameters: {},\n // Tool form will submit flat maps for each parameter\n // (e.g. \"repeat_0|cond|param\": \"foo\" instead of nested\n // data structures).\n parameters_normalized: true,\n // Tool form always wants a list of invocations back\n // so that inputs can be batched.\n batch: true\n };\n var validated = true;\n for (var i in this.forms) {\n var form = this.forms[i];\n var job_inputs = form.data.create();\n var step = self.steps[i];\n var step_index = step.step_index;\n form.trigger(\"reset\");\n for (var job_input_id in job_inputs) {\n var input_value = job_inputs[job_input_id];\n var input_id = form.data.match(job_input_id);\n var input_field = form.field_list[input_id];\n var input_def = form.input_list[input_id];\n if (!input_def.step_linked) {\n if (this._isDataStep(step)) {\n validated = input_value && input_value.values && input_value.values.length > 0;\n } else {\n validated = input_def.optional || input_def.is_workflow && input_value !== \"\" || !input_def.is_workflow && input_value !== null;\n }\n if (!validated) {\n form.highlight(input_id);\n break;\n }\n job_def.parameters[step_index] = job_def.parameters[step_index] || {};\n job_def.parameters[step_index][job_input_id] = job_inputs[job_input_id];\n }\n }\n if (!validated) {\n break;\n }\n }\n if (!validated) {\n self._enabled(true);\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation failed.\", job_def);\n } else {\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation complete.\", job_def);\n _utils2.default.request({\n type: \"POST\",\n url: Galaxy.root + \"api/workflows/\" + this.model.id + \"/invocations\",\n data: job_def,\n success: function success(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission successful.\", response);\n self.$el.children().hide();\n self.$el.append(self._templateSuccess(response));\n\n // Show Webhook if job is running\n if ($.isArray(response) && response.length > 0) {\n self.$el.append($(\"\", { id: \"webhook-view\" }));\n var WebhookApp = new _webhooks2.default.WebhookView({\n urlRoot: Galaxy.root + \"api/webhooks/workflow\",\n toolId: job_def.tool_id,\n toolVersion: job_def.tool_version\n });\n }\n\n self._refreshHistory();\n },\n error: function error(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission failed.\", response);\n var input_found = false;\n if (response && response.err_data) {\n for (var i in self.forms) {\n var form = self.forms[i];\n var step_related_errors = response.err_data[form.model.get(\"step_index\")];\n if (step_related_errors) {\n var error_messages = form.data.matchResponse(step_related_errors);\n for (var input_id in error_messages) {\n form.highlight(input_id, error_messages[input_id]);\n input_found = true;\n break;\n }\n }\n }\n }\n if (!input_found) {\n self.modal.show({\n title: \"Workflow submission failed\",\n body: self._templateError(job_def, response && response.err_msg),\n buttons: {\n Close: function Close() {\n self.modal.hide();\n }\n }\n });\n }\n },\n complete: function complete() {\n self._enabled(true);\n }\n });\n }\n },\n\n /** Append new dom to body */\n _append: function _append($container, $el) {\n $container.append(\"\").append($el);\n },\n\n /** Set enabled/disabled state */\n _enabled: function _enabled(enabled) {\n this.execute_btn.model.set({\n wait: !enabled,\n wait_text: \"Sending...\",\n percentage: -1\n });\n this.wp_form && this.wp_form.portlet[enabled ? \"enable\" : \"disable\"]();\n this.history_form && this.history_form.portlet[enabled ? \"enable\" : \"disable\"]();\n _.each(this.forms, function (form) {\n form && form.portlet[enabled ? \"enable\" : \"disable\"]();\n });\n },\n\n /** Is data input module/step */\n _isDataStep: function _isDataStep(steps) {\n var lst = $.isArray(steps) ? steps : [steps];\n for (var i = 0; i < lst.length; i++) {\n var step = lst[i];\n if (!step || !step.step_type || !step.step_type.startsWith(\"data\")) {\n return false;\n }\n }\n return true;\n },\n\n /** Templates */\n _templateSuccess: function _templateSuccess(response) {\n if ($.isArray(response) && response.length > 0) {\n return $(\"\").addClass(\"donemessagelarge\").append($(\"\").html(\"Successfully invoked workflow \" + _utils2.default.sanitize(this.model.get(\"name\")) + \"\" + (response.length > 1 ? \" \" + response.length + \" times\" : \"\") + \".\")).append($(\"\").append(\"\").text(\"You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.\"));\n } else {\n return this._templateError(response, \"Invalid success response. No invocations found.\");\n }\n },\n\n _templateError: function _templateError(response, err_msg) {\n return $(\"\").addClass(\"errormessagelarge\").append($(\"\").text(\"The server could not complete the request. Please contact the Galaxy Team if this error persists. \" + (JSON.stringify(err_msg) || \"\"))).append($(\"\").text(JSON.stringify(response, null, 4)));\n }\n}); /** This is the run workflow tool form view. */\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 78 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, jQuery, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _uiModal = __webpack_require__(7);\n\nvar _uiModal2 = _interopRequireDefault(_uiModal);\n\nvar _errorModal = __webpack_require__(79);\n\nvar _errorModal2 = _interopRequireDefault(_errorModal);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\n/**\n * A dialog/modal that allows copying a user history or 'importing' from user\n * another. Generally called via historyCopyDialog below.\n * @type {Object}\n */\nvar CopyDialog = {\n // language related strings/fns\n defaultName: _.template(\"Copy of '<%- name %>'\"),\n title: _.template((0, _localization2.default)(\"Copying history\") + \" \\\"<%- name %>\\\"\"),\n submitLabel: (0, _localization2.default)(\"Copy\"),\n errorMessage: (0, _localization2.default)(\"History could not be copied.\"),\n progressive: (0, _localization2.default)(\"Copying history\"),\n activeLabel: (0, _localization2.default)(\"Copy only the active, non-deleted datasets\"),\n allLabel: (0, _localization2.default)(\"Copy all datasets including deleted ones\"),\n anonWarning: (0, _localization2.default)(\"As an anonymous user, unless you login or register, you will lose your current history \") + (0, _localization2.default)(\"after copying this history. \"),\n\n // template for modal body\n _template: _.template([\n //TODO: remove inline styles\n // show a warning message for losing current to anon users\n \"<% if( isAnon ){ %>\", '
\", \"<% } %>\", \"\"].join(\"\")),\n\n // empty modal body and let the user know the copy is happening\n _showAjaxIndicator: function _showAjaxIndicator() {\n var indicator = \"
\" + this.progressive + \"...
\";\n this.modal.$(\".modal-body\").empty().append(indicator).css({ \"margin-top\": \"8px\" });\n },\n\n // (sorta) public interface - display the modal, render the form, and potentially copy the history\n // returns a jQuery.Deferred done->history copied, fail->user cancelled\n dialog: function _dialog(modal, history, options) {\n options = options || {};\n\n var dialog = this;\n var deferred = jQuery.Deferred();\n\n var // TODO: getting a little byzantine here\n defaultCopyNameFn = options.nameFn || this.defaultName;\n\n var defaultCopyName = defaultCopyNameFn({\n name: history.get(\"name\")\n });\n\n var // TODO: these two might be simpler as one 3 state option (all,active,no-choice)\n defaultCopyWhat = options.allDatasets ? \"copy-all\" : \"copy-non-deleted\";\n\n var allowAll = !_.isUndefined(options.allowAll) ? options.allowAll : true;\n\n var autoClose = !_.isUndefined(options.autoClose) ? options.autoClose : true;\n\n this.modal = modal;\n\n // validate the name and copy if good\n function checkNameAndCopy() {\n var name = modal.$(\"#copy-modal-title\").val();\n if (!name) {\n modal.$(\".invalid-title\").show();\n return;\n }\n // get further settings, shut down and indicate the ajax call, then hide and resolve/reject\n var copyAllDatasets = modal.$('input[name=\"copy-what\"]:checked').val() === \"copy-all\";\n modal.$(\"button\").prop(\"disabled\", true);\n dialog._showAjaxIndicator();\n history.copy(true, name, copyAllDatasets).done(function (response) {\n deferred.resolve(response);\n }).fail(function (xhr, status, message) {\n var options = {\n name: name,\n copyAllDatasets: copyAllDatasets\n };\n _errorModal2.default.ajaxErrorModal(history, xhr, options, dialog.errorMessage);\n deferred.rejectWith(deferred, arguments);\n }).done(function () {\n if (autoClose) {\n modal.hide();\n }\n });\n }\n\n var originalClosingCallback = options.closing_callback;\n modal.show(_.extend(options, {\n title: this.title({ name: history.get(\"name\") }),\n body: $(dialog._template({\n name: defaultCopyName,\n isAnon: Galaxy.user.isAnonymous(),\n allowAll: allowAll,\n copyWhat: defaultCopyWhat,\n activeLabel: this.activeLabel,\n allLabel: this.allLabel,\n anonWarning: this.anonWarning\n })),\n buttons: _.object([[(0, _localization2.default)(\"Cancel\"), function () {\n modal.hide();\n }], [this.submitLabel, checkNameAndCopy]]),\n height: \"auto\",\n closing_events: true,\n closing_callback: function _historyCopyClose(cancelled) {\n if (cancelled) {\n deferred.reject({ cancelled: true });\n }\n if (originalClosingCallback) {\n originalClosingCallback(cancelled);\n }\n }\n }));\n\n // set the default dataset copy, autofocus the title, and set up for a simple return\n modal.$(\"#copy-modal-title\").focus().select();\n modal.$(\"#copy-modal-title\").on(\"keydown\", function (ev) {\n if (ev.keyCode === 13) {\n ev.preventDefault();\n checkNameAndCopy();\n }\n });\n\n return deferred;\n }\n};\n\n//==============================================================================\n// maintain the (slight) distinction between copy and import\n/**\n * Subclass CopyDialog to use the import language.\n */\nvar ImportDialog = _.extend({}, CopyDialog, {\n defaultName: _.template(\"imported: <%- name %>\"),\n title: _.template((0, _localization2.default)(\"Importing history\") + \" \\\"<%- name %>\\\"\"),\n submitLabel: (0, _localization2.default)(\"Import\"),\n errorMessage: (0, _localization2.default)(\"History could not be imported.\"),\n progressive: (0, _localization2.default)(\"Importing history\"),\n activeLabel: (0, _localization2.default)(\"Import only the active, non-deleted datasets\"),\n allLabel: (0, _localization2.default)(\"Import all datasets including deleted ones\"),\n anonWarning: (0, _localization2.default)(\"As an anonymous user, unless you login or register, you will lose your current history \") + (0, _localization2.default)(\"after importing this history. \")\n});\n\n//==============================================================================\n/**\n * Main interface for both history import and history copy dialogs.\n * @param {Backbone.Model} history the history to copy\n * @param {Object} options a hash\n * @return {jQuery.Deferred} promise that fails on close and succeeds on copy\n *\n * options:\n * (this object is also passed to the modal used to display the dialog and accepts modal options)\n * {Function} nameFn if defined, use this to build the default name shown to the user\n * (the fn is passed: {name: })\n * {bool} useImport if true, use the 'import' language (instead of Copy)\n * {bool} allowAll if true, allow the user to choose between copying all datasets and\n * only non-deleted datasets\n * {String} allDatasets default initial checked radio button: 'copy-all' or 'copy-non-deleted',\n */\nvar historyCopyDialog = function historyCopyDialog(history, options) {\n options = options || {};\n // create our own modal if Galaxy doesn't have one (mako tab without use_panels)\n var modal = window.parent.Galaxy.modal || new _uiModal2.default.View({});\n return options.useImport ? ImportDialog.dialog(modal, history, options) : CopyDialog.dialog(modal, history, options);\n};\n\n//==============================================================================\nexports.default = historyCopyDialog;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 79 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function($, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//TODO: toastr is another possibility - I didn't see where I might add details, tho\n\n/* ============================================================================\nError modals meant to replace the o-so-easy alerts.\n\nThese are currently styled as errormessages but use the Galaxy.modal\ninfrastructure to be shown/closed. They're capable of showing details in a\ntogglable dropdown and the details are formatted in a pre.\n\nExample:\n errorModal( 'Heres a message', 'A Title', { some_details: 'here' });\n errorModal( 'Heres a message' ); // no details, title is 'Error'\n\nThere are three specialized forms:\n offlineErrorModal a canned response for when there's no connection\n badGatewayErrorModal canned response for when Galaxy is restarting\n ajaxErrorModal plugable into any Backbone class as an\n error event handler by accepting the error args: model, xhr, options\n\nExamples:\n if( navigator.offLine ){ offlineErrorModal(); }\n if( xhr.status === 502 ){ badGatewayErrorModal(); }\n this.listenTo( this.model, 'error', ajaxErrorModal );\n\n============================================================================ */\n\nvar CONTACT_MSG = (0, _localization2.default)(\"Please contact a Galaxy administrator if the problem persists.\");\nvar DEFAULT_AJAX_ERR_MSG = (0, _localization2.default)(\"An error occurred while updating information with the server.\");\nvar DETAILS_MSG = (0, _localization2.default)(\"The following information can assist the developers in finding the source of the error:\");\n\n/** private helper that builds the modal and handles adding details */\nfunction _errorModal(message, title, details) {\n // create and return the modal, adding details button only if needed\n Galaxy.modal.show({\n title: title,\n body: message,\n closing_events: true,\n buttons: {\n Ok: function Ok() {\n Galaxy.modal.hide();\n }\n }\n });\n Galaxy.modal.$el.addClass(\"error-modal\");\n\n if (details) {\n Galaxy.modal.$(\".error-details\").add(Galaxy.modal.$('button:contains(\"Details\")')).remove();\n $(\"\").addClass(\"error-details\").hide().appendTo(Galaxy.modal.$(\".modal-content\")).append([$(\"\").text(DETAILS_MSG), $(\"\").text(JSON.stringify(details, null, \" \"))]);\n\n $(\"\").appendTo(Galaxy.modal.$(\".buttons\")).click(function () {\n Galaxy.modal.$(\".error-details\").toggle();\n });\n }\n return Galaxy.modal;\n}\n\n/** Display a modal showing an error message but fallback to alert if there's no modal */\nfunction errorModal(message, title, details) {\n if (!message) {\n return;\n }\n\n message = (0, _localization2.default)(message);\n title = (0, _localization2.default)(title) || (0, _localization2.default)(\"Error:\");\n if (window.Galaxy && Galaxy.modal) {\n return _errorModal(message, title, details);\n }\n\n alert(title + \"\\n\\n\" + message);\n console.log(\"error details:\", JSON.stringify(details));\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal when the user may be offline */\nfunction offlineErrorModal() {\n return errorModal((0, _localization2.default)(\"You appear to be offline. Please check your connection and try again.\"), (0, _localization2.default)(\"Offline?\"));\n}\n\n// ----------------------------------------------------------------------------\n/** 502 messages that should be displayed when galaxy is restarting */\nfunction badGatewayErrorModal() {\n return errorModal((0, _localization2.default)(\"Galaxy is currently unreachable. Please try again in a few minutes.\") + \" \" + CONTACT_MSG, (0, _localization2.default)(\"Cannot connect to Galaxy\"));\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal (with details) about a failed Backbone ajax operation */\nfunction ajaxErrorModal(model, xhr, options, message, title) {\n message = message || DEFAULT_AJAX_ERR_MSG;\n message += \" \" + CONTACT_MSG;\n title = title || (0, _localization2.default)(\"An error occurred\");\n var details = _ajaxDetails(model, xhr, options);\n return errorModal(message, title, details);\n}\n\n/** build details which may help debugging the ajax call */\nfunction _ajaxDetails(model, xhr, options) {\n return {\n //TODO: still can't manage Raven id\n raven: _.result(window.Raven, \"lastEventId\"),\n userAgent: navigator.userAgent,\n onLine: navigator.onLine,\n version: _.result(Galaxy.config, \"version_major\"),\n xhr: _.omit(xhr, _.functions(xhr)),\n options: _.omit(options, \"xhr\"),\n // add ajax data from Galaxy object cache\n url: _.result(Galaxy.lastAjax, \"url\"),\n data: _.result(Galaxy.lastAjax, \"data\"),\n // backbone stuff (auto-redacting email for user)\n model: _.result(model, \"toJSON\", \"\" + model),\n user: _.omit(_.result(Galaxy.user, \"toJSON\"), \"email\")\n };\n}\n\n//=============================================================================\nexports.default = {\n errorModal: errorModal,\n offlineErrorModal: offlineErrorModal,\n badGatewayErrorModal: badGatewayErrorModal,\n ajaxErrorModal: ajaxErrorModal\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 80 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _underscore = __webpack_require__(1);\n\nvar _ = _interopRequireWildcard(_underscore);\n\nvar _backbone = __webpack_require__(2);\n\nvar Backbone = _interopRequireWildcard(_backbone);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }\n\n//=============================================================================\n/**\n * A Collection that can be limited/offset/re-ordered/filtered.\n * @type {Backbone.Collection}\n */\nvar ControlledFetchCollection = Backbone.Collection.extend({\n /** call setOrder on initialization to build the comparator based on options */\n initialize: function initialize(models, options) {\n Backbone.Collection.prototype.initialize.call(this, models, options);\n this.setOrder(options.order || this.order, { silent: true });\n },\n\n /** set up to track order changes and re-sort when changed */\n _setUpListeners: function _setUpListeners() {\n return this.on({\n \"changed-order\": this.sort\n });\n },\n\n /** override to provide order and offsets based on instance vars, set limit if passed,\n * and set allFetched/fire 'all-fetched' when xhr returns\n */\n fetch: function fetch(options) {\n options = this._buildFetchOptions(options);\n Galaxy.debug(\"fetch options:\", options);\n return Backbone.Collection.prototype.fetch.call(this, options);\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function _buildFetchOptions(options) {\n // note: we normally want options passed in to override the defaults built here\n // so most of these fns will generate defaults\n options = _.clone(options) || {};\n var self = this;\n\n // jquery ajax option; allows multiple q/qv for filters (instead of 'q[]')\n options.traditional = true;\n\n // options.data\n // we keep limit, offset, etc. in options *as well as move it into data* because:\n // - it makes fetch calling convenient to add it to a single options map (instead of as mult. args)\n // - it allows the std. event handlers (for fetch, etc.) to have access\n // to the pagination options too\n // (i.e. this.on( 'sync', function( options ){ if( options.limit ){ ... } }))\n // however, when we send to xhr/jquery we copy them to data also so that they become API query params\n options.data = options.data || self._buildFetchData(options);\n Galaxy.debug(\"data:\", options.data);\n\n // options.data.filters --> options.data.q, options.data.qv\n var filters = this._buildFetchFilters(options);\n Galaxy.debug(\"filters:\", filters);\n if (!_.isEmpty(filters)) {\n _.extend(options.data, this._fetchFiltersToAjaxData(filters));\n }\n Galaxy.debug(\"data:\", options.data);\n return options;\n },\n\n /** Build the dictionary to send to fetch's XHR as data */\n _buildFetchData: function _buildFetchData(options) {\n var defaults = {};\n if (this.order) {\n defaults.order = this.order;\n }\n return _.defaults(_.pick(options, this._fetchParams), defaults);\n },\n\n /** These attribute keys are valid params to fetch/API-index */\n _fetchParams: [\n /** model dependent string to control the order of models returned */\n \"order\",\n /** limit the number of models returned from a fetch */\n \"limit\",\n /** skip this number of models when fetching */\n \"offset\",\n /** what series of attributes to return (model dependent) */\n \"view\",\n /** individual keys to return for the models (see api/histories.index) */\n \"keys\"],\n\n /** add any needed filters here based on collection state */\n _buildFetchFilters: function _buildFetchFilters(options) {\n // override\n return _.clone(options.filters || {});\n },\n\n /** Convert dictionary filters to qqv style arrays */\n _fetchFiltersToAjaxData: function _fetchFiltersToAjaxData(filters) {\n // return as a map so ajax.data can extend from it\n var filterMap = {\n q: [],\n qv: []\n };\n _.each(filters, function (v, k) {\n // don't send if filter value is empty\n if (v === undefined || v === \"\") {\n return;\n }\n // json to python\n if (v === true) {\n v = \"True\";\n }\n if (v === false) {\n v = \"False\";\n }\n if (v === null) {\n v = \"None\";\n }\n // map to k/v arrays (q/qv)\n filterMap.q.push(k);\n filterMap.qv.push(v);\n });\n return filterMap;\n },\n\n /** override to reset allFetched flag to false */\n reset: function reset(models, options) {\n this.allFetched = false;\n return Backbone.Collection.prototype.reset.call(this, models, options);\n },\n\n // ........................................................................ order\n order: null,\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: {\n update_time: _baseMvc2.default.buildComparator(\"update_time\", {\n ascending: false\n }),\n \"update_time-asc\": _baseMvc2.default.buildComparator(\"update_time\", {\n ascending: true\n }),\n create_time: _baseMvc2.default.buildComparator(\"create_time\", {\n ascending: false\n }),\n \"create_time-asc\": _baseMvc2.default.buildComparator(\"create_time\", {\n ascending: true\n })\n },\n\n /** set the order and comparator for this collection then sort with the new order\n * @event 'changed-order' passed the new order and the collection\n */\n setOrder: function setOrder(order, options) {\n options = options || {};\n var collection = this;\n var comparator = collection.comparators[order];\n if (_.isUndefined(comparator)) {\n throw new Error(\"unknown order: \" + order);\n }\n // if( _.isUndefined( comparator ) ){ return; }\n if (comparator === collection.comparator) {\n return;\n }\n\n collection.order = order;\n collection.comparator = comparator;\n\n if (!options.silent) {\n collection.trigger(\"changed-order\", options);\n }\n return collection;\n }\n});\n\n//=============================================================================\n/**\n *\n */\nvar PaginatedCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for each page's fetch */\n limitPerPage: 500,\n\n initialize: function initialize(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n this.currentPage = options.currentPage || 0;\n },\n\n getTotalItemCount: function getTotalItemCount() {\n return this.length;\n },\n\n shouldPaginate: function shouldPaginate() {\n return this.getTotalItemCount() >= this.limitPerPage;\n },\n\n getLastPage: function getLastPage() {\n return Math.floor(this.getTotalItemCount() / this.limitPerPage);\n },\n\n getPageCount: function getPageCount() {\n return this.getLastPage() + 1;\n },\n\n getPageLimitOffset: function getPageLimitOffset(pageNum) {\n pageNum = this.constrainPageNum(pageNum);\n return {\n limit: this.limitPerPage,\n offset: pageNum * this.limitPerPage\n };\n },\n\n constrainPageNum: function constrainPageNum(pageNum) {\n return Math.max(0, Math.min(pageNum, this.getLastPage()));\n },\n\n /** fetch the next page of data */\n fetchPage: function fetchPage(pageNum, options) {\n var self = this;\n pageNum = self.constrainPageNum(pageNum);\n self.currentPage = pageNum;\n options = _.defaults(options || {}, self.getPageLimitOffset(pageNum));\n\n self.trigger(\"fetching-more\");\n return self.fetch(options).always(function () {\n self.trigger(\"fetching-more-done\");\n });\n },\n\n fetchCurrentPage: function fetchCurrentPage(options) {\n return this.fetchPage(this.currentPage, options);\n },\n\n fetchPrevPage: function fetchPrevPage(options) {\n return this.fetchPage(this.currentPage - 1, options);\n },\n\n fetchNextPage: function fetchNextPage(options) {\n return this.fetchPage(this.currentPage + 1, options);\n }\n});\n\n//=============================================================================\n/**\n * A Collection that will load more elements without reseting.\n */\nvar InfinitelyScrollingCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: null,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 100,\n\n initialize: function initialize(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n /** @type {Integer} number of contents to return from the first fetch */\n this.limitOnFirstFetch = options.limitOnFirstFetch || this.limitOnFirstFetch;\n /** @type {Integer} limit for every fetch after the first */\n this.limitPerFetch = options.limitPerFetch || this.limitPerFetch;\n /** @type {Boolean} are all contents fetched? */\n this.allFetched = false;\n /** @type {Integer} what was the offset of the last content returned */\n this.lastFetched = options.lastFetched || 0;\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function _buildFetchOptions(options) {\n // options (options for backbone.fetch and jquery.ajax generally)\n // backbone option; false here to make fetching an addititive process\n options.remove = options.remove || false;\n return ControlledFetchCollection.prototype._buildFetchOptions.call(this, options);\n },\n\n /** fetch the first 'page' of data */\n fetchFirst: function fetchFirst(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchFirst:\", options);\n options = options ? _.clone(options) : {};\n this.allFetched = false;\n this.lastFetched = 0;\n return this.fetchMore(_.defaults(options, {\n reset: true,\n limit: this.limitOnFirstFetch\n }));\n },\n\n /** fetch the next page of data */\n fetchMore: function fetchMore(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchMore:\", options);\n options = _.clone(options || {});\n var collection = this;\n\n Galaxy.debug(\"fetchMore, options.reset:\", options.reset);\n if (!options.reset && collection.allFetched) {\n return jQuery.when();\n }\n\n // TODO: this fails in the edge case where\n // the first fetch offset === limit (limit 4, offset 4, collection.length 4)\n if (options.reset) {\n options.offset = 0;\n } else if (options.offset === undefined) {\n options.offset = collection.lastFetched;\n }\n var limit = options.limit = options.limit || collection.limitPerFetch || null;\n Galaxy.debug(\"fetchMore, limit:\", limit, \"offset:\", options.offset);\n\n collection.trigger(\"fetching-more\");\n return collection.fetch(options).always(function () {\n collection.trigger(\"fetching-more-done\");\n })\n // maintain allFetched flag and trigger if all were fetched this time\n .done(function _postFetchMore(fetchedData) {\n var numFetched = _.isArray(fetchedData) ? fetchedData.length : 0;\n collection.lastFetched += numFetched;\n Galaxy.debug(\"fetchMore, lastFetched:\", collection.lastFetched);\n // anything less than a full page means we got all there is to get\n if (!limit || numFetched < limit) {\n collection.allFetched = true;\n collection.trigger(\"all-fetched\", this);\n }\n });\n },\n\n /** fetch all the collection */\n fetchAll: function fetchAll(options) {\n // whitelist options to prevent allowing limit/offset/filters\n // (use vanilla fetch instead)\n options = options || {};\n var self = this;\n options = _.pick(options, \"silent\");\n options.filters = {};\n return self.fetch(options).done(function () {\n self.allFetched = true;\n self.trigger(\"all-fetched\", self);\n });\n }\n});\n\n//==============================================================================\nexports.default = {\n ControlledFetchCollection: ControlledFetchCollection,\n PaginatedCollection: PaginatedCollection,\n InfinitelyScrollingCollection: InfinitelyScrollingCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n\n/***/ }),\n/* 81 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _datasetModel = __webpack_require__(72);\n\nvar _datasetModel2 = _interopRequireDefault(_datasetModel);\n\nvar _historyContentModel = __webpack_require__(73);\n\nvar _historyContentModel2 = _interopRequireDefault(_historyContentModel);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _datasetModel2.default.DatasetAssociation;\n\nvar hcontentMixin = _historyContentModel2.default.HistoryContentMixin;\n/** @class (HDA) model for a Galaxy dataset contained in and related to a history.\n */\nvar HistoryDatasetAssociation = _super.extend(_baseMvc2.default.mixin(hcontentMixin,\n/** @lends HistoryDatasetAssociation.prototype */{\n /** default attributes for a model */\n defaults: _.extend({}, _super.prototype.defaults, hcontentMixin.defaults, {\n history_content_type: \"dataset\",\n model_class: \"HistoryDatasetAssociation\"\n })\n}));\n\n//==============================================================================\nexports.default = {\n HistoryDatasetAssociation: HistoryDatasetAssociation\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 82 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listItem = __webpack_require__(41);\n\nvar _listItem2 = _interopRequireDefault(_listItem);\n\nvar _loadingIndicator = __webpack_require__(156);\n\nvar _loadingIndicator2 = _interopRequireDefault(_loadingIndicator);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(83);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"list\";\n/* ============================================================================\nTODO:\n\n============================================================================ */\n/** @class View for a list/collection of models and the sub-views of those models.\n * Sub-views must (at least have the interface if not) inherit from ListItemView.\n * (For a list panel that also includes some 'container' model (History->HistoryContents)\n * use ModelWithListPanel)\n *\n * Allows for:\n * searching collection/sub-views\n * selecting/multi-selecting sub-views\n *\n * Currently used:\n * for dataset/dataset-choice\n * as superclass of ModelListPanel\n */\nvar ListPanel = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(\n/** @lends ListPanel.prototype */{\n _logNamespace: logNamespace,\n\n /** class to use for constructing the sub-views */\n viewClass: _listItem2.default.ListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: Backbone.Collection,\n\n tagName: \"div\",\n className: \"list-panel\",\n\n /** (in ms) that jquery effects will use */\n fxSpeed: \"fast\",\n\n /** string to display when the collection has no contents */\n emptyMsg: (0, _localization2.default)(\"This list is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: (0, _localization2.default)(\"No matching items found\"),\n /** string used for search placeholder */\n searchPlaceholder: (0, _localization2.default)(\"search\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the list\n */\n initialize: function initialize(attributes, options) {\n attributes = attributes || {};\n // set the logger if requested\n if (attributes.logger) {\n this.logger = attributes.logger;\n }\n this.log(this + \".initialize:\", attributes);\n\n // ---- instance vars\n /** how quickly should jquery fx run? */\n this.fxSpeed = _.has(attributes, \"fxSpeed\") ? attributes.fxSpeed : this.fxSpeed;\n\n /** filters for displaying subviews */\n this.filters = [];\n /** current search terms */\n this.searchFor = attributes.searchFor || \"\";\n\n /** loading indicator */\n // this.indicator = new LoadingIndicator( this.$el );\n\n /** currently showing selectors on items? */\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : true;\n //this.selecting = false;\n\n /** cached selected item.model.ids to persist btwn renders */\n this.selected = attributes.selected || [];\n /** the last selected item.model.id */\n this.lastSelected = null;\n\n /** are sub-views draggable */\n this.dragItems = attributes.dragItems || false;\n\n /** list item view class (when passed models) */\n this.viewClass = attributes.viewClass || this.viewClass;\n\n /** list item views */\n this.views = [];\n /** list item models */\n this.collection = attributes.collection || this._createDefaultCollection();\n\n /** filter fns run over collection items to see if they should show in the list */\n this.filters = attributes.filters || [];\n\n /** override $scrollContainer fn via attributes - fn should return jq for elem to call scrollTo on */\n this.$scrollContainer = attributes.$scrollContainer || this.$scrollContainer;\n\n /** @type {String} generic title */\n this.title = attributes.title || \"\";\n /** @type {String} generic subtitle */\n this.subtitle = attributes.subtitle || \"\";\n\n this._setUpListeners();\n },\n\n // ------------------------------------------------------------------------ listeners\n /** create any event listeners for the list */\n _setUpListeners: function _setUpListeners() {\n this.off();\n\n //TODO: move errorHandler down into list-view from history-view or\n // pass to global error handler (Galaxy)\n this.on({\n error: function error(model, xhr, options, msg, details) {\n //this.errorHandler( model, xhr, options, msg, details );\n console.error(model, xhr, options, msg, details);\n },\n // show hide the loading indicator\n loading: function loading() {\n this._showLoadingIndicator(\"loading...\", 40);\n },\n \"loading-done\": function loadingDone() {\n this._hideLoadingIndicator(40);\n }\n });\n\n // throw the first render up as a diff namespace using once (for outside consumption)\n this.once(\"rendered\", function () {\n this.trigger(\"rendered:initial\", this);\n });\n\n this._setUpCollectionListeners();\n this._setUpViewListeners();\n return this;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function _createDefaultCollection() {\n // override\n return new this.collectionClass([]);\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n this.log(this + \"._setUpCollectionListeners\", this.collection);\n this.stopListening(this.collection);\n\n // bubble up error events\n this.listenTo(this.collection, {\n error: function error(model, xhr, options, msg, details) {\n this.trigger(\"error\", model, xhr, options, msg, details);\n },\n update: function update(collection, options) {\n var changes = options.changes;\n // console.info( collection + ', update:', changes, '\\noptions:', options );\n // more than one: render everything\n if (options.renderAll || changes.added.length + changes.removed.length > 1) {\n return this.renderItems();\n }\n // otherwise, let the single add/remove handlers do it\n if (changes.added.length === 1) {\n return this.addItemView(_.first(changes.added), collection, options);\n }\n if (changes.removed.length === 1) {\n return this.removeItemView(_.first(changes.removed), collection, options);\n }\n }\n });\n return this;\n },\n\n /** listening for sub-view events that bubble up with the 'view:' prefix */\n _setUpViewListeners: function _setUpViewListeners() {\n this.log(this + \"._setUpViewListeners\");\n\n // shift to select a range\n this.on({\n \"view:selected\": function viewSelected(view, ev) {\n if (ev && ev.shiftKey && this.lastSelected) {\n var lastSelectedView = this.viewFromModelId(this.lastSelected);\n if (lastSelectedView) {\n this.selectRange(view, lastSelectedView);\n }\n } else if (ev && ev.altKey && !this.selecting) {\n this.showSelectors();\n }\n this.selected.push(view.model.id);\n this.lastSelected = view.model.id;\n },\n\n \"view:de-selected\": function viewDeSelected(view, ev) {\n this.selected = _.without(this.selected, view.model.id);\n }\n });\n },\n\n // ------------------------------------------------------------------------ rendering\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function render(speed) {\n this.log(this + \".render\", speed);\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _buildNewRender: function _buildNewRender() {\n this.debug(this + \"(ListPanel)._buildNewRender\");\n var $newRender = $(this.templates.el({}, this));\n this._renderControls($newRender);\n this._renderTitle($newRender);\n this._renderSubtitle($newRender);\n this._renderSearch($newRender);\n this.renderItems($newRender);\n return $newRender;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _renderControls: function _renderControls($newRender) {\n this.debug(this + \"(ListPanel)._renderControls\");\n var $controls = $(this.templates.controls({}, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n /** return a jQuery object containing the title DOM */\n _renderTitle: function _renderTitle($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** return a jQuery object containing the subtitle DOM (if any) */\n _renderSubtitle: function _renderSubtitle($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function _queueNewRender($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n $(panel).queue(\"fx\", [function (next) {\n panel.$el.fadeOut(speed, next);\n }, function (next) {\n panel._swapNewRender($newRender);\n next();\n }, function (next) {\n panel.$el.fadeIn(speed, next);\n }, function (next) {\n panel.trigger(\"rendered\", panel);\n next();\n }]);\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function _swapNewRender($newRender) {\n this.$el.empty().attr(\"class\", this.className).append($newRender.children());\n if (this.selecting) {\n this.showSelectors(0);\n }\n return this;\n },\n\n /** Set up any behaviors, handlers (ep. plugins) that need to be called when the entire view has been built but\n * not attached to the page yet.\n */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n this.$controls($where).find(\"[title]\").tooltip();\n // set up the pupup for actions available when multi selecting\n this._renderMultiselectActionMenu($where);\n return this;\n },\n\n /** render a menu containing the actions available to sets of selected items */\n _renderMultiselectActionMenu: function _renderMultiselectActionMenu($where) {\n $where = $where || this.$el;\n var $menu = $where.find(\".list-action-menu\");\n var actions = this.multiselectActions();\n if (!actions.length) {\n return $menu.empty();\n }\n\n var $newMenu = $(['
', '\", '
', \"
\", \"
\"].join(\"\"));\n var $actions = actions.map(function (action) {\n var html = ['
\"].join(\"\");\n return $(html).click(function (ev) {\n ev.preventDefault();\n return action.func(ev);\n });\n });\n $newMenu.find(\"ul\").append($actions);\n $menu.replaceWith($newMenu);\n return $newMenu;\n },\n\n /** return a list of plain objects used to render multiselect actions menu. Each object should have:\n * html: an html string used as the anchor contents\n * func: a function called when the anchor is clicked (passed the click event)\n */\n multiselectActions: function multiselectActions() {\n return [];\n },\n\n // ------------------------------------------------------------------------ sub-$element shortcuts\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function $scrollContainer($where) {\n // override or set via attributes.$scrollContainer\n return ($where || this.$el).parent().parent();\n },\n /** convenience selector for the section that displays the list controls */\n $controls: function $controls($where) {\n return ($where || this.$el).find(\"> .controls\");\n },\n /** list-items: where the subviews are contained in the view's dom */\n $list: function $list($where) {\n return ($where || this.$el).find(\"> .list-items\");\n },\n /** container where list messages are attached */\n $messages: function $messages($where) {\n //TODO: controls isn't really correct here (only for ModelListPanel)\n return ($where || this.$el).find(\"> .controls .messages\");\n },\n /** the message displayed when no views can be shown (no views, none matching search) */\n $emptyMessage: function $emptyMessage($where) {\n return ($where || this.$el).find(\"> .empty-message\");\n },\n\n // ------------------------------------------------------------------------ hda sub-views\n /** render the subviews for the list's collection */\n renderItems: function renderItems($whereTo) {\n $whereTo = $whereTo || this.$el;\n var panel = this;\n panel.log(this + \".renderItems\", $whereTo);\n\n var $list = panel.$list($whereTo);\n panel.freeViews();\n // console.log( 'views freed' );\n //TODO:? cache and re-use views?\n var shownModels = panel._filterCollection();\n // console.log( 'models filtered:', shownModels );\n\n panel.views = shownModels.map(function (itemModel) {\n var view = panel._createItemView(itemModel);\n return view;\n });\n\n $list.empty();\n // console.log( 'list emptied' );\n if (panel.views.length) {\n panel._attachItems($whereTo);\n // console.log( 'items attached' );\n }\n panel._renderEmptyMessage($whereTo).toggle(!panel.views.length);\n panel.trigger(\"views:ready\", panel.views);\n\n // console.log( '------------------------------------------- rendering items' );\n return panel.views;\n },\n\n /** Filter the collection to only those models that should be currently viewed */\n _filterCollection: function _filterCollection() {\n // override this\n var panel = this;\n return panel.collection.filter(_.bind(panel._filterItem, panel));\n },\n\n /** Should the model be viewable in the current state?\n * Checks against this.filters and this.searchFor\n */\n _filterItem: function _filterItem(model) {\n // override this\n var panel = this;\n return _.every(panel.filters.map(function (fn) {\n return fn.call(model);\n })) && (!panel.searchFor || model.matchesAll(panel.searchFor));\n },\n\n /** Create a view for a model and set up it's listeners */\n _createItemView: function _createItemView(model) {\n var ViewClass = this._getItemViewClass(model);\n var options = _.extend(this._getItemViewOptions(model), {\n model: model\n });\n var view = new ViewClass(options);\n this._setUpItemViewListeners(view);\n return view;\n },\n\n /** Free a view for a model. Note: does not remove it from the DOM */\n _destroyItemView: function _destroyItemView(view) {\n this.stopListening(view);\n this.views = _.without(this.views, view);\n },\n\n _destroyItemViews: function _destroyItemViews(view) {\n var self = this;\n self.views.forEach(function (v) {\n self.stopListening(v);\n });\n self.views = [];\n return self;\n },\n\n /** free any sub-views the list has */\n freeViews: function freeViews() {\n return this._destroyItemViews();\n },\n\n /** Get the bbone view class based on the model */\n _getItemViewClass: function _getItemViewClass(model) {\n // override this\n return this.viewClass;\n },\n\n /** Get the options passed to the new view based on the model */\n _getItemViewOptions: function _getItemViewOptions(model) {\n // override this\n return {\n //logger : this.logger,\n fxSpeed: this.fxSpeed,\n expanded: false,\n selectable: this.selecting,\n selected: _.contains(this.selected, model.id),\n draggable: this.dragItems\n };\n },\n\n /** Set up listeners for new models */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n // send all events to the panel, re-namspaceing them with the view prefix\n this.listenTo(view, \"all\", function () {\n var args = Array.prototype.slice.call(arguments, 0);\n args[0] = \"view:\" + args[0];\n panel.trigger.apply(panel, args);\n });\n\n // drag multiple - hijack ev.setData to add all selected items\n this.listenTo(view, \"draggable:dragstart\", function (ev, v) {\n //TODO: set multiple drag data here\n var json = {};\n\n var selected = this.getSelectedModels();\n if (selected.length) {\n json = selected.toJSON();\n } else {\n json = [v.model.toJSON()];\n }\n ev.dataTransfer.setData(\"text\", JSON.stringify(json));\n //ev.dataTransfer.setDragImage( v.el, 60, 60 );\n }, this);\n\n return panel;\n },\n\n /** Attach views in this.views to the model based on $whereTo */\n _attachItems: function _attachItems($whereTo) {\n var self = this;\n // console.log( '_attachItems:', $whereTo, this.$list( $whereTo ) );\n //ASSUMES: $list has been emptied\n this.$list($whereTo).append(this.views.map(function (view) {\n return self._renderItemView$el(view);\n }));\n return this;\n },\n\n /** get a given subview's $el (or whatever may wrap it) and return it */\n _renderItemView$el: function _renderItemView$el(view) {\n // useful to wrap and override\n return view.render(0).$el;\n },\n\n /** render the empty/none-found message */\n _renderEmptyMessage: function _renderEmptyMessage($whereTo) {\n this.debug(\"_renderEmptyMessage\", $whereTo, this.searchFor);\n var text = this.searchFor ? this.noneFoundMsg : this.emptyMsg;\n return this.$emptyMessage($whereTo).text(text);\n },\n\n /** expand all item views */\n expandAll: function expandAll() {\n _.each(this.views, function (view) {\n view.expand();\n });\n },\n\n /** collapse all item views */\n collapseAll: function collapseAll() {\n _.each(this.views, function (view) {\n view.collapse();\n });\n },\n\n // ------------------------------------------------------------------------ collection/views syncing\n /** Add a view (if the model should be viewable) to the panel */\n addItemView: function addItemView(model, collection, options) {\n // console.log( this + '.addItemView:', model );\n var panel = this;\n // get the index of the model in the list of filtered models shown by this list\n // in order to insert the view in the proper place\n //TODO:? potentially expensive\n var modelIndex = panel._filterCollection().indexOf(model);\n if (modelIndex === -1) {\n return undefined;\n }\n var view = panel._createItemView(model);\n // console.log( 'adding and rendering:', modelIndex, view.toString() );\n\n $(view).queue(\"fx\", [function (next) {\n // hide the empty message first if only view\n if (panel.$emptyMessage().is(\":visible\")) {\n panel.$emptyMessage().fadeOut(panel.fxSpeed, next);\n } else {\n next();\n }\n }, function (next) {\n panel._attachView(view, modelIndex);\n next();\n }]);\n return view;\n },\n\n /** internal fn to add view (to both panel.views and panel.$list) */\n _attachView: function _attachView(view, modelIndex, useFx) {\n // console.log( this + '._attachView:', view, modelIndex, useFx );\n useFx = _.isUndefined(useFx) ? true : useFx;\n modelIndex = modelIndex || 0;\n var panel = this;\n\n // use the modelIndex to splice into views and insert at the proper index in the DOM\n panel.views.splice(modelIndex, 0, view);\n panel._insertIntoListAt(modelIndex, panel._renderItemView$el(view).hide());\n\n panel.trigger(\"view:attached\", view);\n if (useFx) {\n view.$el.slideDown(panel.fxSpeed, function () {\n panel.trigger(\"view:attached:rendered\");\n });\n } else {\n view.$el.show();\n panel.trigger(\"view:attached:rendered\");\n }\n return view;\n },\n\n /** insert a jq object as a child of list-items at the specified *DOM index* */\n _insertIntoListAt: function _insertIntoListAt(index, $what) {\n // console.log( this + '._insertIntoListAt:', index, $what );\n var $list = this.$list();\n if (index === 0) {\n $list.prepend($what);\n } else {\n $list.children().eq(index - 1).after($what);\n }\n return $what;\n },\n\n /** Remove a view from the panel (if found) */\n removeItemView: function removeItemView(model, collection, options) {\n var panel = this;\n var view = _.find(panel.views, function (v) {\n return v.model === model;\n });\n if (!view) {\n return undefined;\n }\n panel.views = _.without(panel.views, view);\n panel.trigger(\"view:removed\", view);\n\n // potentially show the empty message if no views left\n // use anonymous queue here - since remove can happen multiple times\n $({}).queue(\"fx\", [function (next) {\n view.$el.fadeOut(panel.fxSpeed, next);\n }, function (next) {\n view.remove();\n panel.trigger(\"view:removed:rendered\");\n if (!panel.views.length) {\n panel._renderEmptyMessage().fadeIn(panel.fxSpeed, next);\n } else {\n next();\n }\n }]);\n return view;\n },\n\n /** get views based on model.id */\n viewFromModelId: function viewFromModelId(id) {\n return _.find(this.views, function (v) {\n return v.model.id === id;\n });\n },\n\n /** get views based on model */\n viewFromModel: function viewFromModel(model) {\n return model ? this.viewFromModelId(model.id) : undefined;\n },\n\n /** get views based on model properties */\n viewsWhereModel: function viewsWhereModel(properties) {\n return this.views.filter(function (view) {\n return _.isMatch(view.model.attributes, properties);\n });\n },\n\n /** A range of views between (and including) viewA and viewB */\n viewRange: function viewRange(viewA, viewB) {\n if (viewA === viewB) {\n return viewA ? [viewA] : [];\n }\n\n var indexA = this.views.indexOf(viewA);\n var indexB = this.views.indexOf(viewB);\n\n // handle not found\n if (indexA === -1 || indexB === -1) {\n if (indexA === indexB) {\n return [];\n }\n return indexA === -1 ? [viewB] : [viewA];\n }\n // reverse if indeces are\n //note: end inclusive\n return indexA < indexB ? this.views.slice(indexA, indexB + 1) : this.views.slice(indexB, indexA + 1);\n },\n\n // ------------------------------------------------------------------------ searching\n /** render a search input for filtering datasets shown\n * (see SearchableMixin in base-mvc for implementation of the actual searching)\n * return will start the search\n * esc will clear the search\n * clicking the clear button will clear the search\n * uses searchInput in ui.js\n */\n _renderSearch: function _renderSearch($where) {\n $where.find(\".controls .search-input\").searchInput({\n placeholder: this.searchPlaceholder,\n initialVal: this.searchFor,\n onfirstsearch: _.bind(this._firstSearch, this),\n onsearch: _.bind(this.searchItems, this),\n onclear: _.bind(this.clearSearch, this)\n });\n return $where;\n },\n\n /** What to do on the first search entered */\n _firstSearch: function _firstSearch(searchFor) {\n // override to load model details if necc.\n this.log(\"onFirstSearch\", searchFor);\n return this.searchItems(searchFor);\n },\n\n /** filter view list to those that contain the searchFor terms */\n searchItems: function searchItems(searchFor, force) {\n this.log(\"searchItems\", searchFor, this.searchFor, force);\n if (!force && this.searchFor === searchFor) {\n return this;\n }\n this.searchFor = searchFor;\n this.renderItems();\n this.trigger(\"search:searching\", searchFor, this);\n var $search = this.$(\"> .controls .search-query\");\n if ($search.val() !== searchFor) {\n $search.val(searchFor);\n }\n return this;\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function clearSearch(searchFor) {\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n this.renderItems();\n return this;\n },\n\n // ------------------------------------------------------------------------ selection\n /** @type Integer when the number of list item views is >= to this, don't animate selectors */\n THROTTLE_SELECTOR_FX_AT: 20,\n\n /** show selectors on all visible itemViews and associated controls */\n showSelectors: function showSelectors(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = true;\n this.$(\".list-actions\").slideDown(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, function (view) {\n view.showSelector(speed);\n });\n //this.selected = [];\n //this.lastSelected = null;\n },\n\n /** hide selectors on all visible itemViews and associated controls */\n hideSelectors: function hideSelectors(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = false;\n this.$(\".list-actions\").slideUp(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, function (view) {\n view.hideSelector(speed);\n });\n this.selected = [];\n this.lastSelected = null;\n },\n\n /** show or hide selectors on all visible itemViews and associated controls */\n toggleSelectors: function toggleSelectors() {\n if (!this.selecting) {\n this.showSelectors();\n } else {\n this.hideSelectors();\n }\n },\n\n /** select all visible items */\n selectAll: function selectAll(event) {\n _.each(this.views, function (view) {\n view.select(event);\n });\n },\n\n /** deselect all visible items */\n deselectAll: function deselectAll(event) {\n this.lastSelected = null;\n _.each(this.views, function (view) {\n view.deselect(event);\n });\n },\n\n /** select a range of datasets between A and B */\n selectRange: function selectRange(viewA, viewB) {\n var range = this.viewRange(viewA, viewB);\n _.each(range, function (view) {\n view.select();\n });\n return range;\n },\n\n /** return an array of all currently selected itemViews */\n getSelectedViews: function getSelectedViews() {\n return _.filter(this.views, function (v) {\n return v.selected;\n });\n },\n\n /** return a collection of the models of all currenly selected items */\n getSelectedModels: function getSelectedModels() {\n // console.log( '(getSelectedModels)' );\n return new this.collection.constructor(_.map(this.getSelectedViews(), function (view) {\n return view.model;\n }));\n },\n\n // ------------------------------------------------------------------------ loading indicator\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function _showLoadingIndicator(msg, speed, callback) {\n this.debug(\"_showLoadingIndicator\", this.indicator, msg, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (!this.indicator) {\n this.indicator = new _loadingIndicator2.default(this.$el);\n this.debug(\"\\t created\", this.indicator);\n }\n if (!this.$el.is(\":visible\")) {\n this.indicator.show(0, callback);\n } else {\n this.$el.fadeOut(speed);\n this.indicator.show(msg, speed, callback);\n }\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function _hideLoadingIndicator(speed, callback) {\n this.debug(\"_hideLoadingIndicator\", this.indicator, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (this.indicator) {\n this.indicator.hide(speed, callback);\n }\n },\n\n // ------------------------------------------------------------------------ scrolling\n /** get the current scroll position of the panel in its parent */\n scrollPosition: function scrollPosition() {\n return this.$scrollContainer().scrollTop();\n },\n\n /** set the current scroll position of the panel in its parent */\n scrollTo: function scrollTo(pos, speed) {\n speed = speed || 0;\n this.$scrollContainer().animate({ scrollTop: pos }, speed);\n return this;\n },\n\n /** Scrolls the panel to the top. */\n scrollToTop: function scrollToTop(speed) {\n return this.scrollTo(0, speed);\n },\n\n /** scroll to the given view in list-items */\n scrollToItem: function scrollToItem(view, speed) {\n if (!view) {\n return this;\n }\n return this;\n },\n\n /** Scrolls the panel to show the content with the given id. */\n scrollToId: function scrollToId(id, speed) {\n return this.scrollToItem(this.viewFromModelId(id), speed);\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .select-all\": \"selectAll\",\n \"click .deselect-all\": \"deselectAll\"\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function toString() {\n return \"ListPanel(\" + this.collection + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListPanel.prototype.templates = function () {\n var elTemplate = _baseMvc2.default.wrapTemplate([\n // temp container\n \"
\", '', '', '', \"
\"]);\n\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
\"]);\n\n return {\n el: elTemplate,\n controls: controlsTemplate\n };\n}();\n\n//=============================================================================\n/** View for a model that has a sub-collection (e.g. History, DatasetCollection)\n * Allows:\n * the model to be reset\n * auto assign panel.collection to panel.model[ panel.modelCollectionKey ]\n *\n */\nvar ModelListPanel = ListPanel.extend({\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n initialize: function initialize(attributes) {\n ListPanel.prototype.initialize.call(this, attributes);\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : false;\n\n this.setModel(this.model, attributes);\n },\n\n /** release/free/shutdown old models and set up panel for new models\n * @fires new-model with the panel as parameter\n */\n setModel: function setModel(model, attributes) {\n attributes = attributes || {};\n this.debug(this + \".setModel:\", model, attributes);\n\n this.freeModel();\n this.freeViews();\n\n if (model) {\n var oldModelId = this.model ? this.model.get(\"id\") : null;\n\n // set up the new model with user, logger, storage, events\n this.model = model;\n if (this.logger) {\n this.model.logger = this.logger;\n }\n this._setUpModelListeners();\n\n //TODO: relation btwn model, collection becoming tangled here\n // free the collection, and assign the new collection to either\n // the model[ modelCollectionKey ], attributes.collection, or an empty vanilla collection\n this.stopListening(this.collection);\n this.collection = this.model[this.modelCollectionKey] || attributes.collection || this._createDefaultCollection();\n this._setUpCollectionListeners();\n\n if (oldModelId && model.get(\"id\") !== oldModelId) {\n this.trigger(\"new-model\", this);\n }\n }\n return this;\n },\n\n /** free the current model and all listeners for it, free any views for the model */\n freeModel: function freeModel() {\n // stop/release the previous model, and clear cache to sub-views\n if (this.model) {\n this.stopListening(this.model);\n //TODO: see base-mvc\n //this.model.free();\n //this.model = null;\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ listening\n /** listening for model events */\n _setUpModelListeners: function _setUpModelListeners() {\n // override\n this.log(this + \"._setUpModelListeners\", this.model);\n // bounce model errors up to the panel\n this.listenTo(this.model, \"error\", function () {\n var args = Array.prototype.slice.call(arguments, 0);\n //args.unshift( 'model:error' );\n args.unshift(\"error\");\n this.trigger.apply(this, args);\n }, this);\n\n // debugging\n if (this.logger) {\n this.listenTo(this.model, \"all\", function (event) {\n this.info(this + \"(model)\", event, arguments);\n });\n }\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n */\n _renderControls: function _renderControls($newRender) {\n this.debug(this + \"(ModelListPanel)._renderControls\");\n var json = this.model ? this.model.toJSON() : {};\n var $controls = $(this.templates.controls(json, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function toString() {\n return \"ModelListPanel(\" + this.model + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nModelListPanel.prototype.templates = function () {\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
', '
',\n //TODO: this is really the only difference - consider factoring titlebar out\n '
<%- model.name %>
', \"
\", '
<%- view.subtitle %>
', '', '', '
', '', \"
\", '
', '
', '\", '\", \"
\", '
', \"
\", \"
\", \"
\"]);\n\n return _.extend(_.clone(ListPanel.prototype.templates), {\n controls: controlsTemplate\n });\n}();\n\n//=============================================================================\nexports.default = {\n ListPanel: ListPanel,\n ModelListPanel: ModelListPanel\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 83 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n\"use_strict\";\n\nvar $ = _jquery2.default;\nvar _l = window._l || function (s) {\n return s;\n};\n\n//TODO: consolidate with tool menu functionality, use there\n\n/** searchInput: (jQuery plugin)\n * Creates a search input, a clear button, and loading indicator\n * within the selected node.\n *\n * When the user either presses return or enters some minimal number\n * of characters, a callback is called. Pressing ESC when the input\n * is focused will clear the input and call a separate callback.\n */\nfunction searchInput(parentNode, options) {\n var KEYCODE_ESC = 27;\n var KEYCODE_RETURN = 13;\n var $parentNode = $(parentNode);\n var firstSearch = true;\n\n var defaults = {\n initialVal: \"\",\n name: \"search\",\n placeholder: \"search\",\n classes: \"\",\n onclear: function onclear() {},\n onfirstsearch: null,\n onsearch: function onsearch(inputVal) {},\n minSearchLen: 0,\n escWillClear: true,\n oninit: function oninit() {}\n };\n\n // .................................................................... input rendering and events\n // visually clear the search, trigger an event, and call the callback\n function clearSearchInput(event) {\n var $input = $(this).parent().children(\"input\");\n $input.val(\"\").trigger(\"searchInput.clear\").blur();\n options.onclear();\n }\n\n // search for searchTerms, trigger an event, call the appropo callback (based on whether this is the first)\n function search(event, searchTerms) {\n if (!searchTerms) {\n return clearSearchInput();\n }\n $(this).trigger(\"search.search\", searchTerms);\n if (typeof options.onfirstsearch === \"function\" && firstSearch) {\n firstSearch = false;\n options.onfirstsearch(searchTerms);\n } else {\n options.onsearch(searchTerms);\n }\n }\n\n // .................................................................... input rendering and events\n function inputTemplate() {\n // class search-query is bootstrap 2.3 style that now lives in base.less\n return ['\"].join(\"\");\n }\n\n // the search input that responds to keyboard events and displays the search value\n function $input() {\n return $(inputTemplate())\n // select all text on a focus\n .focus(function (event) {\n $(this).select();\n })\n // attach behaviors to esc, return if desired, search on some min len string\n .keyup(function (event) {\n event.preventDefault();\n event.stopPropagation();\n\n // esc key will clear if desired\n if (event.which === KEYCODE_ESC && options.escWillClear) {\n clearSearchInput.call(this, event);\n } else {\n var searchTerms = $(this).val();\n // return key or the search string len > minSearchLen (if not 0) triggers search\n if (event.which === KEYCODE_RETURN || options.minSearchLen && searchTerms.length >= options.minSearchLen) {\n search.call(this, event, searchTerms);\n }\n }\n }).val(options.initialVal);\n }\n\n // .................................................................... clear button rendering and events\n // a button for clearing the search bar, placed on the right hand side\n function $clearBtn() {\n return $([''].join(\"\")).tooltip({ placement: \"bottom\" }).click(function (event) {\n clearSearchInput.call(this, event);\n });\n }\n\n // .................................................................... loadingIndicator rendering\n // a button for clearing the search bar, placed on the right hand side\n function $loadingIndicator() {\n return $([''].join(\"\")).hide().tooltip({ placement: \"bottom\" });\n }\n\n // .................................................................... commands\n // visually swap the load, clear buttons\n function toggleLoadingIndicator() {\n $parentNode.find(\".search-loading\").toggle();\n $parentNode.find(\".search-clear\").toggle();\n }\n\n // .................................................................... init\n // string command (not constructor)\n if (_jquery2.default.type(options) === \"string\") {\n if (options === \"toggle-loading\") {\n toggleLoadingIndicator();\n }\n return $parentNode;\n }\n\n // initial render\n if (_jquery2.default.type(options) === \"object\") {\n options = _jquery2.default.extend(true, {}, defaults, options);\n }\n //NOTE: prepended\n return $parentNode.addClass(\"search-input\").prepend([$input(), $clearBtn(), $loadingIndicator()]);\n}\n\n// as jq plugin\n_jquery2.default.fn.extend({\n searchInput: function $searchInput(options) {\n return this.each(function () {\n return searchInput(this, options);\n });\n }\n});\n\n/***/ }),\n/* 84 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _datasetLi = __webpack_require__(42);\n\nvar _datasetLi2 = _interopRequireDefault(_datasetLi);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _historyItemLi = __webpack_require__(85);\n\nvar _historyItemLi2 = _interopRequireDefault(_historyItemLi);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _datasetLi2.default.DatasetListItemView;\n/** @class Read only view for HistoryDatasetAssociation.\n * Since there are no controls on the HDAView to hide the dataset,\n * the primary thing this class does (currently) is override templates\n * to render the HID.\n */\nvar HDAListItemView = _super.extend(\n/** @lends HDAListItemView.prototype */{\n className: _super.prototype.className + \" history-content\",\n\n initialize: function initialize(attributes, options) {\n _super.prototype.initialize.call(this, attributes, options);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"HDAListItemView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nHDAListItemView.prototype.templates = function () {\n var titleBarTemplate = function titleBarTemplate(dataset) {\n return \"\\n
\\n \";\n };\n\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: _baseMvc2.default.wrapTemplate([\n // add a warning when hidden\n \"<% if( !dataset.visible ){ %>\", '
', (0, _localization2.default)(\"This dataset has been hidden\"), \"
\", \"<% } %>\"], \"dataset\")\n });\n\n return _.extend({}, _super.prototype.templates, {\n titleBar: titleBarTemplate,\n warnings: warnings\n });\n}();\n\n//==============================================================================\nexports.default = {\n HDAListItemView: HDAListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 85 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nfunction _labelIfName(tag) {\n if (tag.indexOf(\"name:\") == 0) {\n return \"\" + _.escape(tag.slice(5)) + \"\";\n } else {\n return \"\";\n }\n}\n\nfunction nametagTemplate(historyItem) {\n return \"\" + _.sortBy(_.uniq(historyItem.tags)).map(_labelIfName).join(\"\") + \"\";\n}\n\nexports.default = {\n nametagTemplate: nametagTemplate\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 86 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _collectionLi = __webpack_require__(43);\n\nvar _collectionLi2 = _interopRequireDefault(_collectionLi);\n\nvar _collectionView = __webpack_require__(87);\n\nvar _collectionView2 = _interopRequireDefault(_collectionView);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _historyItemLi = __webpack_require__(85);\n\nvar _historyItemLi2 = _interopRequireDefault(_historyItemLi);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _collectionLi2.default.DCListItemView;\n/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).\n */\nvar HDCAListItemView = _super.extend(\n/** @lends HDCAListItemView.prototype */{\n className: _super.prototype.className + \" history-content\",\n\n /** event listeners */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n this.listenTo(this.model, {\n \"change:tags change:populated change:visible\": function changeTagsChangePopulatedChangeVisible(model, options) {\n this.render();\n }\n });\n },\n\n /** Override to provide the proper collections panels as the foldout */\n _getFoldoutPanelClass: function _getFoldoutPanelClass() {\n var collectionType = this.model.get(\"collection_type\");\n switch (collectionType) {\n case \"list\":\n return _collectionView2.default.ListCollectionView;\n case \"paired\":\n return _collectionView2.default.PairCollectionView;\n case \"list:paired\":\n return _collectionView2.default.ListOfPairsCollectionView;\n case \"list:list\":\n return _collectionView2.default.ListOfListsCollectionView;\n }\n throw new TypeError(\"Unknown collection_type: \" + collectionType);\n },\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function _swapNewRender($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n //TODO: model currently has no state\n var state = !this.model.get(\"populated\") ? _states2.default.RUNNING : _states2.default.OK;\n //if( this.model.has( 'state' ) ){\n this.$el.addClass(\"state-\" + state);\n //}\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"HDCAListItemView(\" + modelString + \")\";\n }\n});\n\n/** underscore templates */\nHDCAListItemView.prototype.templates = function () {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n hidden: function hidden(collection) {\n collection.visible ? \"\" : \"
\" + (0, _localization2.default)(\"This collection has been hidden\") + \"
\";\n }\n });\n\n // could steal this from hda-base (or use mixed content)\n var titleBarTemplate = function titleBarTemplate(collection) {\n return \"\\n
\\n \";\n };\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n HDCAListItemView: HDCAListItemView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 87 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listView = __webpack_require__(82);\n\nvar _listView2 = _interopRequireDefault(_listView);\n\nvar _collectionModel = __webpack_require__(37);\n\nvar _collectionModel2 = _interopRequireDefault(_collectionModel);\n\nvar _collectionLi = __webpack_require__(43);\n\nvar _collectionLi2 = _interopRequireDefault(_collectionLi);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"collections\";\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a dataset collection.\n */\nvar _super = _listView2.default.ModelListPanel;\nvar CollectionView = _super.extend(\n/** @lends CollectionView.prototype */{\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n _logNamespace: logNamespace,\n\n className: _super.prototype.className + \" dataset-collection-panel\",\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: _collectionLi2.default.DatasetDCEListItemView,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: _collectionLi2.default.NestedDCDCEListItemView,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"elements\",\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function initialize(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n this.hasUser = attributes.hasUser;\n /** A stack of panels that currently cover or hide this panel */\n this.panelStack = [];\n /** The text of the link to go back to the panel containing this one */\n this.parentName = attributes.parentName;\n /** foldout or drilldown */\n this.foldoutStyle = attributes.foldoutStyle || \"foldout\";\n this.downloadUrl = Galaxy.root + \"api/dataset_collections/\" + this.model.attributes.id + \"/download\";\n },\n\n _queueNewRender: function _queueNewRender($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n // TODO: jquery@1.12 doesn't change display when the elem has display: flex\n // this causes display: block for those elems after the use of show/hide animations\n // animations are removed from this view for now until fixed\n panel._swapNewRender($newRender);\n panel.trigger(\"rendered\", panel);\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, use model.getVisibleContents */\n _filterCollection: function _filterCollection() {\n //TODO: should *not* be model.getVisibleContents - visibility is not model related\n return this.model.getVisibleContents();\n },\n\n /** override to return proper view class based on element_type */\n _getItemViewClass: function _getItemViewClass(model) {\n //this.debug( this + '._getItemViewClass:', model );\n //TODO: subclasses use DCEViewClass - but are currently unused - decide\n switch (model.get(\"element_type\")) {\n case \"hda\":\n return this.DatasetDCEViewClass;\n case \"dataset_collection\":\n return this.NestedDCDCEViewClass;\n }\n throw new TypeError(\"Unknown element type:\", model.get(\"element_type\"));\n },\n\n /** override to add link target and anon */\n _getItemViewOptions: function _getItemViewOptions(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n hasUser: this.hasUser,\n //TODO: could move to only nested: list:paired\n foldoutStyle: this.foldoutStyle\n });\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n\n // use pub-sub to: handle drilldown expansion and collapse\n panel.listenTo(view, {\n \"expanded:drilldown\": function expandedDrilldown(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function collapsedDrilldown(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n return this;\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function _expandDrilldownPanel(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$(\"> .controls\").add(this.$list()).hide();\n drilldown.parentName = this.model.get(\"name\");\n this.$el.append(drilldown.render().$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function _collapseDrilldownPanel(drilldown) {\n this.panelStack.pop();\n this.render();\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .navigation .back\": \"close\"\n },\n\n /** close/remove this collection panel */\n close: function close(event) {\n this.remove();\n this.trigger(\"close\");\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"CollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nCollectionView.prototype.templates = function () {\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
\"], \"collection\");\n\n return _.extend(_.clone(_super.prototype.templates), {\n controls: controlsTemplate\n });\n}();\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionView = CollectionView.extend(\n/** @lends ListCollectionView.prototype */{\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: _collectionLi2.default.DatasetDCEListItemView,\n\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"ListCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionView = ListCollectionView.extend(\n/** @lends PairCollectionView.prototype */{\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"PairCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListOfPairsCollectionView = CollectionView.extend(\n/** @lends ListOfPairsCollectionView.prototype */{\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: _collectionLi2.default.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function toString() {\n return \"ListOfPairsCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionView = CollectionView.extend({\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: _collectionLi2.default.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n /** string rep */\n toString: function toString() {\n return \"ListOfListsCollectionView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//==============================================================================\nexports.default = {\n CollectionView: CollectionView,\n ListCollectionView: ListCollectionView,\n PairCollectionView: PairCollectionView,\n ListOfPairsCollectionView: ListOfPairsCollectionView,\n ListOfListsCollectionView: ListOfListsCollectionView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 88 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _datasetLi = __webpack_require__(42);\n\nvar _datasetLi2 = _interopRequireDefault(_datasetLi);\n\nvar _tag = __webpack_require__(22);\n\nvar _tag2 = _interopRequireDefault(_tag);\n\nvar _annotation = __webpack_require__(89);\n\nvar _annotation2 = _interopRequireDefault(_annotation);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n//==============================================================================\nvar _super = _datasetLi2.default.DatasetListItemView;\n/** @class Editing view for DatasetAssociation.\n */\nvar DatasetListItemEdit = _super.extend(\n/** @lends DatasetListItemEdit.prototype */{\n /** set up: options */\n initialize: function initialize(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.hasUser = attributes.hasUser;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n //TODO: move to HiddenUntilActivatedViewMixin\n /** should the tags editor be shown or hidden initially? */\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n /** should the tags editor be shown or hidden initially? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n },\n\n // ......................................................................... titlebar actions\n /** In this override, add the other two primary actions: edit and delete */\n _renderPrimaryActions: function _renderPrimaryActions() {\n var actions = _super.prototype._renderPrimaryActions.call(this);\n if (this.model.get(\"state\") === _states2.default.NOT_VIEWABLE) {\n return actions;\n }\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions.call(this).concat([this._renderEditButton(), this._renderDeleteButton()]);\n },\n\n //TODO: move titleButtons into state renderers, remove state checks in the buttons\n\n /** Render icon-button to edit the attributes (format, permissions, etc.) this dataset. */\n _renderEditButton: function _renderEditButton() {\n var self = this;\n // don't show edit while uploading, in-accessible\n // DO show if in error (ala previous history panel)\n if (this.model.get(\"state\") === _states2.default.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n var purged = this.model.get(\"purged\");\n var deleted = this.model.get(\"deleted\");\n\n var editBtnData = {\n title: (0, _localization2.default)(\"Edit attributes\"),\n href: Galaxy.root + \"datasets/edit?dataset_id=\" + this.model.attributes.id,\n faIcon: \"fa-pencil\",\n classes: \"edit-btn\",\n onclick: function onclick(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/edit\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n };\n\n // disable if purged or deleted and explain why in the tooltip\n if (deleted || purged) {\n editBtnData.disabled = true;\n if (purged) {\n editBtnData.title = (0, _localization2.default)(\"Cannot edit attributes of datasets removed from disk\");\n } else if (deleted) {\n editBtnData.title = (0, _localization2.default)(\"Undelete dataset to edit attributes\");\n }\n\n // disable if still uploading or new\n } else if (_.contains([_states2.default.UPLOAD, _states2.default.NEW], this.model.get(\"state\"))) {\n editBtnData.disabled = true;\n editBtnData.title = (0, _localization2.default)(\"This dataset is not yet editable\");\n }\n return (0, _faIconButton2.default)(editBtnData);\n },\n\n /** Render icon-button to delete this hda. */\n _renderDeleteButton: function _renderDeleteButton() {\n // don't show delete if...\n if (!this.model.get(\"accessible\")) {\n return null;\n }\n\n var self = this;\n var deletedAlready = this.model.isDeletedOrPurged();\n return (0, _faIconButton2.default)({\n title: !deletedAlready ? (0, _localization2.default)(\"Delete\") : (0, _localization2.default)(\"Dataset is already deleted\"),\n disabled: deletedAlready,\n faIcon: \"fa-times\",\n classes: \"delete-btn\",\n onclick: function onclick() {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n self.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n self.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... details\n /** In this override, add tags and annotations controls, make the ? dbkey a link to editing page */\n _renderDetails: function _renderDetails() {\n //TODO: generalize to be allow different details for each state\n var $details = _super.prototype._renderDetails.call(this);\n\n var state = this.model.get(\"state\");\n\n if (!this.model.isDeletedOrPurged() && _.contains([_states2.default.OK, _states2.default.FAILED_METADATA], state)) {\n this._renderTags($details);\n this._renderAnnotation($details);\n this._makeDbkeyEditLink($details);\n }\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /**************************************************************************\n * Render help button to show tool help text without rerunning the tool.\n * Issue #2100\n */\n _renderToolHelpButton: function _renderToolHelpButton() {\n var datasetID = this.model.attributes.dataset_id;\n var jobID = this.model.attributes.creating_job;\n var self = this;\n\n var parseToolBuild = function parseToolBuild(data) {\n var helpString = \"
\";\n if (data.name && data.help) {\n helpString += \"Tool help for \" + data.name + \"\";\n helpString += data.help;\n } else {\n helpString += \"Tool help is unavailable for this dataset.\";\n }\n helpString += \"
\";\n self.$el.find(\".details\").append($.parseHTML(helpString));\n };\n var parseToolID = function parseToolID(data) {\n $.ajax({\n url: Galaxy.root + \"api/tools/\" + data.tool_id + \"/build\"\n }).done(function (data) {\n parseToolBuild(data);\n }).fail(function () {\n parseToolBuild({});\n });\n };\n if (Galaxy.user.id === null) {\n return null;\n }\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Tool Help\"),\n classes: \"icon-btn\",\n href: \"#\",\n faIcon: \"fa-question\",\n onclick: function onclick() {\n var divString = \"thdiv-\" + datasetID;\n if (self.$el.find(\".toolhelp\").length > 0) {\n self.$el.find(\".toolhelp\").toggle();\n } else {\n $.ajax({\n url: Galaxy.root + \"api/jobs/\" + jobID\n }).done(function (data) {\n parseToolID(data);\n }).fail(function () {\n console.log(\"Failed at recovering job information from the Galaxy API for job id \\\"\" + jobID + \"\\\".\");\n });\n }\n }\n });\n },\n //*************************************************************************\n\n /** Add less commonly used actions in the details section based on state */\n _renderSecondaryActions: function _renderSecondaryActions() {\n var actions = _super.prototype._renderSecondaryActions.call(this);\n switch (this.model.get(\"state\")) {\n case _states2.default.UPLOAD:\n case _states2.default.NOT_VIEWABLE:\n return actions;\n case _states2.default.ERROR:\n // error button comes first\n actions.unshift(this._renderErrButton());\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n case _states2.default.OK:\n case _states2.default.FAILED_METADATA:\n return actions.concat([this._renderRerunButton(), this._renderVisualizationsButton(), this._renderToolHelpButton()]);\n }\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n },\n\n /** Render icon-button to report an error on this dataset to the galaxy admin. */\n _renderErrButton: function _renderErrButton() {\n var self = this;\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"View or report this error\"),\n href: Galaxy.root + \"datasets/error?dataset_id=\" + this.model.attributes.id,\n classes: \"report-error-btn\",\n faIcon: \"fa-bug\",\n onclick: function onclick(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/error\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n });\n },\n\n /** Render icon-button to re-run the job that created this dataset. */\n _renderRerunButton: function _renderRerunButton() {\n var creating_job = this.model.get(\"creating_job\");\n if (this.model.get(\"rerunnable\")) {\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Run this job again\"),\n href: this.model.urls.rerun,\n classes: \"rerun-btn\",\n target: this.linkTarget,\n faIcon: \"fa-refresh\",\n onclick: function onclick(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"/\", {\n job_id: creating_job\n });\n }\n }\n });\n }\n },\n\n /** Render an icon-button or popupmenu of links based on the applicable visualizations */\n _renderVisualizationsButton: function _renderVisualizationsButton() {\n //TODO: someday - lazyload visualizations\n var visualizations = this.model.get(\"visualizations\");\n if (this.model.isDeletedOrPurged() || !this.hasUser || !this.model.hasData() || _.isEmpty(visualizations)) {\n return null;\n }\n if (!_.isObject(visualizations[0])) {\n this.warn(\"Visualizations have been switched off\");\n return null;\n }\n\n var $visualizations = $(this.templates.visualizations(visualizations, this));\n //HACK: need to re-write those directed at galaxy_main with linkTarget\n $visualizations.find('[target=\"galaxy_main\"]').attr(\"target\", this.linkTarget);\n // use addBack here to include the root $visualizations elem (for the case of 1 visualization)\n this._addScratchBookFn($visualizations.find(\".visualization-link\").addBack(\".visualization-link\"));\n return $visualizations;\n },\n\n /** add scratchbook functionality to visualization links */\n _addScratchBookFn: function _addScratchBookFn($links) {\n var li = this;\n $links.click(function (ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Visualization\",\n url: $(this).attr(\"href\")\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n });\n },\n\n //TODO: if possible move these to readonly view - but display the owner's tags/annotation (no edit)\n /** Render the tags list/control */\n _renderTags: function _renderTags($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.tagsEditor = new _tag2.default.TagsEditor({\n model: this.model,\n el: $where.find(\".tags-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function onshow() {\n view.tagsEditorShown = true;\n },\n onhide: function onhide() {\n view.tagsEditorShown = false;\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit dataset tags\"),\n classes: \"tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.tagsEditorShown) {\n this.tagsEditor.toggle(true);\n }\n },\n\n /** Render the annotation display/control */\n _renderAnnotation: function _renderAnnotation($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.annotationEditor = new _annotation2.default.AnnotationEditor({\n model: this.model,\n el: $where.find(\".annotation-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function onshow() {\n view.annotationEditorShown = true;\n },\n onhide: function onhide() {\n view.annotationEditorShown = false;\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit dataset annotation\"),\n classes: \"annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.annotationEditorShown) {\n this.annotationEditor.toggle(true);\n }\n },\n\n /** If the format/dbkey/genome_build isn't set, make the display a link to the edit page */\n _makeDbkeyEditLink: function _makeDbkeyEditLink($details) {\n // make the dbkey a link to editing\n if (this.model.get(\"metadata_dbkey\") === \"?\" && !this.model.isDeletedOrPurged()) {\n var editableDbkey = $('?').attr(\"href\", this.model.urls.edit).attr(\"target\", \"_top\");\n $details.find(\".dbkey .value\").replaceWith(editableDbkey);\n }\n },\n\n // ......................................................................... events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .undelete-link\": \"_clickUndeleteLink\",\n \"click .purge-link\": \"_clickPurgeLink\",\n\n \"click .edit-btn\": function clickEditBtn(ev) {\n this.trigger(\"edit\", this, ev);\n },\n \"click .delete-btn\": function clickDeleteBtn(ev) {\n this.trigger(\"delete\", this, ev);\n },\n \"click .rerun-btn\": function clickRerunBtn(ev) {\n this.trigger(\"rerun\", this, ev);\n },\n \"click .report-err-btn\": function clickReportErrBtn(ev) {\n this.trigger(\"report-err\", this, ev);\n },\n \"click .visualization-btn\": function clickVisualizationBtn(ev) {\n this.trigger(\"visualize\", this, ev);\n },\n \"click .dbkey a\": function clickDbkeyA(ev) {\n this.trigger(\"edit\", this, ev);\n }\n }),\n\n /** listener for item undelete (in the messages section) */\n _clickUndeleteLink: function _clickUndeleteLink(ev) {\n this.model.undelete();\n return false;\n },\n\n /** listener for item purge (in the messages section) */\n _clickPurgeLink: function _clickPurgeLink(ev) {\n if (confirm((0, _localization2.default)(\"This will permanently remove the data in your dataset. Are you sure?\"))) {\n this.model.purge();\n }\n return false;\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function toString() {\n var modelString = this.model ? \"\" + this.model : \"(no model)\";\n return \"HDAEditView(\" + modelString + \")\";\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetListItemEdit.prototype.templates = function () {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n failed_metadata: _baseMvc2.default.wrapTemplate([\n // in this override, provide a link to the edit page\n '<% if( dataset.state === \"failed_metadata\" ){ %>', '
\", \"<% } %>\"], \"dataset\"),\n\n deleted: _baseMvc2.default.wrapTemplate([\n // in this override, provide links to undelete or purge the dataset\n \"<% if( dataset.deleted && !dataset.purged ){ %>\",\n // deleted not purged\n '
\", \"<% } %>\"], \"visualizations\");\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n visualizations: visualizationsTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n DatasetListItemEdit: DatasetListItemEdit\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 89 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(15);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// =============================================================================\n/** A view on any model that has a 'annotation' attribute\n */\nvar AnnotationEditor = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseMvc2.default.HiddenUntilActivatedViewMixin).extend({\n tagName: \"div\",\n className: \"annotation-display\",\n\n /** Set up listeners, parse options */\n initialize: function initialize(options) {\n options = options || {};\n this.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n //console.debug( this, options );\n // only listen to the model only for changes to annotations\n this.listenTo(this.model, \"change:annotation\", function () {\n this.render();\n });\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function render() {\n var view = this;\n this.$el.html(this._template());\n\n //TODO: handle empties better\n this.$annotation().make_text_editable({\n use_textarea: true,\n on_finish: function on_finish(newAnnotation) {\n view.$annotation().text(newAnnotation);\n view.model.save({ annotation: newAnnotation }, { silent: true }).fail(function () {\n view.$annotation().text(view.model.previous(\"annotation\"));\n });\n }\n });\n return this;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _template: function _template() {\n var annotation = this.model.get(\"annotation\");\n return [\n //TODO: make prompt optional\n '\",\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n '
', _.escape(annotation), \"
\"].join(\"\");\n },\n\n /** @returns {jQuery} the main element for this view */\n $annotation: function $annotation() {\n return this.$el.find(\".annotation\");\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function remove() {\n this.$annotation.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function toString() {\n return [\"AnnotationEditor(\", \"\" + this.model, \")\"].join(\"\");\n }\n});\n// =============================================================================\nexports.default = {\n AnnotationEditor: AnnotationEditor\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1)))\n\n/***/ }),\n/* 90 */,\n/* 91 */,\n/* 92 */,\n/* 93 */,\n/* 94 */,\n/* 95 */,\n/* 96 */,\n/* 97 */,\n/* 98 */,\n/* 99 */,\n/* 100 */,\n/* 101 */,\n/* 102 */,\n/* 103 */,\n/* 104 */,\n/* 105 */,\n/* 106 */,\n/* 107 */,\n/* 108 */,\n/* 109 */,\n/* 110 */,\n/* 111 */,\n/* 112 */,\n/* 113 */,\n/* 114 */,\n/* 115 */,\n/* 116 */,\n/* 117 */,\n/* 118 */,\n/* 119 */,\n/* 120 */,\n/* 121 */,\n/* 122 */,\n/* 123 */,\n/* 124 */,\n/* 125 */,\n/* 126 */,\n/* 127 */,\n/* 128 */,\n/* 129 */,\n/* 130 */,\n/* 131 */,\n/* 132 */,\n/* 133 */,\n/* 134 */,\n/* 135 */,\n/* 136 */,\n/* 137 */,\n/* 138 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_) {\n\nvar _jquery = __webpack_require__(0);\n\nvar _jquery2 = _interopRequireDefault(_jquery);\n\nvar _galaxy = __webpack_require__(24);\n\nvar _galaxy2 = _interopRequireDefault(_galaxy);\n\nvar _router = __webpack_require__(30);\n\nvar _router2 = _interopRequireDefault(_router);\n\nvar _toolPanel = __webpack_require__(139);\n\nvar _toolPanel2 = _interopRequireDefault(_toolPanel);\n\nvar _historyPanel = __webpack_require__(150);\n\nvar _historyPanel2 = _interopRequireDefault(_historyPanel);\n\nvar _page = __webpack_require__(25);\n\nvar _page2 = _interopRequireDefault(_page);\n\nvar _toolForm = __webpack_require__(65);\n\nvar _toolForm2 = _interopRequireDefault(_toolForm);\n\nvar _formWrapper = __webpack_require__(44);\n\nvar _formWrapper2 = _interopRequireDefault(_formWrapper);\n\nvar _userPreferences = __webpack_require__(164);\n\nvar _userPreferences2 = _interopRequireDefault(_userPreferences);\n\nvar _userCustomBuilds = __webpack_require__(165);\n\nvar _userCustomBuilds2 = _interopRequireDefault(_userCustomBuilds);\n\nvar _tours = __webpack_require__(57);\n\nvar _tours2 = _interopRequireDefault(_tours);\n\nvar _gridView = __webpack_require__(12);\n\nvar _gridView2 = _interopRequireDefault(_gridView);\n\nvar _gridShared = __webpack_require__(166);\n\nvar _gridShared2 = _interopRequireDefault(_gridShared);\n\nvar _workflow = __webpack_require__(167);\n\nvar _workflow2 = _interopRequireDefault(_workflow);\n\nvar _historyList = __webpack_require__(169);\n\nvar _historyList2 = _interopRequireDefault(_historyList);\n\nvar _toolFormComposite = __webpack_require__(77);\n\nvar _toolFormComposite2 = _interopRequireDefault(_toolFormComposite);\n\nvar _queryStringParsing = __webpack_require__(8);\n\nvar _queryStringParsing2 = _interopRequireDefault(_queryStringParsing);\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _datasetError = __webpack_require__(170);\n\nvar _datasetError2 = _interopRequireDefault(_datasetError);\n\nvar _datasetEditAttributes = __webpack_require__(171);\n\nvar _datasetEditAttributes2 = _interopRequireDefault(_datasetEditAttributes);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar $ = _jquery2.default;\n\n\n/** define the 'Analyze Data'/analysis/main/home page for Galaxy\n * * has a masthead\n * * a left tool menu to allow the user to load tools in the center panel\n * * a right history menu that shows the user's current data\n * * a center panel\n * Both panels (generally) persist while the center panel shows any\n * UI needed for the current step of an analysis, like:\n * * tool forms to set tool parameters,\n * * tables showing the contents of datasets\n * * etc.\n */\nwindow.app = function app(options, bootstrapped) {\n window.Galaxy = new _galaxy2.default.GalaxyApp(options, bootstrapped);\n Galaxy.debug(\"analysis app\");\n\n /** Routes */\n var AnalysisRouter = _router2.default.extend({\n routes: {\n \"(/)\": \"home\",\n \"(/)root*\": \"home\",\n \"(/)tours(/)(:tour_id)\": \"show_tours\",\n \"(/)user(/)\": \"show_user\",\n \"(/)user(/)(:form_id)\": \"show_user_form\",\n \"(/)workflow(/)\": \"show_workflows\",\n \"(/)workflow/run(/)\": \"show_run\",\n \"(/)pages(/)create(/)\": \"show_pages_create\",\n \"(/)pages(/)edit(/)\": \"show_pages_edit\",\n \"(/)pages(/)(:action_id)\": \"show_pages\",\n \"(/)visualizations(/)edit(/)\": \"show_visualizations_edit\",\n \"(/)visualizations/(:action_id)\": \"show_visualizations\",\n \"(/)workflows/list_published(/)\": \"show_workflows_published\",\n \"(/)histories(/)rename(/)\": \"show_histories_rename\",\n \"(/)histories(/)permissions(/)\": \"show_histories_permissions\",\n \"(/)histories(/)(:action_id)\": \"show_histories\",\n \"(/)datasets(/)list(/)\": \"show_datasets\",\n \"(/)workflow/import_workflow\": \"show_import_workflow\",\n \"(/)custom_builds\": \"show_custom_builds\",\n \"(/)datasets/edit\": \"show_dataset_edit_attributes\",\n \"(/)datasets/error\": \"show_dataset_error\"\n },\n\n require_login: [\"show_user\", \"show_user_form\", \"show_workflows\"],\n\n authenticate: function authenticate(args, name) {\n return Galaxy.user && Galaxy.user.id || this.require_login.indexOf(name) == -1;\n },\n\n show_tours: function show_tours(tour_id) {\n if (tour_id) {\n _tours2.default.giveTour(tour_id);\n } else {\n this.page.display(new _tours2.default.ToursView());\n }\n },\n\n show_user: function show_user() {\n this.page.display(new _userPreferences2.default.View());\n },\n\n show_user_form: function show_user_form(form_id) {\n var model = new _userPreferences2.default.Model({\n user_id: Galaxy.params.id\n });\n this.page.display(new _formWrapper2.default.View(model.get(form_id)));\n },\n\n show_visualizations: function show_visualizations(action_id) {\n this.page.display(new _gridShared2.default.View({\n action_id: action_id,\n plural: \"Visualizations\",\n item: \"visualization\"\n }));\n },\n\n show_visualizations_edit: function show_visualizations_edit() {\n this.page.display(new _formWrapper2.default.View({\n url: \"visualization/edit?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"visualizations/list\"\n }));\n },\n\n show_workflows_published: function show_workflows_published() {\n this.page.display(new _gridView2.default({\n url_base: Galaxy.root + \"workflow/list_published\",\n dict_format: true\n }));\n },\n\n show_histories: function show_histories(action_id) {\n this.page.display(new _historyList2.default.View({ action_id: action_id }));\n },\n\n show_histories_rename: function show_histories_rename() {\n this.page.display(new _formWrapper2.default.View({\n url: \"history/rename?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"histories/list\"\n }));\n },\n\n show_histories_permissions: function show_histories_permissions() {\n this.page.display(new _formWrapper2.default.View({\n url: \"history/permissions?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"histories/list\"\n }));\n },\n\n show_datasets: function show_datasets() {\n this.page.display(new _gridView2.default({\n url_base: Galaxy.root + \"dataset/list\",\n dict_format: true\n }));\n },\n\n show_pages: function show_pages(action_id) {\n this.page.display(new _gridShared2.default.View({\n action_id: action_id,\n plural: \"Pages\",\n item: \"page\"\n }));\n },\n\n show_pages_create: function show_pages_create() {\n this.page.display(new _formWrapper2.default.View({\n url: \"page/create\",\n redirect: \"pages/list\"\n }));\n },\n\n show_pages_edit: function show_pages_edit() {\n this.page.display(new _formWrapper2.default.View({\n url: \"page/edit?id=\" + _queryStringParsing2.default.get(\"id\"),\n redirect: \"pages/list\"\n }));\n },\n\n show_workflows: function show_workflows() {\n this.page.display(new _workflow2.default.View());\n },\n\n show_run: function show_run() {\n this._loadWorkflow();\n },\n\n show_import_workflow: function show_import_workflow() {\n this.page.display(new _workflow2.default.ImportWorkflowView());\n },\n\n show_custom_builds: function show_custom_builds() {\n var self = this;\n var historyPanel = this.page.historyPanel.historyView;\n if (!historyPanel || !historyPanel.model || !historyPanel.model.id) {\n window.setTimeout(function () {\n self.show_custom_builds();\n }, 500);\n return;\n }\n this.page.display(new _userCustomBuilds2.default.View());\n },\n\n show_dataset_edit_attributes: function show_dataset_edit_attributes() {\n this.page.display(new _datasetEditAttributes2.default.View());\n },\n\n show_dataset_error: function show_dataset_error() {\n this.page.display(new _datasetError2.default.View());\n },\n\n /** */\n home: function home(params) {\n // TODO: to router, remove Globals\n // load a tool by id (tool_id) or rerun a previous tool execution (job_id)\n if (params.tool_id || params.job_id) {\n if (params.tool_id === \"upload1\") {\n this.page.toolPanel.upload.show();\n this._loadCenterIframe(\"welcome\");\n } else {\n this._loadToolForm(params);\n }\n } else {\n // show the workflow run form\n if (params.workflow_id) {\n this._loadWorkflow();\n // load the center iframe with controller.action: galaxy.org/?m_c=history&m_a=list -> history/list\n } else if (params.m_c) {\n this._loadCenterIframe(params.m_c + \"/\" + params.m_a);\n // show the workflow run form\n } else {\n this._loadCenterIframe(\"welcome\");\n }\n }\n },\n\n /** load the center panel with a tool form described by the given params obj */\n _loadToolForm: function _loadToolForm(params) {\n //TODO: load tool form code async\n params.id = decodeURIComponent(params.tool_id);\n this.page.display(new _toolForm2.default.View(params));\n },\n\n /** load the center panel iframe using the given url */\n _loadCenterIframe: function _loadCenterIframe(url, root) {\n root = root || Galaxy.root;\n url = root + url;\n this.page.$(\"#galaxy_main\").prop(\"src\", url);\n },\n\n /** load workflow by its url in run mode */\n _loadWorkflow: function _loadWorkflow() {\n var self = this;\n _utils2.default.get({\n url: Galaxy.root + \"api/workflows/\" + _utils2.default.getQueryString(\"id\") + \"/download?style=run\",\n success: function success(response) {\n self.page.display(new _toolFormComposite2.default.View(response));\n },\n error: function error(response) {\n var error_msg = response.err_msg || \"Error occurred while loading the resource.\";\n var options = {\n message: error_msg,\n status: \"danger\",\n persistent: true\n };\n self.page.display(new _uiMisc2.default.Message(options));\n }\n });\n }\n });\n\n // render and start the router\n $(function () {\n Galaxy.page = new _page2.default.View(_.extend(options, {\n Left: _toolPanel2.default,\n Right: _historyPanel2.default,\n Router: AnalysisRouter\n }));\n });\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))\n\n/***/ }),\n/* 139 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _tools = __webpack_require__(64);\n\nvar _tools2 = _interopRequireDefault(_tools);\n\nvar _uploadView = __webpack_require__(140);\n\nvar _uploadView2 = _interopRequireDefault(_uploadView);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nvar _toolFormComposite = __webpack_require__(77);\n\nvar _toolFormComposite2 = _interopRequireDefault(_toolFormComposite);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar ToolPanel = Backbone.View.extend({\n initialize: function initialize(page, options) {\n // access configuration options\n var config = options.config;\n this.root = options.root;\n\n /** @type {Object[]} descriptions of user's workflows to be shown in the tool menu */\n this.stored_workflow_menu_entries = config.stored_workflow_menu_entries || [];\n\n // create tool search, tool panel, and tool panel view.\n var tool_search = new _tools2.default.ToolSearch({\n hidden: false\n });\n var tools = new _tools2.default.ToolCollection(config.toolbox);\n this.tool_panel = new _tools2.default.ToolPanel({\n tool_search: tool_search,\n tools: tools,\n layout: config.toolbox_in_panel\n });\n this.tool_panel_view = new _tools2.default.ToolPanelView({\n model: this.tool_panel\n });\n\n // add upload modal\n this.upload_button = new _uploadView2.default({\n nginx_upload_path: config.nginx_upload_path,\n ftp_upload_site: config.ftp_upload_site,\n default_genome: config.default_genome,\n default_extension: config.default_extension\n });\n\n // add uploader button to Galaxy object\n Galaxy.upload = this.upload_button;\n\n // components for panel definition\n this.model = new Backbone.Model({\n title: (0, _localization2.default)(\"Tools\"),\n buttons: [this.upload_button]\n });\n\n // build body template\n this.setElement(this._template());\n },\n\n render: function render() {\n // if there are tools, render panel and display everything\n var self = this;\n if (this.tool_panel.get(\"layout\").size() > 0) {\n this.$el.prepend(this.tool_panel_view.$el);\n this.tool_panel_view.render();\n }\n // build the dom for the workflow portion of the tool menu\n // add internal workflow list\n self.$(\"#internal-workflows\").append(self._templateAllWorkflow({\n title: (0, _localization2.default)(\"All workflows\"),\n href: \"workflow\"\n }));\n _.each(this.stored_workflow_menu_entries, function (menu_entry) {\n self.$(\"#internal-workflows\").append(self._templateWorkflowLink({\n title: menu_entry.stored_workflow.name,\n href: \"workflow/run?id=\" + menu_entry.encoded_stored_workflow_id\n }));\n });\n },\n\n /** build a link to one tool */\n _templateTool: function _templateTool(tool) {\n return ['
\";\n }\n});\nexports.default = { View: View };\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 142 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _defaultRow = __webpack_require__(143);\n\nvar _defaultRow2 = _interopRequireDefault(_defaultRow);\n\nvar _uploadFtp2 = __webpack_require__(32);\n\nvar _uploadFtp3 = _interopRequireDefault(_uploadFtp2);\n\nvar _uploadExtension = __webpack_require__(33);\n\nvar _uploadExtension2 = _interopRequireDefault(_uploadExtension);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _lazyLimited = __webpack_require__(144);\n\nvar _lazyLimited2 = _interopRequireDefault(_lazyLimited);\n\n__webpack_require__(34);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Renders contents of the default uploader */\nexports.default = Backbone.View.extend({\n // current upload size in bytes\n upload_size: 0,\n\n // contains upload row models\n collection: new _uploadModel2.default.Collection(),\n\n // keeps track of the current uploader state\n counter: {\n announce: 0,\n success: 0,\n error: 0,\n running: 0,\n reset: function reset() {\n this.announce = this.success = this.error = this.running = 0;\n }\n },\n\n initialize: function initialize(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ui_button = app.ui_button;\n this.ftp_upload_site = app.currentFtp();\n\n // build template\n this.setElement(this._template());\n this.$uploadbox = this.$(\".upload-box\");\n this.$uploadtable = this.$(\".upload-table\");\n\n // append buttons to dom\n this.btnLocal = new _uiMisc2.default.Button({\n id: \"btn-local\",\n title: \"Choose local file\",\n onclick: function onclick() {\n self.uploadbox.select();\n },\n icon: \"fa fa-laptop\"\n });\n this.btnFtp = new _uiMisc2.default.Button({\n id: \"btn-ftp\",\n title: \"Choose FTP file\",\n onclick: function onclick() {\n self._eventFtp();\n },\n icon: \"fa fa-folder-open-o\"\n });\n this.btnCreate = new _uiMisc2.default.Button({\n id: \"btn-new\",\n title: \"Paste/Fetch data\",\n onclick: function onclick() {\n self._eventCreate();\n },\n icon: \"fa fa-edit\"\n });\n this.btnStart = new _uiMisc2.default.Button({\n id: \"btn-start\",\n title: \"Start\",\n onclick: function onclick() {\n self._eventStart();\n }\n });\n this.btnStop = new _uiMisc2.default.Button({\n id: \"btn-stop\",\n title: \"Pause\",\n onclick: function onclick() {\n self._eventStop();\n }\n });\n this.btnReset = new _uiMisc2.default.Button({\n id: \"btn-reset\",\n title: \"Reset\",\n onclick: function onclick() {\n self._eventReset();\n }\n });\n this.btnClose = new _uiMisc2.default.Button({\n id: \"btn-close\",\n title: \"Close\",\n onclick: function onclick() {\n self.app.modal.hide();\n }\n });\n _.each([this.btnLocal, this.btnFtp, this.btnCreate, this.btnStop, this.btnReset, this.btnStart, this.btnClose], function (button) {\n self.$(\".upload-buttons\").prepend(button.$el);\n });\n\n // file upload\n this.uploadbox = this.$uploadbox.uploadbox({\n url: this.app.options.nginx_upload_path,\n announce: function announce(index, file) {\n self._eventAnnounce(index, file);\n },\n initialize: function initialize(index) {\n return self.app.toData([self.collection.get(index)], self.history_id);\n },\n progress: function progress(index, percentage) {\n self._eventProgress(index, percentage);\n },\n success: function success(index, message) {\n self._eventSuccess(index, message);\n },\n error: function error(index, message) {\n self._eventError(index, message);\n },\n complete: function complete() {\n self._eventComplete();\n },\n ondragover: function ondragover() {\n self.$uploadbox.addClass(\"highlight\");\n },\n ondragleave: function ondragleave() {\n self.$uploadbox.removeClass(\"highlight\");\n }\n });\n\n // add ftp file viewer\n this.ftp = new _uiPopover2.default.View({\n title: \"FTP files\",\n container: this.btnFtp.$el\n });\n\n // select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, function (ext) {\n return !ext.composite_files;\n }),\n value: this.options.default_extension,\n onchange: function onchange(extension) {\n self._changeExtension(extension);\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\").on(\"click\", function (e) {\n new _uploadExtension2.default({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome,\n onchange: function onchange(genome) {\n self._changeGenome(genome);\n }\n });\n\n // Lazy load helper\n this.loader = new _lazyLimited2.default({\n $container: this.$uploadbox,\n collection: this.collection,\n new_content: function new_content(model) {\n var upload_row = new _defaultRow2.default(self, { model: model });\n self.$uploadtable.find(\"> tbody:first\").append(upload_row.$el);\n upload_row.render();\n return upload_row;\n }\n });\n\n // events\n this.collection.on(\"remove\", function (model) {\n self._eventRemove(model);\n });\n this.render();\n },\n\n render: function render() {\n var message = \"\";\n if (this.counter.announce == 0) {\n if (this.uploadbox.compatible()) {\n message = \" \";\n } else {\n message = \"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.\";\n }\n } else {\n if (this.counter.running == 0) {\n message = \"You added \" + this.counter.announce + \" file(s) to the queue. Add more files or click 'Start' to proceed.\";\n } else {\n message = \"Please wait...\" + this.counter.announce + \" out of \" + this.counter.running + \" remaining.\";\n }\n }\n this.$(\".upload-top-info\").html(message);\n var enable_reset = this.counter.running == 0 && this.counter.announce + this.counter.success + this.counter.error > 0;\n var enable_start = this.counter.running == 0 && this.counter.announce > 0;\n var enable_sources = this.counter.running == 0;\n var show_table = this.counter.announce + this.counter.success + this.counter.error > 0;\n this.btnReset[enable_reset ? \"enable\" : \"disable\"]();\n this.btnStart[enable_start ? \"enable\" : \"disable\"]();\n this.btnStart.$el[enable_start ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnStop[this.counter.running > 0 ? \"enable\" : \"disable\"]();\n this.btnLocal[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp[enable_sources ? \"enable\" : \"disable\"]();\n this.btnCreate[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp.$el[this.ftp_upload_site ? \"show\" : \"hide\"]();\n this.$(\".upload-table\")[show_table ? \"show\" : \"hide\"]();\n this.$(\".upload-helper\")[show_table ? \"hide\" : \"show\"]();\n },\n\n /** A new file has been dropped/selected through the uploadbox plugin */\n _eventAnnounce: function _eventAnnounce(index, file) {\n this.counter.announce++;\n var new_model = new _uploadModel2.default.Model({\n id: index,\n file_name: file.name,\n file_size: file.size,\n file_mode: file.mode || \"local\",\n file_path: file.path,\n file_data: file\n });\n this.render();\n this.collection.add(new_model);\n },\n\n /** Progress */\n _eventProgress: function _eventProgress(index, percentage) {\n var it = this.collection.get(index);\n it.set(\"percentage\", percentage);\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(percentage, it.get(\"file_size\")));\n },\n\n /** Success */\n _eventSuccess: function _eventSuccess(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"success\" });\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(100, it.get(\"file_size\")));\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.success++;\n this.render();\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Error */\n _eventError: function _eventError(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"error\", info: message });\n this.ui_button.model.set({\n percentage: this._uploadPercentage(100, it.get(\"file_size\")),\n status: \"danger\"\n });\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.error++;\n this.render();\n },\n\n /** Queue is done */\n _eventComplete: function _eventComplete() {\n this.collection.each(function (model) {\n model.get(\"status\") == \"queued\" && model.set(\"status\", \"init\");\n });\n this.counter.running = 0;\n this.render();\n },\n\n /** Remove model from upload list */\n _eventRemove: function _eventRemove(model) {\n var status = model.get(\"status\");\n if (status == \"success\") {\n this.counter.success--;\n } else if (status == \"error\") {\n this.counter.error--;\n } else {\n this.counter.announce--;\n }\n this.uploadbox.remove(model.id);\n this.render();\n },\n\n //\n // events triggered by this view\n //\n\n /** Show/hide ftp popup */\n _eventFtp: function _eventFtp() {\n if (!this.ftp.visible) {\n this.ftp.empty();\n var self = this;\n this.ftp.append(new _uploadFtp3.default({\n collection: this.collection,\n ftp_upload_site: this.ftp_upload_site,\n onadd: function onadd(ftp_file) {\n return self.uploadbox.add([{\n mode: \"ftp\",\n name: ftp_file.path,\n size: ftp_file.size,\n path: ftp_file.path\n }]);\n },\n onremove: function onremove(model_index) {\n self.collection.remove(model_index);\n }\n }).$el);\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Create a new file */\n _eventCreate: function _eventCreate() {\n this.uploadbox.add([{ name: \"New File\", size: 0, mode: \"new\" }]);\n },\n\n /** Start upload process */\n _eventStart: function _eventStart() {\n if (this.counter.announce != 0 && this.counter.running == 0) {\n // prepare upload process\n var self = this;\n this.upload_size = 0;\n this.upload_completed = 0;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\") {\n model.set(\"status\", \"queued\");\n self.upload_size += model.get(\"file_size\");\n }\n });\n this.ui_button.model.set({\n percentage: 0,\n status: \"success\"\n });\n this.counter.running = this.counter.announce;\n this.history_id = this.app.currentHistory();\n\n // package ftp files separately, and remove them from queue\n this._uploadFtp();\n\n // queue remaining files\n this.uploadbox.start();\n this.render();\n }\n },\n\n /** Pause upload process */\n _eventStop: function _eventStop() {\n if (this.counter.running > 0) {\n this.ui_button.model.set(\"status\", \"info\");\n $(\".upload-top-info\").html(\"Queue will pause after completing the current file...\");\n this.uploadbox.stop();\n }\n },\n\n /** Remove all */\n _eventReset: function _eventReset() {\n if (this.counter.running == 0) {\n var self = this;\n this.collection.reset();\n this.counter.reset();\n this.uploadbox.reset();\n this.select_extension.value(this.options.default_extension);\n this.select_genome.value(this.options.default_genome);\n this.ui_button.model.set(\"percentage\", 0);\n this.render();\n }\n },\n\n /** Update extension for all models */\n _changeExtension: function _changeExtension(extension, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"extension\") == self.options.default_extension || !defaults_only)) {\n model.set(\"extension\", extension);\n }\n });\n },\n\n /** Update genome for all models */\n _changeGenome: function _changeGenome(genome, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"genome\") == self.options.default_genome || !defaults_only)) {\n model.set(\"genome\", genome);\n }\n });\n },\n\n /** Package and upload ftp files in a single request */\n _uploadFtp: function _uploadFtp() {\n var self = this;\n var list = [];\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"queued\" && model.get(\"file_mode\") == \"ftp\") {\n self.uploadbox.remove(model.id);\n list.push(model);\n }\n });\n if (list.length > 0) {\n $.uploadpost({\n data: this.app.toData(list),\n url: this.app.options.nginx_upload_path,\n success: function success(message) {\n _.each(list, function (model) {\n self._eventSuccess(model.id);\n });\n },\n error: function error(message) {\n _.each(list, function (model) {\n self._eventError(model.id, message);\n });\n }\n });\n }\n },\n\n /** Calculate percentage of all queued uploads */\n _uploadPercentage: function _uploadPercentage(percentage, size) {\n return (this.upload_completed + percentage * size) / this.upload_size;\n },\n\n /** Template */\n _template: function _template() {\n return '
' + '
' + '
' + \"
\" + '
' + '
Drop files here
' + '
' + \"\" + \"
\" + \"
Name
\" + \"
Size
\" + \"
Type
\" + \"
Genome
\" + \"
Settings
\" + \"
Status
\" + \"
\" + \"
\" + \"\" + \"\" + \"
\" + \"
\" + '\" + '
' + \"
\";\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 143 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _uploadSettings = __webpack_require__(31);\n\nvar _uploadSettings2 = _interopRequireDefault(_uploadSettings);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-icon-button fa fa-trash-o\",\n queued: \"upload-icon fa fa-spinner fa-spin\",\n running: \"upload-icon fa fa-spinner fa-spin\",\n success: \"upload-icon-button fa fa-check\",\n error: \"upload-icon-button fa fa-exclamation-triangle\"\n },\n\n initialize: function initialize(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template(options.model));\n this.$mode = this.$(\".upload-mode\");\n this.$title = this.$(\".upload-title\");\n this.$text = this.$(\".upload-text\");\n this.$size = this.$(\".upload-size\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$settings = this.$(\".upload-settings\");\n this.$symbol = this.$(\".upload-symbol\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // append popup to settings icon\n this.settings = new _uiPopover2.default.View({\n title: \"Upload configuration\",\n container: this.$(\".upload-settings\"),\n placement: \"bottom\"\n });\n\n // identify default genome and extension values\n var default_genome = this.app.select_genome.value();\n var default_extension = this.app.select_extension.value();\n\n // create select genomes\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-genome\",\n data: self.app.list_genomes,\n container: this.$(\".upload-genome\"),\n value: default_genome,\n onchange: function onchange(genome) {\n self.model.set(\"genome\", genome);\n }\n });\n\n // create select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-extension\",\n data: self.app.list_extensions,\n container: this.$(\".upload-extension\"),\n value: default_extension,\n onchange: function onchange(extension) {\n self.model.set(\"extension\", extension);\n }\n });\n\n // initialize genome and extension values\n this.model.set({\n genome: default_genome,\n extension: default_extension\n });\n\n // handle click event\n this.$symbol.on(\"click\", function () {\n self._removeRow();\n });\n\n // handle extension info popover\n this.$(\".upload-extension-info\").on(\"click\", function (e) {\n self.app.showExtensionInfo({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value()\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // handle settings popover\n this.$settings.on(\"click\", function (e) {\n self._showSettings();\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", function (e) {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", function () {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", function () {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", function () {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:genome\", function () {\n self._refreshGenome();\n });\n this.listenTo(this.model, \"change:extension\", function () {\n self._refreshExtension();\n });\n this.listenTo(this.model, \"change:file_size\", function () {\n self._refreshFileSize();\n });\n },\n\n render: function render() {\n this._refreshType();\n this._refreshPercentage();\n this._refreshStatus();\n this._refreshInfo();\n this._refreshGenome();\n this._refreshExtension();\n this._refreshFileSize();\n },\n\n /** Remove view */\n remove: function remove() {\n this.select_genome.remove();\n this.select_extension.remove();\n Backbone.View.prototype.remove.apply(this);\n },\n\n /** Render type */\n _refreshType: function _refreshType() {\n var options = this.model.attributes;\n this.$title.html(_.escape(options.file_name));\n this.$size.html(_utils2.default.bytesToString(options.file_size));\n this.$mode.removeClass().addClass(\"upload-mode\").addClass(\"text-primary\");\n if (options.file_mode == \"new\") {\n this.$text.css({\n width: this.$el.width() - 16 + \"px\",\n top: this.$el.height() - 8 + \"px\"\n }).show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$mode.addClass(\"fa fa-edit\");\n } else if (options.file_mode == \"local\") {\n this.$mode.addClass(\"fa fa-laptop\");\n } else if (options.file_mode == \"ftp\") {\n this.$mode.addClass(\"fa fa-folder-open-o\");\n }\n },\n\n /** Update extension */\n _refreshExtension: function _refreshExtension() {\n this.select_extension.value(this.model.get(\"extension\"));\n },\n\n /** Update genome */\n _refreshGenome: function _refreshGenome() {\n this.select_genome.value(this.model.get(\"genome\"));\n },\n\n /** Refresh info text */\n _refreshInfo: function _refreshInfo() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(\"Failed: \" + info).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage status */\n _refreshPercentage: function _refreshPercentage() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n this.$progress_bar.css({ width: percentage + \"%\" });\n this.$percentage.html(percentage != 100 ? percentage + \"%\" : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function _refreshStatus() {\n var status = this.model.get(\"status\");\n this.$symbol.removeClass().addClass(\"upload-symbol\").addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status == \"init\");\n var enabled = this.model.get(\"enabled\");\n this.$text_content.attr(\"disabled\", !enabled);\n if (enabled) {\n this.select_genome.enable();\n this.select_extension.enable();\n } else {\n this.select_genome.disable();\n this.select_extension.disable();\n }\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.$info_progress.hide();\n }\n },\n\n /** Refresh file size */\n _refreshFileSize: function _refreshFileSize() {\n this.$size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Remove row */\n _removeRow: function _removeRow() {\n if ([\"init\", \"success\", \"error\"].indexOf(this.model.get(\"status\")) !== -1) {\n this.app.collection.remove(this.model);\n }\n },\n\n /** Attach file info popup */\n _showSettings: function _showSettings() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new _uploadSettings2.default(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** View template */\n _template: function _template(options) {\n return \"
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
 
0%
\";\n }\n}); /** Renders the default uploader rows */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 144 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/** Contains helpers to limit/lazy load views for backbone views */\n\nexports.default = Backbone.View.extend({\n initialize: function initialize(options) {\n var self = this;\n this.$container = options.$container;\n this.collection = options.collection;\n this.new_content = options.new_content;\n this.max = options.max || 50;\n this.content_list = {};\n this.$message = $(\"\").addClass(\"ui-limitloader\").append(\"...only the first \" + this.max + \" entries are visible.\");\n this.$container.append(this.$message);\n this.listenTo(this.collection, \"reset\", this._reset, this);\n this.listenTo(this.collection, \"add\", this._refresh, this);\n this.listenTo(this.collection, \"remove\", this._remove, this);\n },\n\n /** Checks if the limit has been reached */\n _done: function _done() {\n var done = _.size(this.content_list) > this.max;\n this.$message[done ? \"show\" : \"hide\"]();\n return done;\n },\n\n /** Remove all content */\n _reset: function _reset() {\n _.each(this.content_list, function (content) {\n content.remove();\n });\n this.content_list = {};\n this.$message.hide();\n },\n\n /** Remove content */\n _remove: function _remove(model) {\n var model_id = model.id;\n var content = this.content_list[model_id];\n if (content) {\n content.remove();\n delete this.content_list[model_id];\n }\n this._refresh();\n },\n\n /** Refreshes container content by adding new views if visible */\n _refresh: function _refresh() {\n if (!this._done()) {\n for (var i in this.collection.models) {\n var model = this.collection.models[i];\n var view = this.content_list[model.id];\n if (!this.content_list[model.id]) {\n var content = this.new_content(model);\n this.content_list[model.id] = content;\n if (this._done()) {\n break;\n }\n }\n }\n }\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 145 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _compositeRow = __webpack_require__(146);\n\nvar _compositeRow2 = _interopRequireDefault(_compositeRow);\n\nvar _uploadExtension = __webpack_require__(33);\n\nvar _uploadExtension2 = _interopRequireDefault(_uploadExtension);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n collection: new _uploadModel2.default.Collection(),\n initialize: function initialize(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ftp_upload_site = app.currentFtp();\n this.setElement(this._template());\n\n // create button section\n this.btnStart = new _uiMisc2.default.Button({\n title: \"Start\",\n onclick: function onclick() {\n self._eventStart();\n }\n });\n this.btnClose = new _uiMisc2.default.Button({\n title: \"Close\",\n onclick: function onclick() {\n self.app.modal.hide();\n }\n });\n\n // append buttons to dom\n _.each([this.btnStart, this.btnClose], function (button) {\n self.$(\".upload-buttons\").prepend(button.$el);\n });\n\n // select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, function (ext) {\n return ext.composite_files;\n }),\n onchange: function onchange(extension) {\n self.collection.reset();\n var details = _.findWhere(self.list_extensions, {\n id: extension\n });\n if (details && details.composite_files) {\n _.each(details.composite_files, function (item) {\n self.collection.add({\n id: self.collection.size(),\n file_desc: item.description || item.name\n });\n });\n }\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\").on(\"click\", function (e) {\n new _uploadExtension2.default({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome\n });\n\n // listener for collection triggers on change in composite datatype and extension selection\n this.listenTo(this.collection, \"add\", function (model) {\n self._eventAnnounce(model);\n });\n this.listenTo(this.collection, \"change add\", function () {\n self.render();\n });\n this.select_extension.options.onchange(this.select_extension.value());\n this.render();\n },\n\n render: function render() {\n var model = this.collection.first();\n if (model && model.get(\"status\") == \"running\") {\n this.select_genome.disable();\n this.select_extension.disable();\n } else {\n this.select_genome.enable();\n this.select_extension.enable();\n }\n if (this.collection.where({ status: \"ready\" }).length == this.collection.length && this.collection.length > 0) {\n this.btnStart.enable();\n this.btnStart.$el.addClass(\"btn-primary\");\n } else {\n this.btnStart.disable();\n this.btnStart.$el.removeClass(\"btn-primary\");\n }\n this.$(\".upload-table\")[this.collection.length > 0 ? \"show\" : \"hide\"]();\n },\n\n //\n // upload events / process pipeline\n //\n\n /** Builds the basic ui with placeholder rows for each composite data type file */\n _eventAnnounce: function _eventAnnounce(model) {\n var upload_row = new _compositeRow2.default(this, { model: model });\n this.$(\".upload-table > tbody:first\").append(upload_row.$el);\n this.$(\".upload-table\")[this.collection.length > 0 ? \"show\" : \"hide\"]();\n upload_row.render();\n },\n\n /** Start upload process */\n _eventStart: function _eventStart() {\n var self = this;\n this.collection.each(function (model) {\n model.set({\n genome: self.select_genome.value(),\n extension: self.select_extension.value()\n });\n });\n $.uploadpost({\n url: this.app.options.nginx_upload_path,\n data: this.app.toData(this.collection.filter()),\n success: function success(message) {\n self._eventSuccess(message);\n },\n error: function error(message) {\n self._eventError(message);\n },\n progress: function progress(percentage) {\n self._eventProgress(percentage);\n }\n });\n },\n\n /** Refresh progress state */\n _eventProgress: function _eventProgress(percentage) {\n this.collection.each(function (it) {\n it.set(\"percentage\", percentage);\n });\n },\n\n /** Refresh success state */\n _eventSuccess: function _eventSuccess(message) {\n this.collection.each(function (it) {\n it.set(\"status\", \"success\");\n });\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Refresh error state */\n _eventError: function _eventError(message) {\n this.collection.each(function (it) {\n it.set({ status: \"error\", info: message });\n });\n },\n\n /** Load html template */\n _template: function _template() {\n return '
' + '
' + '
' + \"
\" + '
' + '
' + \"\" + \"
\" + \"
\" + \"
\" + \"
Description
\" + \"
Name
\" + \"
Size
\" + \"
Settings
\" + \"
Status
\" + \"
\" + \"\" + \"\" + \"
\" + \"
\" + '\" + '
' + \"
\";\n }\n}); /** Renders contents of the composite uploader */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 146 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadSettings = __webpack_require__(31);\n\nvar _uploadSettings2 = _interopRequireDefault(_uploadSettings);\n\nvar _uploadFtp = __webpack_require__(32);\n\nvar _uploadFtp2 = _interopRequireDefault(_uploadFtp);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\n__webpack_require__(34);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-mode fa fa-exclamation text-primary\",\n ready: \"upload-mode fa fa-check text-success\",\n running: \"upload-mode fa fa-spinner fa-spin\",\n success: \"upload-mode fa fa-check\",\n error: \"upload-mode fa fa-exclamation-triangle\"\n },\n\n initialize: function initialize(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template());\n this.$source = this.$(\".upload-source\");\n this.$settings = this.$(\".upload-settings\");\n this.$status = this.$(\".upload-status\");\n this.$text = this.$(\".upload-text\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$file_name = this.$(\".upload-file-name\");\n this.$file_desc = this.$(\".upload-file-desc\");\n this.$file_size = this.$(\".upload-file-size\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // build upload functions\n this.uploadinput = this.$el.uploadinput({\n ondragover: function ondragover() {\n self.model.get(\"enabled\") && self.$el.addClass(\"warning\");\n },\n ondragleave: function ondragleave() {\n self.$el.removeClass(\"warning\");\n },\n onchange: function onchange(files) {\n if (self.model.get(\"status\") != \"running\" && files && files.length > 0) {\n self.model.reset({\n file_data: files[0],\n file_name: files[0].name,\n file_size: files[0].size,\n file_mode: files[0].mode || \"local\"\n });\n self._refreshReady();\n }\n }\n });\n\n // source selection popup\n this.button_menu = new _uiMisc2.default.ButtonMenu({\n icon: \"fa-caret-down\",\n title: \"Select\",\n pull: \"left\"\n });\n this.$source.append(this.button_menu.$el);\n this.button_menu.addMenu({\n icon: \"fa-laptop\",\n title: \"Choose local file\",\n onclick: function onclick() {\n self.uploadinput.dialog();\n }\n });\n if (this.app.ftp_upload_site) {\n this.button_menu.addMenu({\n icon: \"fa-folder-open-o\",\n title: \"Choose FTP file\",\n onclick: function onclick() {\n self._showFtp();\n }\n });\n }\n this.button_menu.addMenu({\n icon: \"fa-edit\",\n title: \"Paste/Fetch data\",\n onclick: function onclick() {\n self.model.reset({\n file_mode: \"new\",\n file_name: \"New File\"\n });\n }\n });\n\n // add ftp file viewer\n this.ftp = new _uiPopover2.default.View({\n title: \"Choose FTP file:\",\n container: this.$source.find(\".ui-button-menu\"),\n placement: \"right\"\n });\n\n // append popup to settings icon\n this.settings = new _uiPopover2.default.View({\n title: \"Upload configuration\",\n container: this.$settings,\n placement: \"bottom\"\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", function (e) {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n self._refreshReady();\n });\n\n // handle settings popover\n this.$settings.on(\"click\", function (e) {\n self._showSettings();\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", function () {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", function () {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", function () {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:file_name\", function () {\n self._refreshFileName();\n });\n this.listenTo(this.model, \"change:file_mode\", function () {\n self._refreshMode();\n });\n this.listenTo(this.model, \"change:file_size\", function () {\n self._refreshFileSize();\n });\n this.listenTo(this.model, \"remove\", function () {\n self.remove();\n });\n this.app.collection.on(\"reset\", function () {\n self.remove();\n });\n },\n\n render: function render() {\n this.$el.attr(\"id\", \"upload-row-\" + this.model.id);\n this.$file_name.html(_.escape(this.model.get(\"file_name\") || \"-\"));\n this.$file_desc.html(this.model.get(\"file_desc\") || \"Unavailable\");\n this.$file_size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n this.$status.removeClass().addClass(this.status_classes.init);\n },\n\n /** Remove view */\n remove: function remove() {\n // call the base class remove method\n Backbone.View.prototype.remove.apply(this);\n },\n\n //\n // handle model events\n //\n\n /** Refresh ready or not states */\n _refreshReady: function _refreshReady() {\n this.app.collection.each(function (model) {\n model.set(\"status\", model.get(\"file_size\") > 0 && \"ready\" || \"init\");\n });\n },\n\n /** Refresh mode and e.g. show/hide textarea field */\n _refreshMode: function _refreshMode() {\n var file_mode = this.model.get(\"file_mode\");\n if (file_mode == \"new\") {\n this.height = this.$el.height();\n this.$text.css({\n width: this.$el.width() - 16 + \"px\",\n top: this.$el.height() - 8 + \"px\"\n }).show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$text_content.val(\"\").trigger(\"keyup\");\n } else {\n this.$el.height(this.height);\n this.$text.hide();\n }\n },\n\n /** Refresh information */\n _refreshInfo: function _refreshInfo() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(\"Failed: \" + info).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage */\n _refreshPercentage: function _refreshPercentage() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n if (percentage != 0) {\n this.$progress_bar.css({ width: percentage + \"%\" });\n } else {\n this.$progress_bar.addClass(\"no-transition\");\n this.$progress_bar.css({ width: \"0%\" });\n this.$progress_bar[0].offsetHeight;\n this.$progress_bar.removeClass(\"no-transition\");\n }\n this.$percentage.html(percentage != 100 ? percentage + \"%\" : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function _refreshStatus() {\n var status = this.model.get(\"status\");\n this.$status.removeClass().addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status != \"running\");\n this.$text_content.attr(\"disabled\", !this.model.get(\"enabled\"));\n this.$el.removeClass(\"success danger warning\");\n if (status == \"running\" || status == \"ready\") {\n this.model.set(\"percentage\", 0);\n }\n this.$source.find(\".button\")[status == \"running\" ? \"addClass\" : \"removeClass\"](\"disabled\");\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.model.set(\"percentage\", 100);\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.model.set(\"percentage\", 0);\n this.$info_progress.hide();\n this.$info_text.show();\n } else {\n this.$info_progress.show();\n this.$info_text.hide();\n }\n },\n\n /** File name */\n _refreshFileName: function _refreshFileName() {\n this.$file_name.html(this.model.get(\"file_name\") || \"-\");\n },\n\n /** File size */\n _refreshFileSize: function _refreshFileSize() {\n this.$file_size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Show/hide ftp popup */\n _showFtp: function _showFtp() {\n if (!this.ftp.visible) {\n var self = this;\n this.ftp.empty();\n this.ftp.append(new _uploadFtp2.default({\n ftp_upload_site: this.app.ftp_upload_site,\n onchange: function onchange(ftp_file) {\n self.ftp.hide();\n if (self.model.get(\"status\") != \"running\" && ftp_file) {\n self.model.reset({\n file_mode: \"ftp\",\n file_name: ftp_file.path,\n file_size: ftp_file.size,\n file_path: ftp_file.path\n });\n self._refreshReady();\n }\n }\n }).$el);\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Show/hide settings popup */\n _showSettings: function _showSettings() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new _uploadSettings2.default(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** Template */\n _template: function _template() {\n return '
' + \"
\" + '
' + '
' + '
' + '
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
' + '' + \"
\" + \"
\" + \"
\" + \"
\" + '
' + \"
\" + \"
\" + '' + \"
\" + \"
\" + '' + \"
\" + \"
\" + '' + \"
\" + '
' + \"
\" + '
' + '
' + '
' + '' + '
0%
' + \"
\" + \"
\" + \"
\" + \"
\";\n }\n}); /** Renders the composite upload row view */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 147 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _collectionRow = __webpack_require__(148);\n\nvar _collectionRow2 = _interopRequireDefault(_collectionRow);\n\nvar _uploadFtp = __webpack_require__(32);\n\nvar _uploadFtp2 = _interopRequireDefault(_uploadFtp);\n\nvar _uploadExtension = __webpack_require__(33);\n\nvar _uploadExtension2 = _interopRequireDefault(_uploadExtension);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _listCollectionCreator = __webpack_require__(35);\n\nvar _listCollectionCreator2 = _interopRequireDefault(_listCollectionCreator);\n\n__webpack_require__(34);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Renders contents of the collection uploader */\nexports.default = Backbone.View.extend({\n // current upload size in bytes\n upload_size: 0,\n\n // contains upload row models\n collection: new _uploadModel2.default.Collection(),\n\n // keeps track of the current uploader state\n counter: {\n announce: 0,\n success: 0,\n error: 0,\n running: 0,\n reset: function reset() {\n this.announce = this.success = this.error = this.running = 0;\n }\n },\n\n initialize: function initialize(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ui_button = app.ui_button;\n this.ftp_upload_site = app.currentFtp();\n this.setElement(this._template());\n\n // append buttons to dom\n this.btnLocal = new _uiMisc2.default.Button({\n id: \"btn-local\",\n title: \"Choose local files\",\n onclick: function onclick() {\n self.uploadbox.select();\n },\n icon: \"fa fa-laptop\"\n });\n this.btnFtp = new _uiMisc2.default.Button({\n id: \"btn-ftp\",\n title: \"Choose FTP files\",\n onclick: function onclick() {\n self._eventFtp();\n },\n icon: \"fa fa-folder-open-o\"\n });\n this.btnCreate = new _uiMisc2.default.Button({\n id: \"btn-new\",\n title: \"Paste/Fetch data\",\n onclick: function onclick() {\n self._eventCreate();\n },\n icon: \"fa fa-edit\"\n });\n this.btnStart = new _uiMisc2.default.Button({\n id: \"btn-start\",\n title: \"Start\",\n onclick: function onclick() {\n self._eventStart();\n }\n });\n this.btnBuild = new _uiMisc2.default.Button({\n id: \"btn-build\",\n title: \"Build\",\n onclick: function onclick() {\n self._eventBuild();\n }\n });\n this.btnStop = new _uiMisc2.default.Button({\n id: \"btn-stop\",\n title: \"Pause\",\n onclick: function onclick() {\n self._eventStop();\n }\n });\n this.btnReset = new _uiMisc2.default.Button({\n id: \"btn-reset\",\n title: \"Reset\",\n onclick: function onclick() {\n self._eventReset();\n }\n });\n this.btnClose = new _uiMisc2.default.Button({\n id: \"btn-close\",\n title: \"Close\",\n onclick: function onclick() {\n self.app.modal.hide();\n }\n });\n _.each([this.btnLocal, this.btnFtp, this.btnCreate, this.btnStop, this.btnReset, this.btnStart, this.btnBuild, this.btnClose], function (button) {\n self.$(\".upload-buttons\").prepend(button.$el);\n });\n\n // file upload\n this.uploadbox = this.$(\".upload-box\").uploadbox({\n url: this.app.options.nginx_upload_path,\n announce: function announce(index, file) {\n self._eventAnnounce(index, file);\n },\n initialize: function initialize(index) {\n return self.app.toData([self.collection.get(index)], self.history_id);\n },\n progress: function progress(index, percentage) {\n self._eventProgress(index, percentage);\n },\n success: function success(index, message) {\n self._eventSuccess(index, message);\n },\n error: function error(index, message) {\n self._eventError(index, message);\n },\n complete: function complete() {\n self._eventComplete();\n },\n ondragover: function ondragover() {\n self.$(\".upload-box\").addClass(\"highlight\");\n },\n ondragleave: function ondragleave() {\n self.$(\".upload-box\").removeClass(\"highlight\");\n }\n });\n\n // add ftp file viewer\n this.ftp = new _uiPopover2.default.View({\n title: \"FTP files\",\n container: this.btnFtp.$el\n });\n\n // select extension\n this.select_extension = new _uiSelect2.default.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, function (ext) {\n return !ext.composite_files;\n }),\n value: this.options.default_extension,\n onchange: function onchange(extension) {\n self.updateExtension(extension);\n }\n });\n\n this.collectionType = \"list\";\n this.select_collection = new _uiSelect2.default.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-collection-type\"),\n data: [{ id: \"list\", text: \"List\" }, { id: \"paired\", text: \"Paired\" }, { id: \"list:paired\", text: \"List of Pairs\" }],\n value: \"list\",\n onchange: function onchange(collectionType) {\n self.updateCollectionType(collectionType);\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\").on(\"click\", function (e) {\n new _uploadExtension2.default({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n }).on(\"mousedown\", function (e) {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new _uiSelect2.default.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome,\n onchange: function onchange(genome) {\n self.updateGenome(genome);\n }\n });\n\n // events\n this.collection.on(\"remove\", function (model) {\n self._eventRemove(model);\n });\n this._updateScreen();\n },\n\n /** A new file has been dropped/selected through the uploadbox plugin */\n _eventAnnounce: function _eventAnnounce(index, file) {\n this.counter.announce++;\n var new_model = new _uploadModel2.default.Model({\n id: index,\n file_name: file.name,\n file_size: file.size,\n file_mode: file.mode || \"local\",\n file_path: file.path,\n file_data: file,\n extension: this.select_extension.value(),\n genome: this.select_genome.value()\n });\n this.collection.add(new_model);\n var upload_row = new _collectionRow2.default(this, { model: new_model });\n this.$(\".upload-table > tbody:first\").append(upload_row.$el);\n this._updateScreen();\n upload_row.render();\n },\n\n /** Progress */\n _eventProgress: function _eventProgress(index, percentage) {\n var it = this.collection.get(index);\n it.set(\"percentage\", percentage);\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(percentage, it.get(\"file_size\")));\n },\n\n /** Success */\n _eventSuccess: function _eventSuccess(index, message) {\n // var hdaId = message[\"outputs\"][0][\"id\"];\n var hids = _.pluck(message[\"outputs\"], \"hid\");\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"success\", hids: hids });\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(100, it.get(\"file_size\")));\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.success++;\n this._updateScreen();\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Error */\n _eventError: function _eventError(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"error\", info: message });\n this.ui_button.model.set({\n percentage: this._uploadPercentage(100, it.get(\"file_size\")),\n status: \"danger\"\n });\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.error++;\n this._updateScreen();\n },\n\n /** Queue is done */\n _eventComplete: function _eventComplete() {\n this.collection.each(function (model) {\n model.get(\"status\") == \"queued\" && model.set(\"status\", \"init\");\n });\n this.counter.running = 0;\n this._updateScreen();\n },\n\n _eventBuild: function _eventBuild() {\n var allHids = [];\n _.forEach(this.collection.models, function (upload) {\n allHids.push.apply(allHids, upload.get(\"hids\"));\n });\n var models = _.map(allHids, function (hid) {\n return Galaxy.currHistoryPanel.collection.getByHid(hid);\n });\n var selection = new Galaxy.currHistoryPanel.collection.constructor(models);\n // I'm building the selection wrong because I need to set this historyId directly.\n selection.historyId = Galaxy.currHistoryPanel.collection.historyId;\n Galaxy.currHistoryPanel.buildCollection(this.collectionType, selection, true);\n this.counter.running = 0;\n this._updateScreen();\n this._eventReset();\n this.app.modal.hide();\n },\n\n /** Remove model from upload list */\n _eventRemove: function _eventRemove(model) {\n var status = model.get(\"status\");\n if (status == \"success\") {\n this.counter.success--;\n } else if (status == \"error\") {\n this.counter.error--;\n } else {\n this.counter.announce--;\n }\n this.uploadbox.remove(model.id);\n this._updateScreen();\n },\n\n //\n // events triggered by this view\n //\n\n /** Show/hide ftp popup */\n _eventFtp: function _eventFtp() {\n if (!this.ftp.visible) {\n this.ftp.empty();\n var self = this;\n this.ftp.append(new _uploadFtp2.default({\n collection: this.collection,\n ftp_upload_site: this.ftp_upload_site,\n onadd: function onadd(ftp_file) {\n return self.uploadbox.add([{\n mode: \"ftp\",\n name: ftp_file.path,\n size: ftp_file.size,\n path: ftp_file.path\n }]);\n },\n onremove: function onremove(model_index) {\n self.collection.remove(model_index);\n }\n }).$el);\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Create a new file */\n _eventCreate: function _eventCreate() {\n this.uploadbox.add([{ name: \"New File\", size: 0, mode: \"new\" }]);\n },\n\n /** Start upload process */\n _eventStart: function _eventStart() {\n if (this.counter.announce == 0 || this.counter.running > 0) {\n return;\n }\n var self = this;\n this.upload_size = 0;\n this.upload_completed = 0;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\") {\n model.set(\"status\", \"queued\");\n self.upload_size += model.get(\"file_size\");\n }\n });\n this.ui_button.model.set({ percentage: 0, status: \"success\" });\n this.counter.running = this.counter.announce;\n this.history_id = this.app.currentHistory();\n this.uploadbox.start();\n this._updateScreen();\n },\n\n /** Pause upload process */\n _eventStop: function _eventStop() {\n if (this.counter.running > 0) {\n this.ui_button.model.set(\"status\", \"info\");\n $(\".upload-top-info\").html(\"Queue will pause after completing the current file...\");\n this.uploadbox.stop();\n }\n },\n\n /** Remove all */\n _eventReset: function _eventReset() {\n if (this.counter.running == 0) {\n this.collection.reset();\n this.counter.reset();\n this.uploadbox.reset();\n this.select_extension.value(this.options.default_extension);\n this.select_genome.value(this.options.default_genome);\n this.ui_button.model.set(\"percentage\", 0);\n this._updateScreen();\n }\n },\n\n /** Update extension for all models */\n updateExtension: function updateExtension(extension, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"extension\") == self.options.default_extension || !defaults_only)) {\n model.set(\"extension\", extension);\n }\n });\n },\n\n /** Update collection type */\n updateCollectionType: function updateCollectionType(collectionType) {\n var self = this;\n this.collectionType = collectionType;\n },\n\n /** Update genome for all models */\n updateGenome: function updateGenome(genome, defaults_only) {\n var self = this;\n this.collection.each(function (model) {\n if (model.get(\"status\") == \"init\" && (model.get(\"genome\") == self.options.default_genome || !defaults_only)) {\n model.set(\"genome\", genome);\n }\n });\n },\n\n /** Set screen */\n _updateScreen: function _updateScreen() {\n var message = \"\";\n if (this.counter.announce == 0) {\n if (this.uploadbox.compatible()) {\n message = \" \";\n } else {\n message = \"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.\";\n }\n } else {\n if (this.counter.running == 0) {\n message = \"You added \" + this.counter.announce + \" file(s) to the queue. Add more files or click 'Start' to proceed.\";\n } else {\n message = \"Please wait...\" + this.counter.announce + \" out of \" + this.counter.running + \" remaining.\";\n }\n }\n this.$(\".upload-top-info\").html(message);\n var enable_reset = this.counter.running == 0 && this.counter.announce + this.counter.success + this.counter.error > 0;\n var enable_start = this.counter.running == 0 && this.counter.announce > 0;\n var enable_build = this.counter.running == 0 && this.counter.announce == 0 && this.counter.success > 0 && this.counter.error == 0;\n var enable_sources = this.counter.running == 0;\n var show_table = this.counter.announce + this.counter.success + this.counter.error > 0;\n this.btnReset[enable_reset ? \"enable\" : \"disable\"]();\n this.btnStart[enable_start ? \"enable\" : \"disable\"]();\n this.btnStart.$el[enable_start ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnBuild[enable_build ? \"enable\" : \"disable\"]();\n this.btnBuild.$el[enable_build ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnStop[this.counter.running > 0 ? \"enable\" : \"disable\"]();\n this.btnLocal[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp[enable_sources ? \"enable\" : \"disable\"]();\n this.btnCreate[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp.$el[this.ftp_upload_site ? \"show\" : \"hide\"]();\n this.$(\".upload-table\")[show_table ? \"show\" : \"hide\"]();\n this.$(\".upload-helper\")[show_table ? \"hide\" : \"show\"]();\n },\n\n /** Calculate percentage of all queued uploads */\n _uploadPercentage: function _uploadPercentage(percentage, size) {\n return (this.upload_completed + percentage * size) / this.upload_size;\n },\n\n /** Template */\n _template: function _template() {\n return '
' + '
' + '
' + \"
\" + '
' + '
Drop files here
' + '
' + \"\" + \"
\" + \"
Name
\" + \"
Size
\" + \"
Status
\" + \"
\" + \"
\" + \"\" + \"\" + \"
\" + \"
\" + '\" + '
' + \"
\";\n }\n});\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 148 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uploadModel = __webpack_require__(16);\n\nvar _uploadModel2 = _interopRequireDefault(_uploadModel);\n\nvar _uploadSettings = __webpack_require__(31);\n\nvar _uploadSettings2 = _interopRequireDefault(_uploadSettings);\n\nvar _uiPopover = __webpack_require__(10);\n\nvar _uiPopover2 = _interopRequireDefault(_uiPopover);\n\nvar _uiSelect = __webpack_require__(13);\n\nvar _uiSelect2 = _interopRequireDefault(_uiSelect);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nexports.default = Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-icon-button fa fa-trash-o\",\n queued: \"upload-icon fa fa-spinner fa-spin\",\n running: \"upload-icon fa fa-spinner fa-spin\",\n success: \"upload-icon-button fa fa-check\",\n error: \"upload-icon-button fa fa-exclamation-triangle\"\n },\n\n initialize: function initialize(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template(options.model));\n this.$mode = this.$(\".upload-mode\");\n this.$title = this.$(\".upload-title-extended\");\n this.$text = this.$(\".upload-text\");\n this.$size = this.$(\".upload-size\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$symbol = this.$(\".upload-symbol\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // append popup to settings icon\n this.settings = new _uiPopover2.default.View({\n title: \"Upload configuration\",\n container: this.$(\".upload-settings\"),\n placement: \"bottom\"\n });\n\n // identify default genome and extension values\n var default_genome = this.app.select_genome.value();\n var default_extension = this.app.select_extension.value();\n\n // handle click event\n this.$symbol.on(\"click\", function () {\n self._removeRow();\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", function (e) {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", function () {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", function () {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", function () {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:file_size\", function () {\n self._refreshFileSize();\n });\n this.listenTo(this.model, \"remove\", function () {\n self.remove();\n });\n this.app.collection.on(\"reset\", function () {\n self.remove();\n });\n },\n\n render: function render() {\n var options = this.model.attributes;\n this.$title.html(_.escape(options.file_name));\n this.$size.html(_utils2.default.bytesToString(options.file_size));\n this.$mode.removeClass().addClass(\"upload-mode\").addClass(\"text-primary\");\n if (options.file_mode == \"new\") {\n this.$text.css({\n width: this.$el.width() - 16 + \"px\",\n top: this.$el.height() - 8 + \"px\"\n }).show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$mode.addClass(\"fa fa-edit\");\n } else if (options.file_mode == \"local\") {\n this.$mode.addClass(\"fa fa-laptop\");\n } else if (options.file_mode == \"ftp\") {\n this.$mode.addClass(\"fa fa-folder-open-o\");\n }\n },\n\n /** Refresh info text */\n _refreshInfo: function _refreshInfo() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(\"Failed: \" + info).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage status */\n _refreshPercentage: function _refreshPercentage() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n this.$progress_bar.css({ width: percentage + \"%\" });\n this.$percentage.html(percentage != 100 ? percentage + \"%\" : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function _refreshStatus() {\n var status = this.model.get(\"status\");\n this.$symbol.removeClass().addClass(\"upload-symbol\").addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status == \"init\");\n var enabled = this.model.get(\"enabled\");\n this.$text_content.attr(\"disabled\", !enabled);\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.$info_progress.hide();\n }\n },\n\n /** Refresh file size */\n _refreshFileSize: function _refreshFileSize() {\n this.$size.html(_utils2.default.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Remove row */\n _removeRow: function _removeRow() {\n if ([\"init\", \"success\", \"error\"].indexOf(this.model.get(\"status\")) !== -1) {\n this.app.collection.remove(this.model);\n }\n },\n\n /** Attach file info popup */\n _showSettings: function _showSettings() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new _uploadSettings2.default(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** View template */\n _template: function _template(options) {\n return \"
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
\";\n }\n}); /** Renders the collection uploader rows */\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 149 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = {\n tool: \"fa-wrench\",\n data_input: \"fa-file-o\",\n data_collection_input: \"fa-folder-o\",\n subworkflow: \"fa-sitemap fa-rotate-270\",\n pause: \"fa-pause\"\n};\n\n/***/ }),\n/* 150 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _optionsMenu = __webpack_require__(151);\n\nvar _optionsMenu2 = _interopRequireDefault(_optionsMenu);\n\nvar _historyViewEditCurrent = __webpack_require__(152);\n\nvar _historyViewEditCurrent2 = _interopRequireDefault(_historyViewEditCurrent);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** the right hand panel in the analysis page that shows the current history */\nvar HistoryPanel = Backbone.View.extend({\n initialize: function initialize(page, options) {\n var self = this;\n this.userIsAnonymous = Galaxy.user.isAnonymous();\n this.allow_user_dataset_purge = options.config.allow_user_dataset_purge;\n this.root = options.root;\n\n // view of the current history\n this.historyView = new _historyViewEditCurrent2.default.CurrentHistoryView({\n className: _historyViewEditCurrent2.default.CurrentHistoryView.prototype.className + \" middle\",\n purgeAllowed: this.allow_user_dataset_purge,\n linkTarget: \"galaxy_main\"\n });\n\n // add history panel to Galaxy object\n Galaxy.currHistoryPanel = this.historyView;\n Galaxy.currHistoryPanel.listenToGalaxy(Galaxy);\n\n // build buttons\n this.buttonRefresh = new _uiMisc2.default.ButtonLink({\n id: \"history-refresh-button\",\n title: \"Refresh history\",\n cls: \"panel-header-button\",\n icon: \"fa fa-refresh\",\n onclick: function onclick() {\n self.historyView.loadCurrentHistory();\n }\n });\n this.buttonOptions = new _uiMisc2.default.ButtonLink({\n id: \"history-options-button\",\n title: \"History options\",\n cls: \"panel-header-button\",\n target: \"galaxy_main\",\n icon: \"fa fa-cog\",\n href: this.root + \"root/history_options\"\n });\n this.buttonViewMulti = new _uiMisc2.default.ButtonLink({\n id: \"history-view-multi-button\",\n title: \"View all histories\",\n cls: \"panel-header-button\",\n icon: \"fa fa-columns\",\n href: this.root + \"history/view_multiple\"\n });\n\n // define components\n this.model = new Backbone.Model({\n cls: \"history-right-panel\",\n title: (0, _localization2.default)(\"History\"),\n buttons: [this.buttonRefresh, this.buttonOptions, this.buttonViewMulti]\n });\n\n // build body template and connect history view\n this.setElement(this._template());\n this.historyView.setElement(this.$el);\n this.historyView.connectToQuotaMeter(Galaxy.quotaMeter);\n this.historyView.loadCurrentHistory();\n\n // fetch to update the quota meter adding 'current' for any anon-user's id\n Galaxy.listenTo(this.historyView, \"history-size-change\", function () {\n Galaxy.user.fetch({\n url: Galaxy.user.urlRoot() + \"/\" + (Galaxy.user.id || \"current\")\n });\n });\n },\n\n render: function render() {\n this.optionsMenu = (0, _optionsMenu2.default)(this.buttonOptions.$el, {\n anonymous: this.userIsAnonymous,\n purgeAllowed: this.allow_user_dataset_purge,\n root: this.root\n });\n this.buttonViewMulti.$el[!this.userIsAnonymous ? \"show\" : \"hide\"]();\n },\n\n /** add history view div */\n _template: function _template(data) {\n return [''].join(\"\");\n },\n\n toString: function toString() {\n return \"historyPanel\";\n }\n});\n\nexports.default = HistoryPanel;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 151 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function($, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _popupMenu = __webpack_require__(27);\n\nvar _popupMenu2 = _interopRequireDefault(_popupMenu);\n\nvar _copyDialog = __webpack_require__(78);\n\nvar _copyDialog2 = _interopRequireDefault(_copyDialog);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nvar _webhooks = __webpack_require__(17);\n\nvar _webhooks2 = _interopRequireDefault(_webhooks);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// ============================================================================\nvar menu = [{\n html: (0, _localization2.default)(\"History Lists\"),\n header: true\n}, {\n html: (0, _localization2.default)(\"Saved Histories\"),\n href: \"histories/list\",\n target: \"_top\"\n}, {\n html: (0, _localization2.default)(\"Histories Shared with Me\"),\n href: \"histories/list_shared\",\n target: \"_top\"\n}, {\n html: (0, _localization2.default)(\"Current History\"),\n header: true,\n anon: true\n}, {\n html: (0, _localization2.default)(\"Create New\"),\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.createNewHistory();\n }\n }\n}, {\n html: (0, _localization2.default)(\"Copy History\"),\n func: function func() {\n (0, _copyDialog2.default)(Galaxy.currHistoryPanel.model).done(function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n}, {\n html: (0, _localization2.default)(\"Share or Publish\"),\n href: \"history/sharing\"\n}, {\n html: (0, _localization2.default)(\"Show Structure\"),\n href: \"history/display_structured\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Extract Workflow\"),\n href: \"workflow/build_from_current_history\"\n}, {\n html: (0, _localization2.default)(\"Delete\"),\n anon: true,\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really delete the current history?\"))) {\n Galaxy.currHistoryPanel.model._delete().done(function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Delete Permanently\"),\n purge: true,\n anon: true,\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really delete the current history permanently? This cannot be undone.\"))) {\n Galaxy.currHistoryPanel.model.purge().done(function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Dataset Actions\"),\n header: true,\n anon: true\n}, {\n html: (0, _localization2.default)(\"Copy Datasets\"),\n href: \"dataset/copy_datasets\"\n}, {\n html: (0, _localization2.default)(\"Dataset Security\"),\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel && Galaxy.router) {\n Galaxy.router.push(\"/histories/permissions?id=\" + Galaxy.currHistoryPanel.model.id);\n }\n }\n}, {\n html: (0, _localization2.default)(\"Resume Paused Jobs\"),\n href: \"history/resume_paused_jobs?current=True\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Collapse Expanded Datasets\"),\n func: function func() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.collapseAll();\n }\n }\n}, {\n html: (0, _localization2.default)(\"Unhide Hidden Datasets\"),\n anon: true,\n func: function func() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really unhide all hidden datasets?\"))) {\n $.post(Galaxy.root + \"history/adjust_hidden\", { user_action: \"unhide\" }, function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Delete Hidden Datasets\"),\n anon: true,\n func: function func() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm((0, _localization2.default)(\"Really delete all hidden datasets?\"))) {\n $.post(Galaxy.root + \"history/adjust_hidden\", { user_action: \"delete\" }, function () {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n}, {\n html: (0, _localization2.default)(\"Purge Deleted Datasets\"),\n confirm: (0, _localization2.default)(\"Really delete all deleted datasets permanently? This cannot be undone.\"),\n href: \"history/purge_deleted_datasets\",\n purge: true,\n anon: true\n}, {\n html: (0, _localization2.default)(\"Downloads\"),\n header: true\n}, {\n html: (0, _localization2.default)(\"Export Tool Citations\"),\n href: \"history/citations\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Export History to File\"),\n href: \"history/export_archive?preview=True\",\n anon: true\n}, {\n html: (0, _localization2.default)(\"Other Actions\"),\n header: true\n}, {\n html: (0, _localization2.default)(\"Import from File\"),\n href: \"history/import_archive\"\n}];\n\n// Webhooks\n_webhooks2.default.add({\n url: \"api/webhooks/history-menu/all\",\n async: false, // (hypothetically) slows down the performance\n callback: function callback(webhooks) {\n var webhooks_menu = [];\n\n $.each(webhooks.models, function (index, model) {\n var webhook = model.toJSON();\n if (webhook.activate) {\n webhooks_menu.push({\n html: (0, _localization2.default)(webhook.config.title),\n // func: function() {},\n anon: true\n });\n }\n });\n\n if (webhooks_menu.length > 0) {\n webhooks_menu.unshift({\n html: (0, _localization2.default)(\"Webhooks\"),\n header: true\n });\n $.merge(menu, webhooks_menu);\n }\n }\n});\n\nfunction buildMenu(isAnon, purgeAllowed, urlRoot) {\n return _.clone(menu).filter(function (menuOption) {\n if (isAnon && !menuOption.anon) {\n return false;\n }\n if (!purgeAllowed && menuOption.purge) {\n return false;\n }\n\n //TODO:?? hard-coded galaxy_main\n if (menuOption.href) {\n menuOption.href = urlRoot + menuOption.href;\n menuOption.target = menuOption.target || \"galaxy_main\";\n }\n\n if (menuOption.confirm) {\n menuOption.func = function () {\n if (confirm(menuOption.confirm)) {\n galaxy_main.location = menuOption.href;\n }\n };\n }\n return true;\n });\n}\n\nvar create = function create($button, options) {\n options = options || {};\n var isAnon = options.anonymous === undefined ? true : options.anonymous;\n var purgeAllowed = options.purgeAllowed || false;\n var menu = buildMenu(isAnon, purgeAllowed, Galaxy.root);\n //console.debug( 'menu:', menu );\n return new _popupMenu2.default($button, menu);\n};\n\n// ============================================================================\nexports.default = create;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 152 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, $, jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _historyModel = __webpack_require__(38);\n\nvar _historyModel2 = _interopRequireDefault(_historyModel);\n\nvar _historyViewEdit = __webpack_require__(154);\n\nvar _historyViewEdit2 = _interopRequireDefault(_historyViewEdit);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// ============================================================================\n/** session storage for history panel preferences (and to maintain state)\n */\nvar HistoryViewPrefs = _baseMvc2.default.SessionStorageModel.extend(\n/** @lends HistoryViewPrefs.prototype */{\n defaults: {\n /** should the tags editor be shown or hidden initially? */\n tagsEditorShown: false,\n /** should the annotation editor be shown or hidden initially? */\n annotationEditorShown: false,\n ///** what is the currently focused content (dataset or collection) in the current history?\n // * (the history panel will highlight and scroll to the focused content view)\n // */\n //focusedContentId : null\n /** Current scroll position */\n scrollPosition: 0\n },\n toString: function toString() {\n return \"HistoryViewPrefs(\" + JSON.stringify(this.toJSON()) + \")\";\n }\n});\n\n/** key string to store panel prefs (made accessible on class so you can access sessionStorage directly) */\nHistoryViewPrefs.storageKey = function storageKey() {\n return \"history-panel\";\n};\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = _historyViewEdit2.default.HistoryViewEdit;\n// used in root/index.mako\n/** @class View/Controller for the user's current history model as used in the history\n * panel (current right hand panel) of the analysis page.\n *\n * The only history panel that:\n * will poll for updates.\n * displays datasets in reverse hid order.\n */\nvar CurrentHistoryView = _super.extend(\n/** @lends CurrentHistoryView.prototype */{\n className: _super.prototype.className + \" current-history-panel\",\n\n /** override to use drilldown (and not foldout) for how collections are displayed */\n HDCAViewClass: _super.prototype.HDCAViewClass.extend({\n foldoutStyle: \"drilldown\"\n }),\n\n emptyMsg: [(0, _localization2.default)(\"This history is empty\"), \". \", (0, _localization2.default)(\"You can \"), '', (0, _localization2.default)(\"load your own data\"), \"\", (0, _localization2.default)(\" or \"), '', (0, _localization2.default)(\"get data from an external source\"), \"\"].join(\"\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events */\n initialize: function initialize(attributes) {\n attributes = attributes || {};\n\n // ---- persistent preferences\n /** maintain state / preferences over page loads */\n this.preferences = new HistoryViewPrefs(_.extend({\n id: HistoryViewPrefs.storageKey()\n }, _.pick(attributes, _.keys(HistoryViewPrefs.prototype.defaults))));\n\n _super.prototype.initialize.call(this, attributes);\n\n /** sub-views that will overlay this panel (collections) */\n this.panelStack = [];\n\n /** id of currently focused content */\n this.currentContentId = attributes.currentContentId || null;\n //NOTE: purposely not sent to localstorage since panel recreation roughly lines up with a reset of this value\n },\n\n /** Override to cache the current scroll position with a listener */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n\n var panel = this;\n // reset scroll position when there's a new history\n this.on(\"new-model\", function () {\n panel.preferences.set(\"scrollPosition\", 0);\n });\n },\n\n // ------------------------------------------------------------------------ loading history/item models\n // TODO: next three more appropriate moved to the app level\n /** (re-)loads the user's current history & contents w/ details */\n loadCurrentHistory: function loadCurrentHistory() {\n return this.loadHistory(null, {\n url: Galaxy.root + \"history/current_history_json\"\n });\n },\n\n /** loads a history & contents w/ details and makes them the current history */\n switchToHistory: function switchToHistory(historyId, attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", (0, _localization2.default)(\"You must be logged in to switch histories\"), (0, _localization2.default)(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(historyId, {\n url: Galaxy.root + \"history/set_as_current?id=\" + historyId\n });\n },\n\n /** creates a new history on the server and sets it as the user's current history */\n createNewHistory: function createNewHistory(attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", (0, _localization2.default)(\"You must be logged in to create histories\"), (0, _localization2.default)(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(null, {\n url: Galaxy.root + \"history/create_new_current\"\n });\n },\n\n /** release/free/shutdown old models and set up panel for new models */\n setModel: function setModel(model, attributes, render) {\n _super.prototype.setModel.call(this, model, attributes, render);\n if (this.model && this.model.id) {\n this.log(\"checking for updates\");\n this.model.checkForUpdates();\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ history/content event listening\n /** listening for history events */\n _setUpModelListeners: function _setUpModelListeners() {\n _super.prototype._setUpModelListeners.call(this);\n // re-broadcast any model change events so that listeners don't have to re-bind to each history\n return this.listenTo(this.model, {\n \"change:nice_size change:size\": function changeNice_sizeChangeSize() {\n this.trigger(\"history-size-change\", this, this.model, arguments);\n },\n \"change:id\": function changeId() {\n this.once(\"loading-done\", function () {\n this.model.checkForUpdates();\n });\n }\n });\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n _super.prototype._setUpCollectionListeners.call(this);\n // if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,\n // then: remove it from the collection if the panel is set to NOT show hidden datasets\n this.listenTo(this.collection, \"state:ready\", function (model, newState, oldState) {\n if (!model.get(\"visible\") && !this.collection.storage.includeHidden()) {\n this.removeItemView(model);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** override to add a handler to capture the scroll position when the parent scrolls */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n // console.log( '_setUpBehaviors', this.$scrollContainer( $where ).get(0), this.$list( $where ) );\n // we need to call this in _setUpBehaviors which is called after render since the $el\n // may not be attached to $el.parent and $scrollContainer() may not work\n var panel = this;\n _super.prototype._setUpBehaviors.call(panel, $where);\n\n // cache the handler to remove and re-add so we don't pile up the handlers\n if (!this._debouncedScrollCaptureHandler) {\n this._debouncedScrollCaptureHandler = _.debounce(function scrollCapture() {\n // cache the scroll position (only if visible)\n if (panel.$el.is(\":visible\")) {\n panel.preferences.set(\"scrollPosition\", $(this).scrollTop());\n }\n }, 40);\n }\n\n panel.$scrollContainer($where).off(\"scroll\", this._debouncedScrollCaptureHandler).on(\"scroll\", this._debouncedScrollCaptureHandler);\n return panel;\n },\n\n /** In this override, handle null models and move the search input to the top */\n _buildNewRender: function _buildNewRender() {\n if (!this.model) {\n return $();\n }\n var $newRender = _super.prototype._buildNewRender.call(this);\n $newRender.find(\".search\").prependTo($newRender.find(\"> .controls\"));\n this._renderQuotaMessage($newRender);\n return $newRender;\n },\n\n /** render the message displayed when a user is over quota and can't run jobs */\n _renderQuotaMessage: function _renderQuotaMessage($whereTo) {\n $whereTo = $whereTo || this.$el;\n return $(this.templates.quotaMsg({}, this)).prependTo($whereTo.find(\".messages\"));\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderTags: function _renderTags($where) {\n var panel = this;\n // render tags and show/hide based on preferences\n _super.prototype._renderTags.call(panel, $where);\n if (panel.preferences.get(\"tagsEditorShown\")) {\n panel.tagsEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(panel.tagsEditor, \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\", function (tagsEditor) {\n panel.preferences.set(\"tagsEditorShown\", tagsEditor.hidden);\n });\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderAnnotation: function _renderAnnotation($where) {\n var panel = this;\n // render annotation and show/hide based on preferences\n _super.prototype._renderAnnotation.call(panel, $where);\n if (panel.preferences.get(\"annotationEditorShown\")) {\n panel.annotationEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(panel.annotationEditor, \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\", function (annotationEditor) {\n panel.preferences.set(\"annotationEditorShown\", annotationEditor.hidden);\n });\n },\n\n /** Override to scroll to cached position (in prefs) after swapping */\n _swapNewRender: function _swapNewRender($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n var panel = this;\n _.delay(function () {\n var pos = panel.preferences.get(\"scrollPosition\");\n if (pos) {\n panel.scrollTo(pos, 0);\n }\n }, 10);\n //TODO: is this enough of a delay on larger histories?\n\n return this;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** Override to add the current-content highlight class to currentContentId's view */\n _attachItems: function _attachItems($whereTo) {\n _super.prototype._attachItems.call(this, $whereTo);\n var panel = this;\n if (panel.currentContentId) {\n panel._setCurrentContentById(panel.currentContentId);\n }\n return this;\n },\n\n /** Override to remove any drill down panels */\n addItemView: function addItemView(model, collection, options) {\n var view = _super.prototype.addItemView.call(this, model, collection, options);\n if (!view) {\n return view;\n }\n if (this.panelStack.length) {\n return this._collapseDrilldownPanel();\n }\n return view;\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n // use pub-sub to: handle drilldown expansion and collapse\n return panel.listenTo(view, {\n \"expanded:drilldown\": function expandedDrilldown(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function collapsedDrilldown(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n },\n\n /** display 'current content': add a visible highlight and store the id of a content item */\n setCurrentContent: function setCurrentContent(view) {\n this.$(\".history-content.current-content\").removeClass(\"current-content\");\n if (view) {\n view.$el.addClass(\"current-content\");\n this.currentContentId = view.model.id;\n } else {\n this.currentContentId = null;\n }\n },\n\n /** find the view with the id and then call setCurrentContent on it */\n _setCurrentContentById: function _setCurrentContentById(id) {\n var view = this.viewFromModelId(id) || null;\n this.setCurrentContent(view);\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function _expandDrilldownPanel(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$controls().add(this.$list()).hide();\n drilldown.parentName = this.model.get(\"name\");\n drilldown.delegateEvents().render().$el.appendTo(this.$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function _collapseDrilldownPanel(drilldown) {\n this.panelStack.pop();\n //TODO: MEM: free the panel\n this.$controls().add(this.$list()).show();\n },\n\n // ........................................................................ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n // the two links in the empty message\n \"click .uploader-link\": function clickUploaderLink(ev) {\n Galaxy.upload.show(ev);\n },\n \"click .get-data-link\": function clickGetDataLink(ev) {\n var $toolMenu = $(\".toolMenuContainer\");\n $toolMenu.parent().scrollTop(0);\n $toolMenu.find('span:contains(\"Get Data\")').click();\n }\n }),\n\n // ........................................................................ external objects/MVC\n listenToGalaxy: function listenToGalaxy(galaxy) {\n this.listenTo(galaxy, {\n // when the galaxy_main iframe is loaded with a new page,\n // compare the url to the following list and if there's a match\n // pull the id from url and indicate in the history view that\n // the dataset with that id is the 'current'ly active dataset\n \"center-frame:load\": function centerFrameLoad(data) {\n var pathToMatch = data.fullpath;\n var hdaId = null;\n var useToURLRegexMap = {\n display: /datasets\\/([a-f0-9]+)\\/display/,\n edit: /datasets\\/([a-f0-9]+)\\/edit/,\n report_error: /dataset\\/errors\\?id=([a-f0-9]+)/,\n rerun: /tool_runner\\/rerun\\?id=([a-f0-9]+)/,\n show_params: /datasets\\/([a-f0-9]+)\\/show_params/\n // no great way to do this here? (leave it in the dataset event handlers above?)\n // 'visualization' : 'visualization',\n };\n _.find(useToURLRegexMap, function (regex, use) {\n // grab the more specific match result (1), save, and use it as the find flag\n hdaId = _.result(pathToMatch.match(regex), 1);\n return hdaId;\n });\n // need to type mangle to go from web route to history contents\n this._setCurrentContentById(hdaId ? \"dataset-\" + hdaId : null);\n },\n // when the center panel is given a new view, clear the current indicator\n \"center-panel:load\": function centerPanelLoad(view) {\n this._setCurrentContentById();\n }\n });\n },\n\n //TODO: remove quota meter from panel and remove this\n /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */\n connectToQuotaMeter: function connectToQuotaMeter(quotaMeter) {\n if (!quotaMeter) {\n return this;\n }\n // show/hide the 'over quota message' in the history when the meter tells it to\n this.listenTo(quotaMeter, \"quota:over\", this.showQuotaMessage);\n this.listenTo(quotaMeter, \"quota:under\", this.hideQuotaMessage);\n\n // having to add this to handle re-render of hview while overquota (the above do not fire)\n this.on(\"rendered rendered:initial\", function () {\n if (quotaMeter && quotaMeter.isOverQuota()) {\n this.showQuotaMessage();\n }\n });\n return this;\n },\n\n /** Override to preserve the quota message */\n clearMessages: function clearMessages(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target = $target.not(\".quota-message\");\n $target.fadeOut(this.fxSpeed, function () {\n $(this).remove();\n });\n return this;\n },\n\n /** Show the over quota message (which happens to be in the history panel).\n */\n showQuotaMessage: function showQuotaMessage() {\n var $msg = this.$(\".quota-message\");\n if ($msg.is(\":hidden\")) {\n $msg.slideDown(this.fxSpeed);\n }\n },\n\n /** Hide the over quota message (which happens to be in the history panel).\n */\n hideQuotaMessage: function hideQuotaMessage() {\n var $msg = this.$(\".quota-message\");\n if (!$msg.is(\":hidden\")) {\n $msg.slideUp(this.fxSpeed);\n }\n },\n\n // ........................................................................ options menu\n //TODO: remove to batch\n /** unhide any hidden datasets */\n unhideHidden: function unhideHidden() {\n var self = this;\n if (confirm((0, _localization2.default)(\"Really unhide all hidden datasets?\"))) {\n // get all hidden, regardless of deleted/purged\n return self.model.contents._filterAndUpdate({ visible: false, deleted: \"\", purged: \"\" }, { visible: true }).done(function () {\n // TODO: would be better to render these as they're unhidden instead of all at once\n if (!self.model.contents.includeHidden) {\n self.renderItems();\n }\n });\n }\n return jQuery.when();\n },\n\n /** delete any hidden datasets */\n deleteHidden: function deleteHidden() {\n var self = this;\n if (confirm((0, _localization2.default)(\"Really delete all hidden datasets?\"))) {\n return self.model.contents._filterAndUpdate(\n // get all hidden, regardless of deleted/purged\n { visible: false, deleted: \"\", purged: \"\" },\n // both delete *and* unhide them\n { deleted: true, visible: true });\n }\n return jQuery.when();\n },\n\n /** Return a string rep of the history */\n toString: function toString() {\n return \"CurrentHistoryView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nCurrentHistoryView.prototype.templates = function () {\n var quotaMsgTemplate = _baseMvc2.default.wrapTemplate(['
', (0, _localization2.default)(\"You are over your disk quota\"), \". \", (0, _localization2.default)(\"Tool execution is on hold until your disk usage drops below your allocated quota\"), \".\", \"
\"], \"history\");\n return _.extend(_.clone(_super.prototype.templates), {\n quotaMsg: quotaMsgTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n CurrentHistoryView: CurrentHistoryView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 153 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if (\"value\" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n//ASSUMES: jquery\n//=============================================================================\n/** @class AjaxQueue\n * Class that allows queueing functions that return jQuery promises (such\n * as ajax calls). Each function waits for the previous to complete before\n * being called\n *\n * @constructor accepts a list of functions and automatically begins\n * processing them\n */\nvar AjaxQueue = function () {\n function AjaxQueue(initialFunctions) {\n _classCallCheck(this, AjaxQueue);\n\n /** the main deferred for the entire queue - note: also sends notifications of progress */\n this.deferred = jQuery.Deferred();\n /** the queue array of functions */\n this.queue = [];\n /** cache the response from each deferred call - error or success */\n this.responses = [];\n /** total number of fn's to process */\n this.numToProcess = 0;\n /** is the queue processing/waiting for any calls to return? */\n this.running = false;\n\n this.init(initialFunctions || []);\n this.start();\n }\n\n /** add all fns in initialFunctions (if any) to the queue */\n\n\n _createClass(AjaxQueue, [{\n key: \"init\",\n value: function init(initialFunctions) {\n var _this = this;\n\n initialFunctions.forEach(function (fn) {\n _this.add(fn);\n });\n }\n }, {\n key: \"add\",\n value: function add(fn) {\n var _this2 = this;\n\n var index = this.queue.length;\n this.numToProcess += 1;\n\n this.queue.push(function () {\n var fnIndex = index;\n var xhr = fn();\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(function (response) {\n _this2.deferred.notify({\n curr: fnIndex,\n total: _this2.numToProcess,\n response: response\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(function (response) {\n _this2.responses.push(response);\n if (_this2.queue.length) {\n _this2.queue.shift()();\n } else {\n _this2.stop();\n }\n });\n });\n return this;\n }\n }, {\n key: \"start\",\n value: function start() {\n if (this.queue.length) {\n this.running = true;\n this.queue.shift()();\n }\n return this;\n }\n\n /** stop the queue\n * @param {boolean} causeFail cause an error/fail on the main deferred\n * @param {String} msg message to send when rejecting the main deferred\n */\n\n }, {\n key: \"stop\",\n value: function stop(causeFail, msg) {\n //TODO: doesn't abort current call\n this.running = false;\n this.queue = [];\n if (causeFail) {\n //TODO: spliced args instead\n this.deferred.reject(msg);\n } else {\n this.deferred.resolve(this.responses);\n }\n this.numToProcess = 0;\n this.deferred = jQuery.Deferred();\n return this;\n }\n\n // only a handful of the deferred interface for now - possible YAGNI\n /** implement done from the jq deferred interface */\n\n }, {\n key: \"done\",\n value: function done(fn) {\n return this.deferred.done(fn);\n }\n\n /** implement fail from the jq deferred interface */\n\n }, {\n key: \"fail\",\n value: function fail(fn) {\n return this.deferred.fail(fn);\n }\n\n /** implement always from the jq deferred interface */\n\n }, {\n key: \"always\",\n value: function always(fn) {\n return this.deferred.always(fn);\n }\n\n /** implement progress from the jq deferred interface */\n\n }, {\n key: \"progress\",\n value: function progress(fn) {\n return this.deferred.progress(fn);\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n\n }], [{\n key: \"create\",\n value: function create(initialFunctions) {\n return new AjaxQueue(initialFunctions).deferred;\n }\n }]);\n\n return AjaxQueue;\n}();\n\n//=============================================================================\n/** @class NamedAjaxQueue\n * @augments AjaxQueue\n * Allows associating a name with a deferring fn and prevents adding deferring\n * fns if the name has already been used. Useful to prevent build up of duplicate\n * async calls.\n * Both the array initialFunctions sent to constructor and any added later with\n * add() should be objects (NOT functions) of the form:\n * { name: some unique id,\n * fn: the deferring fn or ajax call }\n */\n\n\nvar NamedAjaxQueue = function (_AjaxQueue) {\n _inherits(NamedAjaxQueue, _AjaxQueue);\n\n function NamedAjaxQueue(initialFunctions) {\n _classCallCheck(this, NamedAjaxQueue);\n\n var _this3 = _possibleConstructorReturn(this, (NamedAjaxQueue.__proto__ || Object.getPrototypeOf(NamedAjaxQueue)).call(this, initialFunctions));\n\n _this3.names = {};\n return _this3;\n }\n\n /** add the obj.fn to the queue if obj.name hasn't been used before */\n\n\n _createClass(NamedAjaxQueue, [{\n key: \"add\",\n value: function add(obj) {\n if (!(obj.hasOwnProperty(\"name\") && obj.hasOwnProperty(\"fn\"))) {\n throw new Error(\"NamedAjaxQueue.add requires an object with both \\\"name\\\" and \\\"fn\\\": \" + JSON.stringify(obj));\n }\n if (this.names.hasOwnProperty(obj.name)) {\n //console.warn( 'name has been used:', obj.name );\n return;\n }\n this.names[obj.name] = true;\n return _get(NamedAjaxQueue.prototype.__proto__ || Object.getPrototypeOf(NamedAjaxQueue.prototype), \"add\", this).call(this, obj.fn);\n }\n }, {\n key: \"clear\",\n value: function clear() {\n this.names = {};\n return this;\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n\n }], [{\n key: \"create\",\n value: function create(initialFunctions) {\n return new NamedAjaxQueue(initialFunctions).deferred;\n }\n }]);\n\n return NamedAjaxQueue;\n}(AjaxQueue);\n\n//=============================================================================\n\n\nexports.default = {\n AjaxQueue: AjaxQueue,\n NamedAjaxQueue: NamedAjaxQueue\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n\n/***/ }),\n/* 154 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(jQuery, _, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _historyView = __webpack_require__(155);\n\nvar _historyView2 = _interopRequireDefault(_historyView);\n\nvar _historyContents = __webpack_require__(39);\n\nvar _historyContents2 = _interopRequireDefault(_historyContents);\n\nvar _states = __webpack_require__(11);\n\nvar _states2 = _interopRequireDefault(_states);\n\nvar _hdaModel = __webpack_require__(81);\n\nvar _hdaModel2 = _interopRequireDefault(_hdaModel);\n\nvar _hdaLiEdit = __webpack_require__(157);\n\nvar _hdaLiEdit2 = _interopRequireDefault(_hdaLiEdit);\n\nvar _hdcaLiEdit = __webpack_require__(158);\n\nvar _hdcaLiEdit2 = _interopRequireDefault(_hdcaLiEdit);\n\nvar _tag = __webpack_require__(22);\n\nvar _tag2 = _interopRequireDefault(_tag);\n\nvar _annotation = __webpack_require__(89);\n\nvar _annotation2 = _interopRequireDefault(_annotation);\n\nvar _listCollectionCreator = __webpack_require__(35);\n\nvar _listCollectionCreator2 = _interopRequireDefault(_listCollectionCreator);\n\nvar _pairCollectionCreator = __webpack_require__(161);\n\nvar _pairCollectionCreator2 = _interopRequireDefault(_pairCollectionCreator);\n\nvar _listOfPairsCollectionCreator = __webpack_require__(162);\n\nvar _listOfPairsCollectionCreator2 = _interopRequireDefault(_listOfPairsCollectionCreator);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _popupMenu = __webpack_require__(27);\n\nvar _popupMenu2 = _interopRequireDefault(_popupMenu);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(15);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = _historyView2.default.HistoryView;\n// base class for history-view-edit-current and used as-is in history/view.mako\n/** @class Editable View/Controller for the history model.\n *\n * Allows:\n * (everything HistoryView allows)\n * changing the name\n * displaying and editing tags and annotations\n * multi-selection and operations on mulitple content items\n */\nvar HistoryViewEdit = _super.extend(\n/** @lends HistoryViewEdit.prototype */{\n /** class to use for constructing the HistoryDatasetAssociation views */\n HDAViewClass: _hdaLiEdit2.default.HDAListItemEdit,\n /** class to use for constructing the HistoryDatasetCollectionAssociation views */\n HDCAViewClass: _hdcaLiEdit2.default.HDCAListItemEdit,\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes\n */\n initialize: function initialize(attributes) {\n attributes = attributes || {};\n _super.prototype.initialize.call(this, attributes);\n\n // ---- set up instance vars\n /** editor for tags - sub-view */\n this.tagsEditor = null;\n\n /** enable drag and drop - sub-view */\n this.dragItems = true;\n\n /** editor for annotations - sub-view */\n this.annotationEditor = null;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n // states/modes the panel can be in\n /** is the panel currently showing the dataset selection controls? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n },\n\n /** Override to handle history as drag-drop target */\n _setUpListeners: function _setUpListeners() {\n _super.prototype._setUpListeners.call(this);\n return this.on({\n \"droptarget:drop\": function droptargetDrop(ev, data) {\n // process whatever was dropped and re-hide the drop target\n this.dataDropped(data);\n this.dropTargetOff();\n },\n \"view:attached view:removed\": function viewAttachedViewRemoved() {\n this._renderCounts();\n },\n \"search:loading-progress\": this._renderSearchProgress,\n \"search:searching\": this._renderSearchFindings\n });\n },\n\n // ------------------------------------------------------------------------ listeners\n /** listening for history and HDA events */\n _setUpModelListeners: function _setUpModelListeners() {\n _super.prototype._setUpModelListeners.call(this);\n this.listenTo(this.model, \"change:size\", this.updateHistoryDiskSize);\n return this;\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n _super.prototype._setUpCollectionListeners.call(this);\n this.listenTo(this.collection, {\n \"change:deleted\": this._handleItemDeletedChange,\n \"change:visible\": this._handleItemVisibleChange,\n \"change:purged\": function changePurged(model) {\n // hafta get the new nice-size w/o the purged model\n this.model.fetch();\n },\n // loading indicators for deleted/hidden\n \"fetching-deleted\": function fetchingDeleted(collection) {\n this.$(\"> .controls .deleted-count\").html(\"\" + (0, _localization2.default)(\"loading...\") + \"\");\n },\n \"fetching-hidden\": function fetchingHidden(collection) {\n this.$(\"> .controls .hidden-count\").html(\"\" + (0, _localization2.default)(\"loading...\") + \"\");\n },\n \"fetching-deleted-done fetching-hidden-done\": this._renderCounts\n });\n return this;\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** In this override, add tag and annotation editors and a btn to toggle the selectors */\n _buildNewRender: function _buildNewRender() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = _super.prototype._buildNewRender.call(this);\n if (!this.model) {\n return $newRender;\n }\n\n if (Galaxy && Galaxy.user && Galaxy.user.id && Galaxy.user.id === this.model.get(\"user_id\")) {\n this._renderTags($newRender);\n this._renderAnnotation($newRender);\n }\n return $newRender;\n },\n\n /** Update the history size display (curr. upper right of panel). */\n updateHistoryDiskSize: function updateHistoryDiskSize() {\n this.$(\".history-size\").text(this.model.get(\"nice_size\"));\n },\n\n /** override to render counts when the items are rendered */\n renderItems: function renderItems($whereTo) {\n var views = _super.prototype.renderItems.call(this, $whereTo);\n if (!this.searchFor) {\n this._renderCounts($whereTo);\n } else {\n this._renderSearchFindings($whereTo);\n }\n return views;\n },\n\n /** override to show counts, what's deleted/hidden, and links to toggle those */\n _renderCounts: function _renderCounts($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.counts(this.model.toJSON(), this);\n return $whereTo.find(\"> .controls .subtitle\").html(html);\n },\n\n /** render the tags sub-view controller */\n _renderTags: function _renderTags($where) {\n var panel = this;\n this.tagsEditor = new _tag2.default.TagsEditor({\n model: this.model,\n el: $where.find(\".controls .tags-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // show hide sub-view tag editors when this is shown/hidden\n onshow: function onshow() {\n panel.toggleHDATagEditors(true, panel.fxSpeed);\n },\n onhide: function onhide() {\n panel.toggleHDATagEditors(false, panel.fxSpeed);\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit history tags\"),\n classes: \"history-tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n /** render the annotation sub-view controller */\n _renderAnnotation: function _renderAnnotation($where) {\n var panel = this;\n this.annotationEditor = new _annotation2.default.AnnotationEditor({\n model: this.model,\n el: $where.find(\".controls .annotation-display\"),\n onshowFirstTime: function onshowFirstTime() {\n this.render();\n },\n // show hide sub-view view annotation editors when this is shown/hidden\n onshow: function onshow() {\n panel.toggleHDAAnnotationEditors(true, panel.fxSpeed);\n },\n onhide: function onhide() {\n panel.toggleHDAAnnotationEditors(false, panel.fxSpeed);\n },\n $activator: (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Edit history annotation\"),\n classes: \"history-annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n\n /** Set up HistoryViewEdit js/widget behaviours\n * In this override, make the name editable\n */\n _setUpBehaviors: function _setUpBehaviors($where) {\n $where = $where || this.$el;\n _super.prototype._setUpBehaviors.call(this, $where);\n if (!this.model) {\n return;\n }\n\n // anon users shouldn't have access to any of the following\n if (!Galaxy.user || Galaxy.user.isAnonymous() || Galaxy.user.id !== this.model.get(\"user_id\")) {\n return;\n }\n\n var panel = this;\n var nameSelector = \"> .controls .name\";\n $where.find(nameSelector).attr(\"title\", (0, _localization2.default)(\"Click to rename history\")).tooltip({ placement: \"bottom\" }).make_text_editable({\n on_finish: function on_finish(newName) {\n var previousName = panel.model.get(\"name\");\n if (newName && newName !== previousName) {\n panel.$el.find(nameSelector).text(newName);\n panel.model.save({ name: newName }).fail(function () {\n panel.$el.find(nameSelector).text(panel.model.previous(\"name\"));\n });\n } else {\n panel.$el.find(nameSelector).text(previousName);\n }\n }\n });\n },\n\n /** return a new popup menu for choosing a multi selection action\n * ajax calls made for multiple datasets are queued\n */\n multiselectActions: function multiselectActions() {\n var panel = this;\n\n var actions = [{\n html: (0, _localization2.default)(\"Hide datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.hide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }, {\n html: (0, _localization2.default)(\"Unhide datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.unhide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }, {\n html: (0, _localization2.default)(\"Delete datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype[\"delete\"];\n panel.getSelectedModels().ajaxQueue(action);\n }\n }, {\n html: (0, _localization2.default)(\"Undelete datasets\"),\n func: function func() {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.undelete;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }];\n\n if (panel.purgeAllowed) {\n actions.push({\n html: (0, _localization2.default)(\"Permanently delete datasets\"),\n func: function func() {\n if (confirm((0, _localization2.default)(\"This will permanently remove the data in your datasets. Are you sure?\"))) {\n var action = _hdaModel2.default.HistoryDatasetAssociation.prototype.purge;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }\n });\n }\n actions = actions.concat(panel._collectionActions());\n return actions;\n },\n\n /** */\n _collectionActions: function _collectionActions() {\n var panel = this;\n return [{\n html: (0, _localization2.default)(\"Build Dataset List\"),\n func: function func() {\n panel.buildCollection(\"list\");\n }\n },\n // TODO: Only show quick pair if two things selected.\n {\n html: (0, _localization2.default)(\"Build Dataset Pair\"),\n func: function func() {\n panel.buildCollection(\"paired\");\n }\n }, {\n html: (0, _localization2.default)(\"Build List of Dataset Pairs\"),\n func: function func() {\n panel.buildCollection(\"list:paired\");\n }\n }];\n },\n\n buildCollection: function buildCollection(collectionType, selection, hideSourceItems) {\n var panel = this;\n var selection = selection || panel.getSelectedModels();\n var hideSourceItems = hideSourceItems || false;\n var createFunc;\n if (collectionType == \"list\") {\n createFunc = _listCollectionCreator2.default.createListCollection;\n } else if (collectionType == \"paired\") {\n createFunc = _pairCollectionCreator2.default.createPairCollection;\n } else if (collectionType == \"list:paired\") {\n createFunc = _listOfPairsCollectionCreator2.default.createListOfPairsCollection;\n } else {\n console.warn(\"Unknown collectionType encountered \" + collectionType);\n }\n createFunc(selection, hideSourceItems).done(function () {\n panel.model.refresh();\n });\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, add purgeAllowed and whether tags/annotation editors should be shown */\n _getItemViewOptions: function _getItemViewOptions(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n _.extend(options, {\n purgeAllowed: this.purgeAllowed,\n tagsEditorShown: this.tagsEditor && !this.tagsEditor.hidden,\n annotationEditorShown: this.annotationEditor && !this.annotationEditor.hidden\n });\n return options;\n },\n\n /** If this item is deleted and we're not showing deleted items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemDeletedChange: function _handleItemDeletedChange(itemModel) {\n if (itemModel.get(\"deleted\")) {\n this._handleItemDeletion(itemModel);\n } else {\n this._handleItemUndeletion(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemDeletion: function _handleItemDeletion(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeDeleted) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUndeletion: function _handleItemUndeletion(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted -= 1;\n if (!this.model.contents.includeDeleted) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** If this item is hidden and we're not showing hidden items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemVisibleChange: function _handleItemVisibleChange(itemModel) {\n if (itemModel.hidden()) {\n this._handleItemHidden(itemModel);\n } else {\n this._handleItemUnhidden(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemHidden: function _handleItemHidden(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeHidden) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUnhidden: function _handleItemUnhidden(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden -= 1;\n if (!this.model.contents.includeHidden) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** toggle the visibility of each content's tagsEditor applying all the args sent to this function */\n toggleHDATagEditors: function toggleHDATagEditors(showOrHide, speed) {\n _.each(this.views, function (view) {\n if (view.tagsEditor) {\n view.tagsEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n /** toggle the visibility of each content's annotationEditor applying all the args sent to this function */\n toggleHDAAnnotationEditors: function toggleHDAAnnotationEditors(showOrHide, speed) {\n _.each(this.views, function (view) {\n if (view.annotationEditor) {\n view.annotationEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click .toggle-deleted-link\": function clickToggleDeletedLink(ev) {\n this.toggleShowDeleted();\n },\n \"click .toggle-hidden-link\": function clickToggleHiddenLink(ev) {\n this.toggleShowHidden();\n }\n }),\n\n // ------------------------------------------------------------------------ search\n _renderSearchProgress: function _renderSearchProgress(limit, offset) {\n var stop = limit + offset;\n return this.$(\"> .controls .subtitle\").html([\"\", (0, _localization2.default)(\"Searching \"), stop, \"/\", this.model.contentsShown(), \"\"].join(\"\"));\n },\n\n /** override to display number found in subtitle */\n _renderSearchFindings: function _renderSearchFindings($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.found(this.model.toJSON(), this);\n $whereTo.find(\"> .controls .subtitle\").html(html);\n return this;\n },\n\n // ------------------------------------------------------------------------ as drop target\n /** turn all the drag and drop handlers on and add some help text above the drop area */\n dropTargetOn: function dropTargetOn() {\n if (this.dropTarget) {\n return this;\n }\n this.dropTarget = true;\n\n //TODO: to init\n var dropHandlers = {\n dragenter: _.bind(this.dragenter, this),\n dragover: _.bind(this.dragover, this),\n dragleave: _.bind(this.dragleave, this),\n drop: _.bind(this.drop, this)\n };\n\n var $dropTarget = this._renderDropTarget();\n this.$list().before([this._renderDropTargetHelp(), $dropTarget]);\n for (var evName in dropHandlers) {\n if (dropHandlers.hasOwnProperty(evName)) {\n //console.debug( evName, dropHandlers[ evName ] );\n $dropTarget.on(evName, dropHandlers[evName]);\n }\n }\n return this;\n },\n\n /** render a box to serve as a 'drop here' area on the history */\n _renderDropTarget: function _renderDropTarget() {\n this.$(\".history-drop-target\").remove();\n return $(\"\").addClass(\"history-drop-target\");\n },\n\n /** tell the user how it works */\n _renderDropTargetHelp: function _renderDropTargetHelp() {\n this.$(\".history-drop-target-help\").remove();\n return $(\"\").addClass(\"history-drop-target-help\").text((0, _localization2.default)(\"Drag datasets here to copy them to the current history\"));\n },\n\n /** shut down drag and drop event handlers and remove drop target */\n dropTargetOff: function dropTargetOff() {\n if (!this.dropTarget) {\n return this;\n }\n //this.log( 'dropTargetOff' );\n this.dropTarget = false;\n var dropTarget = this.$(\".history-drop-target\").get(0);\n for (var evName in this._dropHandlers) {\n if (this._dropHandlers.hasOwnProperty(evName)) {\n dropTarget.off(evName, this._dropHandlers[evName]);\n }\n }\n this.$(\".history-drop-target\").remove();\n this.$(\".history-drop-target-help\").remove();\n return this;\n },\n /** toggle the target on/off */\n dropTargetToggle: function dropTargetToggle() {\n if (this.dropTarget) {\n this.dropTargetOff();\n } else {\n this.dropTargetOn();\n }\n return this;\n },\n\n dragenter: function dragenter(ev) {\n //console.debug( 'dragenter:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"2px solid black\");\n },\n dragover: function dragover(ev) {\n ev.preventDefault();\n ev.stopPropagation();\n },\n dragleave: function dragleave(ev) {\n //console.debug( 'dragleave:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"1px dashed black\");\n },\n /** when (text) is dropped try to parse as json and trigger an event */\n drop: function drop(ev) {\n ev.preventDefault();\n //ev.stopPropagation();\n\n var self = this;\n var dataTransfer = ev.originalEvent.dataTransfer;\n var data = dataTransfer.getData(\"text\");\n\n dataTransfer.dropEffect = \"move\";\n try {\n data = JSON.parse(data);\n } catch (err) {\n self.warn(\"error parsing JSON from drop:\", data);\n }\n\n self.trigger(\"droptarget:drop\", ev, data, self);\n return false;\n },\n\n /** handler that copies data into the contents */\n dataDropped: function dataDropped(data) {\n var self = this;\n // HDA: dropping will copy it to the history\n if (_.isObject(data) && data.model_class === \"HistoryDatasetAssociation\" && data.id) {\n if (self.contents.currentPage !== 0) {\n return self.contents.fetchPage(0).then(function () {\n return self.model.contents.copy(data.id);\n });\n }\n return self.model.contents.copy(data.id);\n }\n return jQuery.when();\n },\n\n // ........................................................................ misc\n /** Return a string rep of the history */\n toString: function toString() {\n return \"HistoryViewEdit(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryViewEdit.prototype.templates = function () {\n var countsTemplate = _baseMvc2.default.wrapTemplate([\"<% var shown = Math.max( view.views.length, history.contents_active.active ) %>\", \"<% if( shown ){ %>\", '', \"<%- shown %> \", (0, _localization2.default)(\"shown\"), \"\", \"<% } %>\", \"<% if( history.contents_active.deleted ){ %>\", '', \"<% if( view.model.contents.includeDeleted ){ %>\", '', (0, _localization2.default)(\"hide deleted\"), \"\", \"<% } else { %>\", \"<%- history.contents_active.deleted %> \", '', (0, _localization2.default)(\"deleted\"), \"\", \"<% } %>\", \"\", \"<% } %>\", \"<% if( history.contents_active.hidden ){ %>\", '', \"<% if( view.model.contents.includeHidden ){ %>\", '', (0, _localization2.default)(\"hide hidden\"), \"\", \"<% } else { %>\", \"<%- history.contents_active.hidden %> \", '', (0, _localization2.default)(\"hidden\"), \"\", \"<% } %>\", \"\", \"<% } %>\"], \"history\");\n\n var foundTemplate = _baseMvc2.default.wrapTemplate([(0, _localization2.default)(\"Found\"), \" <%- view.views.length %>, \", \"<% if( history.contents_active.deleted ){ %>\", \"<% if( view.model.contents.includeDeleted ){ %>\", '', (0, _localization2.default)(\"hide deleted\"), \", \", \"<% } else { %>\", '', (0, _localization2.default)(\"show deleted\"), \", \", \"<% } %>\", \"<% } %>\", \"<% if( history.contents_active.hidden ){ %>\", \"<% if( view.model.contents.includeHidden ){ %>\", '', (0, _localization2.default)(\"hide hidden\"), \"\", \"<% } else { %>\", '', (0, _localization2.default)(\"show hidden\"), \"\", \"<% } %>\", \"<% } %>\"], \"history\");\n\n return _.extend(_.clone(_super.prototype.templates), {\n counts: countsTemplate,\n found: foundTemplate\n });\n}();\n\n//==============================================================================\nexports.default = {\n HistoryViewEdit: HistoryViewEdit\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 155 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(_, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _listView = __webpack_require__(82);\n\nvar _listView2 = _interopRequireDefault(_listView);\n\nvar _historyModel = __webpack_require__(38);\n\nvar _historyModel2 = _interopRequireDefault(_historyModel);\n\nvar _historyContents = __webpack_require__(39);\n\nvar _historyContents2 = _interopRequireDefault(_historyContents);\n\nvar _historyPreferences = __webpack_require__(40);\n\nvar _historyPreferences2 = _interopRequireDefault(_historyPreferences);\n\nvar _hdaLi = __webpack_require__(84);\n\nvar _hdaLi2 = _interopRequireDefault(_hdaLi);\n\nvar _hdcaLi = __webpack_require__(86);\n\nvar _hdcaLi2 = _interopRequireDefault(_hdcaLi);\n\nvar _userModel = __webpack_require__(59);\n\nvar _userModel2 = _interopRequireDefault(_userModel);\n\nvar _errorModal = __webpack_require__(79);\n\nvar _errorModal2 = _interopRequireDefault(_errorModal);\n\nvar _faIconButton = __webpack_require__(14);\n\nvar _faIconButton2 = _interopRequireDefault(_faIconButton);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(83);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a history model.\n * Allows:\n * changing the loaded history\n * displaying data, info, and download\n * tracking history attrs: size, tags, annotations, name, etc.\n * Does not allow:\n * changing the name\n */\nvar _super = _listView2.default.ModelListPanel;\nvar HistoryView = _super.extend(\n/** @lends HistoryView.prototype */{\n _logNamespace: \"history\",\n\n /** class to use for constructing the HDA views */\n HDAViewClass: _hdaLi2.default.HDAListItemView,\n /** class to use for constructing the HDCA views */\n HDCAViewClass: _hdcaLi2.default.HDCAListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: _historyContents2.default.HistoryContents,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n tagName: \"div\",\n className: _super.prototype.className + \" history-panel\",\n\n /** string to display when the collection is empty */\n emptyMsg: (0, _localization2.default)(\"This history is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: (0, _localization2.default)(\"No matching datasets found\"),\n /** string used for search placeholder */\n searchPlaceholder: (0, _localization2.default)(\"search datasets\"),\n\n /** @type {Number} ms to wait after history load to fetch/decorate hdcas with element_count */\n FETCH_COLLECTION_COUNTS_DELAY: 2000,\n\n // ......................................................................... SET UP\n /** Set up the view, bind listeners.\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function initialize(attributes) {\n _super.prototype.initialize.call(this, attributes);\n // ---- instance vars\n // control contents/behavior based on where (and in what context) the panel is being used\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n /** timeout id for detailed fetch of collection counts, etc... */\n this.detailedFetchTimeoutId = null;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function _createDefaultCollection() {\n // override\n return new this.collectionClass([], {\n history: this.model\n });\n },\n\n /** In this override, clear the update timer on the model */\n freeModel: function freeModel() {\n _super.prototype.freeModel.call(this);\n if (this.model) {\n this.model.clearUpdateTimeout();\n }\n this._clearDetailedFetchTimeout();\n return this;\n },\n\n /** clear the timeout and the cached timeout id */\n _clearDetailedFetchTimeout: function _clearDetailedFetchTimeout() {\n if (this.detailedFetchTimeoutId) {\n clearTimeout(this.detailedFetchTimeoutId);\n this.detailedFetchTimeoutId = null;\n }\n },\n\n /** create any event listeners for the panel\n * @fires: rendered:initial on the first render\n * @fires: empty-history when switching to a history with no contents or creating a new history\n */\n _setUpListeners: function _setUpListeners() {\n var _this = this;\n\n _super.prototype._setUpListeners.call(this);\n this.on({\n error: function error(model, xhr, options, msg, details) {\n this.errorHandler(model, xhr, options, msg, details);\n },\n \"loading-done\": function loadingDone() {\n // after the initial load, decorate with more time consuming fields (like HDCA element_counts)\n _this.detailedFetchTimeoutId = _.delay(function () {\n _this.detailedFetchTimeoutId = null;\n _this.model.contents.fetchCollectionCounts();\n }, _this.FETCH_COLLECTION_COUNTS_DELAY);\n },\n \"views:ready view:attached view:removed\": function viewsReadyViewAttachedViewRemoved(view) {\n this._renderSelectButton();\n },\n \"view:attached\": function viewAttached(view) {\n this.scrollTo(0);\n }\n });\n // this.on( 'all', function(){ console.debug( arguments ); });\n },\n\n // ------------------------------------------------------------------------ loading history/hda models\n /** load the history with the given id then it's contents, sending ajax options to both */\n loadHistory: function loadHistory(historyId, options, contentsOptions) {\n var _this2 = this;\n\n contentsOptions = _.extend(contentsOptions || { silent: true });\n this.info(\"loadHistory:\", historyId, options, contentsOptions);\n this.setModel(new _historyModel2.default.History({ id: historyId }));\n\n contentsOptions.silent = true;\n this.trigger(\"loading\");\n return this.model.fetchWithContents(options, contentsOptions).always(function () {\n _this2.render();\n _this2.trigger(\"loading-done\");\n });\n },\n\n /** convenience alias to the model. Updates the item list only (not the history) */\n refreshContents: function refreshContents(options) {\n if (this.model) {\n return this.model.refresh(options);\n }\n // may have callbacks - so return an empty promise\n return $.when();\n },\n\n /** Override to reset web storage when the id changes (since it needs the id) */\n _setUpCollectionListeners: function _setUpCollectionListeners() {\n _super.prototype._setUpCollectionListeners.call(this);\n return this.listenTo(this.collection, {\n // 'all' : function(){ console.log( this.collection + ':', arguments ); },\n \"fetching-more\": function fetchingMore() {\n this._toggleContentsLoadingIndicator(true);\n this.$emptyMessage().hide();\n },\n \"fetching-more-done\": function fetchingMoreDone() {\n this._toggleContentsLoadingIndicator(false);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function _showLoadingIndicator(msg, speed, callback) {\n var $indicator = $('
');\n this.$el.html($indicator.text(msg).slideDown(!_.isUndefined(speed) ? speed : this.fxSpeed));\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function _hideLoadingIndicator(speed) {\n // make speed a bit slower to compensate for slow rendering of up to 500 contents\n this.$(\".loading-indicator\").slideUp(!_.isUndefined(speed) ? speed : this.fxSpeed + 200, function () {\n $(this).remove();\n });\n },\n\n /** In this override, add a btn to toggle the selectors */\n _buildNewRender: function _buildNewRender() {\n var $newRender = _super.prototype._buildNewRender.call(this);\n this._renderSelectButton($newRender);\n return $newRender;\n },\n\n /** button for starting select mode */\n _renderSelectButton: function _renderSelectButton($where) {\n $where = $where || this.$el;\n // do not render selector option if no actions\n if (!this.multiselectActions().length) {\n return null;\n }\n // do not render (and remove even) if nothing to select\n if (!this.views.length) {\n this.hideSelectors();\n $where.find(\".controls .actions .show-selectors-btn\").remove();\n return null;\n }\n // don't bother rendering if there's one already\n var $existing = $where.find(\".controls .actions .show-selectors-btn\");\n if ($existing.length) {\n return $existing;\n }\n\n return (0, _faIconButton2.default)({\n title: (0, _localization2.default)(\"Operations on multiple datasets\"),\n classes: \"show-selectors-btn\",\n faIcon: \"fa-check-square-o\"\n }).prependTo($where.find(\".controls .actions\"));\n },\n\n /** override to avoid showing intial empty message using contents_active */\n _renderEmptyMessage: function _renderEmptyMessage($whereTo) {\n var $emptyMsg = this.$emptyMessage($whereTo);\n var empty = this.model.get(\"contents_active\").active <= 0;\n if (empty) {\n return $emptyMsg.empty().append(this.emptyMsg).show();\n } else if (this.searchFor && this.model.contents.haveSearchDetails() && !this.views.length) {\n return $emptyMsg.empty().append(this.noneFoundMsg).show();\n }\n $emptyMsg.hide();\n return $();\n },\n\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function $scrollContainer($where) {\n // override or set via attributes.$scrollContainer\n return this.$list($where);\n },\n\n // ------------------------------------------------------------------------ subviews\n _toggleContentsLoadingIndicator: function _toggleContentsLoadingIndicator(show) {\n if (!show) {\n this.$list().find(\".contents-loading-indicator\").remove();\n } else {\n this.$list().html('
' + '
');\n }\n },\n\n /** override to render pagination also */\n renderItems: function renderItems($whereTo) {\n // console.log( this + '.renderItems-----------------', new Date() );\n $whereTo = $whereTo || this.$el;\n var $list = this.$list($whereTo);\n\n // TODO: bootstrap hack to remove orphaned tooltips\n $(\".tooltip\").remove();\n\n $list.empty();\n this.views = [];\n\n var models = this._filterCollection();\n if (models.length) {\n this._renderPagination($whereTo);\n this.views = this._renderSomeItems(models, $list);\n } else {\n // TODO: consolidate with _renderPagination above by (???) passing in models/length?\n $whereTo.find(\"> .controls .list-pagination\").empty();\n }\n this._renderEmptyMessage($whereTo).toggle(!models.length);\n\n this.trigger(\"views:ready\", this.views);\n return this.views;\n },\n\n /** render pagination controls if not searching and contents says we're paginating */\n _renderPagination: function _renderPagination($whereTo) {\n var $paginationControls = $whereTo.find(\"> .controls .list-pagination\");\n if (this.searchFor || !this.model.contents.shouldPaginate()) return $paginationControls.empty();\n\n $paginationControls.html(this.templates.pagination({\n // pagination is 1-based for the user\n current: this.model.contents.currentPage + 1,\n last: this.model.contents.getLastPage() + 1\n }, this));\n $paginationControls.find(\"select.pages\").tooltip();\n return $paginationControls;\n },\n\n /** render a subset of the entire collection (client-side pagination) */\n _renderSomeItems: function _renderSomeItems(models, $list) {\n var _this3 = this;\n\n var views = [];\n $list.append(models.map(function (m) {\n var view = _this3._createItemView(m);\n views.push(view);\n return _this3._renderItemView$el(view);\n }));\n return views;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** in this override, check if the contents would also display based on includeDeleted/hidden */\n _filterItem: function _filterItem(model) {\n var contents = this.model.contents;\n return (contents.includeHidden || !model.hidden()) && (contents.includeDeleted || !model.isDeletedOrPurged()) && _super.prototype._filterItem.call(this, model);\n },\n\n /** In this override, since history contents are mixed,\n * get the appropo view class based on history_content_type\n */\n _getItemViewClass: function _getItemViewClass(model) {\n var contentType = model.get(\"history_content_type\");\n switch (contentType) {\n case \"dataset\":\n return this.HDAViewClass;\n case \"dataset_collection\":\n return this.HDCAViewClass;\n }\n throw new TypeError(\"Unknown history_content_type: \" + contentType);\n },\n\n /** in this override, add a linktarget, and expand if id is in web storage */\n _getItemViewOptions: function _getItemViewOptions(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n expanded: this.model.contents.storage.isExpanded(model.id),\n hasUser: this.model.ownedByCurrUser()\n });\n },\n\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function _setUpItemViewListeners(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n //TODO: send from content view: this.model.collection.storage.addExpanded\n // maintain a list of items whose bodies are expanded\n return panel.listenTo(view, {\n expanded: function expanded(v) {\n panel.model.contents.storage.addExpanded(v.model);\n },\n collapsed: function collapsed(v) {\n panel.model.contents.storage.removeExpanded(v.model);\n }\n });\n },\n\n /** override to remove expandedIds from webstorage */\n collapseAll: function collapseAll() {\n this.model.contents.storage.clearExpanded();\n _super.prototype.collapseAll.call(this);\n },\n\n // ------------------------------------------------------------------------ selection\n /** Override to correctly set the historyId of the new collection */\n getSelectedModels: function getSelectedModels() {\n var collection = _super.prototype.getSelectedModels.call(this);\n collection.historyId = this.collection.historyId;\n return collection;\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click > .controls .prev\": \"_clickPrevPage\",\n \"click > .controls .next\": \"_clickNextPage\",\n \"change > .controls .pages\": \"_changePageSelect\",\n // allow (error) messages to be clicked away\n \"click .messages [class$=message]\": \"clearMessages\"\n }),\n\n _clickPrevPage: function _clickPrevPage(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchPrevPage();\n },\n\n _clickNextPage: function _clickNextPage(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchNextPage();\n },\n\n _changePageSelect: function _changePageSelect(ev) {\n this.model.clearUpdateTimeout();\n var page = $(ev.currentTarget).val();\n this.model.contents.fetchPage(page);\n },\n\n /** Toggle and store the deleted visibility and re-render items\n * @returns {Boolean} new setting\n */\n toggleShowDeleted: function toggleShowDeleted(show, options) {\n show = show !== undefined ? show : !this.model.contents.includeDeleted;\n var contents = this.model.contents;\n contents.setIncludeDeleted(show, options);\n this.trigger(\"show-deleted\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** Toggle and store whether to render explicity hidden contents\n * @returns {Boolean} new setting\n */\n toggleShowHidden: function toggleShowHidden(show, store, options) {\n // console.log( 'toggleShowHidden', show, store );\n show = show !== undefined ? show : !this.model.contents.includeHidden;\n var contents = this.model.contents;\n contents.setIncludeHidden(show, options);\n this.trigger(\"show-hidden\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** On the first search, if there are no details - load them, then search */\n _firstSearch: function _firstSearch(searchFor) {\n var _this4 = this;\n\n var inputSelector = \"> .controls .search-input\";\n this.log(\"onFirstSearch\", searchFor);\n\n // if the contents already have enough details to search, search and return now\n if (this.model.contents.haveSearchDetails()) {\n this.searchItems(searchFor);\n return;\n }\n\n // otherwise, load the details progressively here\n this.$(inputSelector).searchInput(\"toggle-loading\");\n // set this now so that only results will show during progress\n this.searchFor = searchFor;\n var xhr = this.model.contents.progressivelyFetchDetails({ silent: true }).progress(function (response, limit, offset) {\n _this4.renderItems();\n _this4.trigger(\"search:loading-progress\", limit, offset);\n }).always(function () {\n _this4.$el.find(inputSelector).searchInput(\"toggle-loading\");\n }).done(function () {\n _this4.searchItems(searchFor, \"force\");\n });\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function clearSearch(searchFor) {\n var _this5 = this;\n\n if (!this.searchFor) return this;\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n // NOTE: silent + render prevents collection update event with merge only\n // - which causes an empty page due to event handler above\n this.model.contents.fetchCurrentPage({ silent: true }).done(function () {\n _this5.renderItems();\n });\n return this;\n },\n\n // ........................................................................ error handling\n /** Event handler for errors (from the panel, the history, or the history's contents)\n * Alternately use two strings for model and xhr to use custom message and title (respectively)\n * @param {Model or View} model the (Backbone) source of the error\n * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error\n * @param {Object} options the options map commonly used with bbone ajax\n */\n errorHandler: function errorHandler(model, xhr, options) {\n //TODO: to mixin or base model\n // interrupted ajax or no connection\n if (xhr && xhr.status === 0 && xhr.readyState === 0) {\n // return ERROR_MODAL.offlineErrorModal();\n // fail silently\n return;\n }\n // otherwise, leave something to report in the console\n this.error(model, xhr, options);\n // and feedback to a modal\n // if sent two strings (and possibly details as 'options'), use those as message and title\n if (_.isString(model) && _.isString(xhr)) {\n var message = model;\n var title = xhr;\n return _errorModal2.default.errorModal(message, title, options);\n }\n // bad gateway\n // TODO: possibly to global handler\n if (xhr && xhr.status === 502) {\n return _errorModal2.default.badGatewayErrorModal();\n }\n return _errorModal2.default.ajaxErrorModal(model, xhr, options);\n },\n\n /** Remove all messages from the panel. */\n clearMessages: function clearMessages(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target.fadeOut(this.fxSpeed, function () {\n $(this).remove();\n });\n return this;\n },\n\n // ........................................................................ scrolling\n /** Scrolls the panel to show the content sub-view with the given hid.\n * @param {Integer} hid the hid of item to scroll into view\n * @returns {HistoryView} the panel\n */\n scrollToHid: function scrollToHid(hid) {\n return this.scrollToItem(_.first(this.viewsWhereModel({ hid: hid })));\n },\n\n // ........................................................................ misc\n /** utility for adding -st, -nd, -rd, -th to numbers */\n ordinalIndicator: function ordinalIndicator(number) {\n var numStr = \"\" + number;\n switch (numStr.charAt(numStr.length - 1)) {\n case \"1\":\n return numStr + \"st\";\n case \"2\":\n return numStr + \"nd\";\n case \"3\":\n return numStr + \"rd\";\n default:\n return numStr + \"th\";\n }\n },\n\n /** Return a string rep of the history */\n toString: function toString() {\n return \"HistoryView(\" + (this.model ? this.model.get(\"name\") : \"\") + \")\";\n }\n});\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryView.prototype.templates = function () {\n var mainTemplate = function mainTemplate() {\n return \"
\\n \\n
\\n ',\\n
\";\n };\n\n var controlsTemplate = _baseMvc2.default.wrapTemplate(['
\"].join(\"\")),\n\n /** help content */\n helpContent: _.template([\"
\", (0, _localization2.default)([\"Pair collections are permanent collections containing two datasets: one forward and one reverse. \", \"Often these are forward and reverse reads. The pair collections can be passed to tools and \", \"workflows in order to have analyses done on both datasets. This interface allows \", \"you to create a pair, name it, and swap which is forward and which reverse.\"].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)(['Click the \"Swap\" link to make your forward dataset the reverse ', \"and the reverse dataset forward.\"].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Click the \"Cancel\" button to exit the interface.'].join(\"\")), \"
\", \"
\", \"
\", (0, _localization2.default)(['Once your collection is complete, enter a name and ', 'click \"Create list\".'].join(\"\")), \"
\"].join(\"\")),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(['
', '
', '', \"<% if( _.size( problems ) ){ %>\", (0, _localization2.default)(\"The following selections could not be included due to problems\"), \"
<% _.each( problems, function( problem ){ %>\", \"
<%- problem.element.name %>: <%- problem.text %>
\", \"<% }); %>
\", \"<% } else if( _.size( elements ) === 0 ){ %>\", (0, _localization2.default)(\"No datasets were selected\"), \".\", \"<% } else if( _.size( elements ) === 1 ){ %>\", (0, _localization2.default)(\"Only one dataset was selected\"), \": <%- elements[0].name %>\", \"<% } else if( _.size( elements ) > 2 ){ %>\", (0, _localization2.default)(\"Too many datasets were selected\"), ': <%- _.pluck( elements, \"name\" ).join( \", \") %>', \"<% } %>\", \" \", (0, _localization2.default)(\"Two (and only two) elements are needed for the pair\"), \". \", (0, _localization2.default)(\"You may need to \"), '', (0, _localization2.default)(\"cancel\"), \" \", (0, _localization2.default)(\"and reselect new elements\"), \".\", \"\", \"
\", \"
\", '\"].join(\"\"))\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function toString() {\n return \"PairCollectionCreator\";\n }\n});\n\n//==============================================================================\n/** List collection flavor of collectionCreatorModal. */\nvar pairCollectionCreatorModal = function _pairCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = (0, _localization2.default)(\"Create a collection from a pair of datasets\");\n return _listCollectionCreator2.default.collectionCreatorModal(elements, options, PairCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a pair collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createPairCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = pairCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function creationFn(elements, name, hideSourceItems) {\n elements = [{ name: \"forward\", src: \"hda\", id: elements[0].id }, { name: \"reverse\", src: \"hda\", id: elements[1].id }];\n return contents.createHDCA(elements, \"paired\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexports.default = {\n PairCollectionCreator: PairCollectionCreator,\n pairCollectionCreatorModal: pairCollectionCreatorModal,\n createPairCollection: createPairCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 162 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, _, jQuery, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _levenshtein = __webpack_require__(163);\n\nvar _levenshtein2 = _interopRequireDefault(_levenshtein);\n\nvar _naturalSort = __webpack_require__(75);\n\nvar _naturalSort2 = _interopRequireDefault(_naturalSort);\n\nvar _baseCreator = __webpack_require__(74);\n\nvar _baseCreator2 = _interopRequireDefault(_baseCreator);\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nvar _localization = __webpack_require__(4);\n\nvar _localization2 = _interopRequireDefault(_localization);\n\n__webpack_require__(76);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar logNamespace = \"collections\";\n/* ============================================================================\nTODO:\n\n\nPROGRAMMATICALLY:\ncurrPanel.once( 'rendered', function(){\n currPanel.showSelectors();\n currPanel.selectAll();\n _.last( currPanel.actionsPopup.options ).func();\n});\n\n============================================================================ */\n/** A view for paired datasets in the collections creator.\n */\nvar PairView = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n tagName: \"li\",\n className: \"dataset paired\",\n\n initialize: function initialize(attributes) {\n this.pair = attributes.pair || {};\n },\n\n template: _.template(['<%- pair.forward.name %>', '', '<%- pair.name %>', \"\", '<%- pair.reverse.name %>'].join(\"\")),\n\n render: function render() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el.attr(\"draggable\", true).data(\"pair\", this.pair).html(this.template({ pair: this.pair })).addClass(\"flex-column-container\").get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n return this;\n },\n\n events: {\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function _dragstart(ev) {\n ev.currentTarget.style.opacity = \"0.4\";\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.pair));\n\n this.$el.parent().trigger(\"pair.dragstart\", [this]);\n },\n\n /** dragging pairs for re-ordering */\n _dragend: function _dragend(ev) {\n ev.currentTarget.style.opacity = \"1.0\";\n this.$el.parent().trigger(\"pair.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function _sendToParent(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function toString() {\n return \"PairView(\" + this.pair.name + \")\";\n }\n});\n\n// ============================================================================\n/** returns an autopair function that uses the provided options.match function */\nfunction autoPairFnBuilder(options) {\n options = options || {};\n options.createPair = options.createPair || function _defaultCreatePair(params) {\n params = params || {};\n var a = params.listA.splice(params.indexA, 1)[0];\n var b = params.listB.splice(params.indexB, 1)[0];\n var aInBIndex = params.listB.indexOf(a);\n var bInAIndex = params.listA.indexOf(b);\n if (aInBIndex !== -1) {\n params.listB.splice(aInBIndex, 1);\n }\n if (bInAIndex !== -1) {\n params.listA.splice(bInAIndex, 1);\n }\n return this._pair(a, b, { silent: true });\n };\n // compile these here outside of the loop\n var _regexps = [];\n function getRegExps() {\n if (!_regexps.length) {\n _regexps = [new RegExp(this.filters[0]), new RegExp(this.filters[1])];\n }\n return _regexps;\n }\n // mangle params as needed\n options.preprocessMatch = options.preprocessMatch || function _defaultPreprocessMatch(params) {\n var regexps = getRegExps.call(this);\n return _.extend(params, {\n matchTo: params.matchTo.name.replace(regexps[0], \"\"),\n possible: params.possible.name.replace(regexps[1], \"\")\n });\n };\n\n return function _strategy(params) {\n this.debug(\"autopair _strategy ---------------------------\");\n params = params || {};\n var listA = params.listA;\n var listB = params.listB;\n var indexA = 0;\n var indexB;\n\n var bestMatch = {\n score: 0.0,\n index: null\n };\n\n var paired = [];\n //console.debug( 'params:', JSON.stringify( params, null, ' ' ) );\n this.debug(\"starting list lens:\", listA.length, listB.length);\n this.debug(\"bestMatch (starting):\", JSON.stringify(bestMatch, null, \" \"));\n\n while (indexA < listA.length) {\n var matchTo = listA[indexA];\n bestMatch.score = 0.0;\n\n for (indexB = 0; indexB < listB.length; indexB++) {\n var possible = listB[indexB];\n this.debug(indexA + \":\" + matchTo.name);\n this.debug(indexB + \":\" + possible.name);\n\n // no matching with self\n if (listA[indexA] !== listB[indexB]) {\n bestMatch = options.match.call(this, options.preprocessMatch.call(this, {\n matchTo: matchTo,\n possible: possible,\n index: indexB,\n bestMatch: bestMatch\n }));\n this.debug(\"bestMatch:\", JSON.stringify(bestMatch, null, \" \"));\n if (bestMatch.score === 1.0) {\n this.debug(\"breaking early due to perfect match\");\n break;\n }\n }\n }\n var scoreThreshold = options.scoreThreshold.call(this);\n this.debug(\"scoreThreshold:\", scoreThreshold);\n this.debug(\"bestMatch.score:\", bestMatch.score);\n\n if (bestMatch.score >= scoreThreshold) {\n //console.debug( 'autoPairFnBuilder.strategy', listA[ indexA ].name, listB[ bestMatch.index ].name );\n paired.push(options.createPair.call(this, {\n listA: listA,\n indexA: indexA,\n listB: listB,\n indexB: bestMatch.index\n }));\n //console.debug( 'list lens now:', listA.length, listB.length );\n } else {\n indexA += 1;\n }\n if (!listA.length || !listB.length) {\n return paired;\n }\n }\n this.debug(\"paired:\", JSON.stringify(paired, null, \" \"));\n this.debug(\"autopair _strategy ---------------------------\");\n return paired;\n };\n}\n\n// ============================================================================\n/** An interface for building collections of paired datasets.\n */\nvar PairedCollectionCreator = Backbone.View.extend(_baseMvc2.default.LoggableMixin).extend(_baseCreator2.default.CollectionCreatorMixin).extend({\n _logNamespace: logNamespace,\n\n className: \"list-of-pairs-collection-creator collection-creator flex-row-container\",\n\n /** set up initial options, instance vars, behaviors, and autopair (if set to do so) */\n initialize: function initialize(attributes) {\n this.metric(\"PairedCollectionCreator.initialize\", attributes);\n //this.debug( '-- PairedCollectionCreator:', attributes );\n\n attributes = _.defaults(attributes, {\n datasets: [],\n filters: this.DEFAULT_FILTERS,\n automaticallyPair: true,\n strategy: \"lcs\",\n matchPercentage: 0.9,\n twoPassAutopairing: true\n });\n\n /** unordered, original list */\n this.initialList = attributes.datasets;\n\n /** is this from a history? if so, what's its id? */\n this.historyId = attributes.historyId;\n\n /** which filters should be used initially? (String[2] or name in commonFilters) */\n this.filters = this.commonFilters[attributes.filters] || this.commonFilters[this.DEFAULT_FILTERS];\n if (_.isArray(attributes.filters)) {\n this.filters = attributes.filters;\n }\n\n /** try to auto pair the unpaired datasets on load? */\n this.automaticallyPair = attributes.automaticallyPair;\n\n /** what method to use for auto pairing (will be passed aggression level) */\n this.strategy = this.strategies[attributes.strategy] || this.strategies[this.DEFAULT_STRATEGY];\n if (_.isFunction(attributes.strategy)) {\n this.strategy = attributes.strategy;\n }\n\n /** distance/mismatch level allowed for autopairing */\n this.matchPercentage = attributes.matchPercentage;\n\n /** try to autopair using simple first, then this.strategy on the remainder */\n this.twoPassAutopairing = attributes.twoPassAutopairing;\n\n /** remove file extensions (\\.*) from created pair names? */\n this.removeExtensions = true;\n //this.removeExtensions = false;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.oncancel = attributes.oncancel;\n /** fn to call when the collection is created (scoped to this) */\n this.oncreate = attributes.oncreate;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.autoscrollDist = attributes.autoscrollDist || 24;\n\n /** is the unpaired panel shown? */\n this.unpairedPanelHidden = false;\n /** is the paired panel shown? */\n this.pairedPanelHidden = false;\n\n /** DOM elements currently being dragged */\n this.$dragging = null;\n\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n\n this._setUpCommonSettings(attributes);\n this._setUpBehaviors();\n this._dataSetUp();\n },\n\n /** map of common filter pairs by name */\n commonFilters: {\n illumina: [\"_1\", \"_2\"],\n Rs: [\"_R1\", \"_R2\"]\n },\n /** which commonFilter to use by default */\n DEFAULT_FILTERS: \"illumina\",\n\n /** map of name->fn for autopairing */\n strategies: {\n simple: \"autopairSimple\",\n lcs: \"autopairLCS\",\n levenshtein: \"autopairLevenshtein\"\n },\n /** default autopair strategy name */\n DEFAULT_STRATEGY: \"lcs\",\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data: cache initialList, sort, and autopair */\n _dataSetUp: function _dataSetUp() {\n //this.debug( '-- _dataSetUp' );\n\n this.paired = [];\n this.unpaired = [];\n\n this.selectedIds = [];\n\n // sort initial list, add ids if needed, and save new working copy to unpaired\n this._sortInitialList();\n this._ensureIds();\n this.unpaired = this.initialList.slice(0);\n\n if (this.automaticallyPair) {\n this.autoPair();\n this.once(\"rendered:initial\", function () {\n this.trigger(\"autopair\");\n });\n }\n },\n\n /** sort initial list */\n _sortInitialList: function _sortInitialList() {\n //this.debug( '-- _sortInitialList' );\n this._sortDatasetList(this.initialList);\n },\n\n /** sort a list of datasets */\n _sortDatasetList: function _sortDatasetList(list) {\n // currently only natural sort by name\n list.sort(function (a, b) {\n return (0, _naturalSort2.default)(a.name, b.name);\n });\n return list;\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureIds: function _ensureIds() {\n this.initialList.forEach(function (dataset) {\n if (!dataset.hasOwnProperty(\"id\")) {\n dataset.id = _.uniqueId();\n }\n });\n return this.initialList;\n },\n\n /** split initial list into two lists, those that pass forward filters & those passing reverse */\n _splitByFilters: function _splitByFilters() {\n var regexFilters = this.filters.map(function (stringFilter) {\n return new RegExp(stringFilter);\n });\n\n var split = [[], []];\n\n function _filter(unpaired, filter) {\n return filter.test(unpaired.name);\n //return dataset.name.indexOf( filter ) >= 0;\n }\n this.unpaired.forEach(function _filterEach(unpaired) {\n // 90% of the time this seems to work, but:\n //TODO: this treats *all* strings as regex which may confuse people - possibly check for // surrounding?\n // would need explanation in help as well\n regexFilters.forEach(function (filter, i) {\n if (_filter(unpaired, filter)) {\n split[i].push(unpaired);\n }\n });\n });\n return split;\n },\n\n /** add a dataset to the unpaired list in it's proper order */\n _addToUnpaired: function _addToUnpaired(dataset) {\n var _this = this;\n\n // currently, unpaired is natural sorted by name, use binary search to find insertion point\n var binSearchSortedIndex = function binSearchSortedIndex(low, hi) {\n if (low === hi) {\n return low;\n }\n\n var mid = Math.floor((hi - low) / 2) + low;\n\n var compared = (0, _naturalSort2.default)(dataset.name, _this.unpaired[mid].name);\n\n if (compared < 0) {\n return binSearchSortedIndex(low, mid);\n } else if (compared > 0) {\n return binSearchSortedIndex(mid + 1, hi);\n }\n // walk the equal to find the last\n while (_this.unpaired[mid] && _this.unpaired[mid].name === dataset.name) {\n mid++;\n }\n return mid;\n };\n\n this.unpaired.splice(binSearchSortedIndex(0, this.unpaired.length), 0, dataset);\n },\n\n // ------------------------------------------------------------------------ auto pairing\n /** two passes to automatically create pairs:\n * use both simpleAutoPair, then the fn mentioned in strategy\n */\n autoPair: function autoPair(strategy) {\n // split first using exact matching\n var split = this._splitByFilters();\n\n var paired = [];\n if (this.twoPassAutopairing) {\n paired = this.autopairSimple({\n listA: split[0],\n listB: split[1]\n });\n split = this._splitByFilters();\n }\n\n // uncomment to see printlns while running tests\n //this.debug = function(){ console.log.apply( console, arguments ); };\n\n // then try the remainder with something less strict\n strategy = strategy || this.strategy;\n split = this._splitByFilters();\n paired = paired.concat(this[strategy].call(this, {\n listA: split[0],\n listB: split[1]\n }));\n return paired;\n },\n\n /** autopair by exact match */\n autopairSimple: autoPairFnBuilder({\n scoreThreshold: function scoreThreshold() {\n return 0.6;\n },\n match: function _match(params) {\n params = params || {};\n if (params.matchTo === params.possible) {\n return {\n index: params.index,\n score: 1.0\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by levenshtein edit distance scoring */\n autopairLevenshtein: autoPairFnBuilder({\n scoreThreshold: function scoreThreshold() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var distance = (0, _levenshtein2.default)(params.matchTo, params.possible);\n\n var score = 1.0 - distance / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by longest common substrings scoring */\n autopairLCS: autoPairFnBuilder({\n scoreThreshold: function scoreThreshold() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var match = this._naiveStartingAndEndingLCS(params.matchTo, params.possible).length;\n\n var score = match / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** return the concat'd longest common prefix and suffix from two strings */\n _naiveStartingAndEndingLCS: function _naiveStartingAndEndingLCS(s1, s2) {\n var fwdLCS = \"\";\n var revLCS = \"\";\n var i = 0;\n var j = 0;\n while (i < s1.length && i < s2.length) {\n if (s1[i] !== s2[i]) {\n break;\n }\n fwdLCS += s1[i];\n i += 1;\n }\n if (i === s1.length) {\n return s1;\n }\n if (i === s2.length) {\n return s2;\n }\n\n i = s1.length - 1;\n j = s2.length - 1;\n while (i >= 0 && j >= 0) {\n if (s1[i] !== s2[j]) {\n break;\n }\n revLCS = [s1[i], revLCS].join(\"\");\n i -= 1;\n j -= 1;\n }\n return fwdLCS + revLCS;\n },\n\n // ------------------------------------------------------------------------ pairing / unpairing\n /** create a pair from fwd and rev, removing them from unpaired, and placing the new pair in paired */\n _pair: function _pair(fwd, rev, options) {\n options = options || {};\n this.debug(\"_pair:\", fwd, rev);\n var pair = this._createPair(fwd, rev, options.name);\n this.paired.push(pair);\n this.unpaired = _.without(this.unpaired, fwd, rev);\n if (!options.silent) {\n this.trigger(\"pair:new\", pair);\n }\n return pair;\n },\n\n /** create a pair Object from fwd and rev, adding the name attribute (will guess if not given) */\n _createPair: function _createPair(fwd, rev, name) {\n // ensure existance and don't pair something with itself\n if (!(fwd && rev) || fwd === rev) {\n throw new Error(\"Bad pairing: \" + [JSON.stringify(fwd), JSON.stringify(rev)]);\n }\n name = name || this._guessNameForPair(fwd, rev);\n return { forward: fwd, name: name, reverse: rev };\n },\n\n /** try to find a good pair name for the given fwd and rev datasets */\n _guessNameForPair: function _guessNameForPair(fwd, rev, removeExtensions) {\n removeExtensions = removeExtensions !== undefined ? removeExtensions : this.removeExtensions;\n var fwdName = fwd.name;\n var revName = rev.name;\n\n var lcs = this._naiveStartingAndEndingLCS(fwdName.replace(new RegExp(this.filters[0]), \"\"), revName.replace(new RegExp(this.filters[1]), \"\"));\n\n if (removeExtensions) {\n var lastDotIndex = lcs.lastIndexOf(\".\");\n if (lastDotIndex > 0) {\n var extension = lcs.slice(lastDotIndex, lcs.length);\n lcs = lcs.replace(extension, \"\");\n fwdName = fwdName.replace(extension, \"\");\n revName = revName.replace(extension, \"\");\n }\n }\n return lcs || fwdName + \" & \" + revName;\n },\n\n /** unpair a pair, removing it from paired, and adding the fwd,rev datasets back into unpaired */\n _unpair: function _unpair(pair, options) {\n options = options || {};\n if (!pair) {\n throw new Error(\"Bad pair: \" + JSON.stringify(pair));\n }\n this.paired = _.without(this.paired, pair);\n this._addToUnpaired(pair.forward);\n this._addToUnpaired(pair.reverse);\n\n if (!options.silent) {\n this.trigger(\"pair:unpair\", [pair]);\n }\n return pair;\n },\n\n /** unpair all paired datasets */\n unpairAll: function unpairAll() {\n var pairs = [];\n while (this.paired.length) {\n pairs.push(this._unpair(this.paired[0], { silent: true }));\n }\n this.trigger(\"pair:unpair\", pairs);\n },\n\n // ------------------------------------------------------------------------ API\n /** convert a pair into JSON compatible with the collections API */\n _pairToJSON: function _pairToJSON(pair, src) {\n src = src || \"hda\";\n //TODO: consider making this the pair structure when created instead\n return {\n collection_type: \"paired\",\n src: \"new_collection\",\n name: pair.name,\n element_identifiers: [{\n name: \"forward\",\n id: pair.forward.id,\n src: src\n }, {\n name: \"reverse\",\n id: pair.reverse.id,\n src: src\n }]\n };\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function createList(name) {\n var self = this;\n\n var url = Galaxy.root + \"api/histories/\" + this.historyId + \"/contents/dataset_collections\";\n\n //TODO: use ListPairedCollection.create()\n var ajaxData = {\n type: \"dataset_collection\",\n collection_type: \"list:paired\",\n hide_source_items: self.hideOriginals || false,\n name: _.escape(name || self.$(\".collection-name\").val()),\n element_identifiers: self.paired.map(function (pair) {\n return self._pairToJSON(pair);\n })\n };\n //this.debug( JSON.stringify( ajaxData ) );\n self.blocking = true;\n return jQuery.ajax(url, {\n type: \"POST\",\n contentType: \"application/json\",\n dataType: \"json\",\n data: JSON.stringify(ajaxData)\n }).always(function () {\n self.blocking = false;\n }).fail(function (xhr, status, message) {\n self._ajaxErrHandler(xhr, status, message);\n }).done(function (response, message, xhr) {\n //this.info( 'ok', response, message, xhr );\n self.trigger(\"collection:created\", response, message, xhr);\n self.metric(\"collection:created\", response);\n if (typeof self.oncreate === \"function\") {\n self.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n /** handle ajax errors with feedback and details to the user (if available) */\n _ajaxErrHandler: function _ajaxErrHandler(xhr, status, message) {\n this.error(xhr, status, message);\n var self = this;\n var content = (0, _localization2.default)(\"An error occurred while creating this collection\");\n if (xhr) {\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += \": \" + (0, _localization2.default)(\"Galaxy could not be reached and may be updating.\") + (0, _localization2.default)(\" Try again in a few minutes.\");\n } else if (xhr.responseJSON) {\n content += \"
\" + JSON.stringify(xhr.responseJSON) + \"
\";\n } else {\n content += \": \" + message;\n }\n }\n self._showAlert(content, \"alert-danger\");\n },\n\n // ------------------------------------------------------------------------ rendering\n /** render the entire interface */\n render: function render(speed, callback) {\n //this.debug( '-- _render' );\n //this.$el.empty().html( this.templates.main() );\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function _renderHeader(speed, callback) {\n //this.debug( '-- _renderHeader' );\n var $header = this.$(\".header\").empty().html(this.templates.header()).find(\".help-content\").prepend($(this.templates.helpContent()));\n\n this._renderFilters();\n return $header;\n },\n /** fill the filter inputs with the filter values */\n _renderFilters: function _renderFilters() {\n return this.$(\".forward-column .column-header input\").val(this.filters[0]).add(this.$(\".reverse-column .column-header input\").val(this.filters[1]));\n },\n\n /** render the middle including unpaired and paired sections (which may be hidden) */\n _renderMiddle: function _renderMiddle(speed, callback) {\n var $middle = this.$(\".middle\").empty().html(this.templates.middle());\n\n // (re-) hide the un/paired panels based on instance vars\n if (this.unpairedPanelHidden) {\n this.$(\".unpaired-columns\").hide();\n } else if (this.pairedPanelHidden) {\n this.$(\".paired-columns\").hide();\n }\n\n this._renderUnpaired();\n this._renderPaired();\n return $middle;\n },\n /** render the unpaired section, showing datasets accrd. to filters, update the unpaired counts */\n _renderUnpaired: function _renderUnpaired(speed, callback) {\n //this.debug( '-- _renderUnpaired' );\n var self = this;\n\n var $fwd;\n var $rev;\n var $prd = [];\n var split = this._splitByFilters();\n // update unpaired counts\n this.$(\".forward-column .title\").text([split[0].length, (0, _localization2.default)(\"unpaired forward\")].join(\" \"));\n this.$(\".forward-column .unpaired-info\").text(this._renderUnpairedDisplayStr(this.unpaired.length - split[0].length));\n this.$(\".reverse-column .title\").text([split[1].length, (0, _localization2.default)(\"unpaired reverse\")].join(\" \"));\n this.$(\".reverse-column .unpaired-info\").text(this._renderUnpairedDisplayStr(this.unpaired.length - split[1].length));\n\n this.$(\".unpaired-columns .column-datasets\").empty();\n\n // show/hide the auto pair button if any unpaired are left\n this.$(\".autopair-link\").toggle(this.unpaired.length !== 0);\n if (this.unpaired.length === 0) {\n this._renderUnpairedEmpty();\n return;\n }\n\n // create the dataset dom arrays\n $rev = split[1].map(function (dataset, i) {\n // if there'll be a fwd dataset across the way, add a button to pair the row\n if (split[0][i] !== undefined && split[0][i] !== dataset) {\n $prd.push(self._renderPairButton());\n }\n return self._renderUnpairedDataset(dataset);\n });\n $fwd = split[0].map(function (dataset) {\n return self._renderUnpairedDataset(dataset);\n });\n\n if (!$fwd.length && !$rev.length) {\n this._renderUnpairedNotShown();\n return;\n }\n // add to appropo cols\n //TODO: not the best way to render - consider rendering the entire unpaired-columns section in a fragment\n // and swapping out that\n this.$(\".unpaired-columns .forward-column .column-datasets\").append($fwd).add(this.$(\".unpaired-columns .paired-column .column-datasets\").append($prd)).add(this.$(\".unpaired-columns .reverse-column .column-datasets\").append($rev));\n this._adjUnpairedOnScrollbar();\n },\n /** return a string to display the count of filtered out datasets */\n _renderUnpairedDisplayStr: function _renderUnpairedDisplayStr(numFiltered) {\n return [\"(\", numFiltered, \" \", (0, _localization2.default)(\"filtered out\"), \")\"].join(\"\");\n },\n /** return an unattached jQuery DOM element to represent an unpaired dataset */\n _renderUnpairedDataset: function _renderUnpairedDataset(dataset) {\n //TODO: to underscore template\n return $(\"\").attr(\"id\", \"dataset-\" + dataset.id).addClass(\"dataset unpaired\").attr(\"draggable\", true).addClass(dataset.selected ? \"selected\" : \"\").append($(\"\").addClass(\"dataset-name\").text(dataset.name))\n //??\n .data(\"dataset\", dataset);\n },\n /** render the button that may go between unpaired datasets, allowing the user to pair a row */\n _renderPairButton: function _renderPairButton() {\n //TODO: *not* a dataset - don't pretend like it is\n return $(\"\").addClass(\"dataset unpaired\").append($(\"\").addClass(\"dataset-name\").text((0, _localization2.default)(\"Pair these datasets\")));\n },\n /** a message to display when no unpaired left */\n _renderUnpairedEmpty: function _renderUnpairedEmpty() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(\"(\" + (0, _localization2.default)(\"no remaining unpaired datasets\") + \")\");\n this.$(\".unpaired-columns .paired-column .column-datasets\").empty().prepend($msg);\n return $msg;\n },\n /** a message to display when no unpaired can be shown with the current filters */\n _renderUnpairedNotShown: function _renderUnpairedNotShown() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(\"(\" + (0, _localization2.default)(\"no datasets were found matching the current filters\") + \")\");\n this.$(\".unpaired-columns .paired-column .column-datasets\").empty().prepend($msg);\n return $msg;\n },\n /** try to detect if the unpaired section has a scrollbar and adjust left column for better centering of all */\n _adjUnpairedOnScrollbar: function _adjUnpairedOnScrollbar() {\n var $unpairedColumns = this.$(\".unpaired-columns\").last();\n\n var $firstDataset = this.$(\".unpaired-columns .reverse-column .dataset\").first();\n\n if (!$firstDataset.length) {\n return;\n }\n\n var ucRight = $unpairedColumns.offset().left + $unpairedColumns.outerWidth();\n\n var dsRight = $firstDataset.offset().left + $firstDataset.outerWidth();\n\n var rightDiff = Math.floor(ucRight) - Math.floor(dsRight);\n //this.debug( 'rightDiff:', ucRight, '-', dsRight, '=', rightDiff );\n this.$(\".unpaired-columns .forward-column\").css(\"margin-left\", rightDiff > 0 ? rightDiff : 0);\n },\n\n /** render the paired section and update counts of paired datasets */\n _renderPaired: function _renderPaired(speed, callback) {\n //this.debug( '-- _renderPaired' );\n this.$(\".paired-column-title .title\").text([this.paired.length, (0, _localization2.default)(\"paired\")].join(\" \"));\n // show/hide the unpair all link\n this.$(\".unpair-all-link\").toggle(this.paired.length !== 0);\n if (this.paired.length === 0) {\n this._renderPairedEmpty();\n return;\n //TODO: would be best to return here (the $columns)\n } else {\n // show/hide 'remove extensions link' when any paired and they seem to have extensions\n this.$(\".remove-extensions-link\").show();\n }\n\n this.$(\".paired-columns .column-datasets\").empty();\n var self = this;\n this.paired.forEach(function (pair, i) {\n //TODO: cache these?\n var pairView = new PairView({ pair: pair });\n self.$(\".paired-columns .column-datasets\").append(pairView.render().$el).append(['\"].join(\"\"));\n });\n },\n /** a message to display when none paired */\n _renderPairedEmpty: function _renderPairedEmpty() {\n var $msg = $('').text(\"(\" + (0, _localization2.default)(\"no paired datasets yet\") + \")\");\n this.$(\".paired-columns .column-datasets\").empty().prepend($msg);\n return $msg;\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\",\n \".remove-extensions\": \"removeExtensions\"\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function _addPluginComponents() {\n this._chooseFiltersPopover(\".choose-filters-link\");\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", \"rgba( 64, 255, 255, 1.0 )\");\n },\n\n /** build a filter selection popover allowing selection of common filter pairs */\n _chooseFiltersPopover: function _chooseFiltersPopover(selector) {\n function filterChoice(val1, val2) {\n return ['\"].join(\"\");\n }\n var $popoverContent = $(_.template(['
', '
', (0, _localization2.default)(\"Choose from the following filters to change which unpaired reads are shown in the display\"), \":
\"].join(\"\"))({}));\n\n return this.$(selector).popover({\n container: \".collection-creator\",\n placement: \"bottom\",\n html: true,\n //animation : false,\n content: $popoverContent\n });\n },\n\n /** add (or clear if clear is truthy) a validation warning to what */\n _validationWarning: function _validationWarning(what, clear) {\n var VALIDATION_CLASS = \"validation-warning\";\n if (what === \"name\") {\n what = this.$(\".collection-name\").add(this.$(\".collection-name-prompt\"));\n this.$(\".collection-name\").focus().select();\n }\n if (clear) {\n what = what || this.$(\".\" + VALIDATION_CLASS);\n what.removeClass(VALIDATION_CLASS);\n } else {\n what.addClass(VALIDATION_CLASS);\n }\n },\n\n // ------------------------------------------------------------------------ events\n /** set up event handlers on self */\n _setUpBehaviors: function _setUpBehaviors() {\n this.once(\"rendered\", function () {\n this.trigger(\"rendered:initial\", this);\n });\n\n this.on(\"pair:new\", function () {\n //TODO: ideally only re-render the columns (or even elements) involved\n this._renderUnpaired();\n this._renderPaired();\n\n // scroll to bottom where new pairs are added\n //TODO: this doesn't seem to work - innerHeight sticks at 133...\n // may have to do with improper flex columns\n //var $pairedView = this.$( '.paired-columns' );\n //$pairedView.scrollTop( $pairedView.innerHeight() );\n //this.debug( $pairedView.height() )\n this.$(\".paired-columns\").scrollTop(8000000);\n });\n this.on(\"pair:unpair\", function (pairs) {\n //TODO: ideally only re-render the columns (or even elements) involved\n this._renderUnpaired();\n this._renderPaired();\n this.splitView();\n });\n\n this.on(\"filter-change\", function () {\n this.filters = [this.$(\".forward-unpaired-filter input\").val(), this.$(\".reverse-unpaired-filter input\").val()];\n this.metric(\"filter-change\", this.filters);\n this._renderFilters();\n this._renderUnpaired();\n });\n\n this.on(\"autopair\", function () {\n this._renderUnpaired();\n this._renderPaired();\n\n var message;\n var msgClass = null;\n if (this.paired.length) {\n msgClass = \"alert-success\";\n message = this.paired.length + \" \" + (0, _localization2.default)(\"pairs created\");\n if (!this.unpaired.length) {\n message += \": \" + (0, _localization2.default)(\"all datasets have been successfully paired\");\n this.hideUnpaired();\n this.$(\".collection-name\").focus();\n }\n } else {\n message = (0, _localization2.default)([\"Could not automatically create any pairs from the given dataset names.\", \"You may want to choose or enter different filters and try auto-pairing again.\", \"Close this message using the X on the right to view more help.\"].join(\" \"));\n }\n this._showAlert(message, msgClass);\n });\n\n //this.on( 'all', function(){\n // this.info( arguments );\n //});\n return this;\n },\n\n events: {\n // header\n \"click .more-help\": \"_clickMoreHelp\",\n \"click .less-help\": \"_clickLessHelp\",\n \"click .main-help\": \"_toggleHelp\",\n \"click .header .alert button\": \"_hideAlert\",\n \"click .forward-column .column-title\": \"_clickShowOnlyUnpaired\",\n \"click .reverse-column .column-title\": \"_clickShowOnlyUnpaired\",\n \"click .unpair-all-link\": \"_clickUnpairAll\",\n //TODO: this seems kinda backasswards - re-sending jq event as a backbone event, can we listen directly?\n \"change .forward-unpaired-filter input\": function changeForwardUnpairedFilterInput(ev) {\n this.trigger(\"filter-change\");\n },\n \"focus .forward-unpaired-filter input\": function focusForwardUnpairedFilterInput(ev) {\n $(ev.currentTarget).select();\n },\n \"click .autopair-link\": \"_clickAutopair\",\n \"click .choose-filters .filter-choice\": \"_clickFilterChoice\",\n \"click .clear-filters-link\": \"_clearFilters\",\n \"change .reverse-unpaired-filter input\": function changeReverseUnpairedFilterInput(ev) {\n this.trigger(\"filter-change\");\n },\n \"focus .reverse-unpaired-filter input\": function focusReverseUnpairedFilterInput(ev) {\n $(ev.currentTarget).select();\n },\n // unpaired\n \"click .forward-column .dataset.unpaired\": \"_clickUnpairedDataset\",\n \"click .reverse-column .dataset.unpaired\": \"_clickUnpairedDataset\",\n \"click .paired-column .dataset.unpaired\": \"_clickPairRow\",\n \"click .unpaired-columns\": \"clearSelectedUnpaired\",\n \"mousedown .unpaired-columns .dataset\": \"_mousedownUnpaired\",\n // divider\n \"click .paired-column-title\": \"_clickShowOnlyPaired\",\n \"mousedown .flexible-partition-drag\": \"_startPartitionDrag\",\n // paired\n \"click .paired-columns .dataset.paired\": \"selectPair\",\n \"click .paired-columns\": \"clearSelectedPaired\",\n \"click .paired-columns .pair-name\": \"_clickPairName\",\n \"click .unpair-btn\": \"_clickUnpair\",\n // paired - drop target\n //'dragenter .paired-columns' : '_dragenterPairedColumns',\n //'dragleave .paired-columns .column-datasets': '_dragleavePairedColumns',\n \"dragover .paired-columns .column-datasets\": \"_dragoverPairedColumns\",\n \"drop .paired-columns .column-datasets\": \"_dropPairedColumns\",\n\n \"pair.dragstart .paired-columns .column-datasets\": \"_pairDragstart\",\n \"pair.dragend .paired-columns .column-datasets\": \"_pairDragend\",\n\n // footer\n \"change .remove-extensions\": function changeRemoveExtensions(ev) {\n this.toggleExtensions();\n },\n \"change .collection-name\": \"_changeName\",\n \"keydown .collection-name\": \"_nameCheckForEnter\",\n \"change .hide-originals\": \"_changeHideOriginals\",\n \"click .cancel-create\": \"_cancelCreate\",\n \"click .create-collection\": \"_clickCreate\" //,\n },\n\n /** toggle between showing only unpaired and split view */\n _clickShowOnlyUnpaired: function _clickShowOnlyUnpaired(ev) {\n //this.debug( 'click unpaired', ev.currentTarget );\n if (this.$(\".paired-columns\").is(\":visible\")) {\n this.hidePaired();\n } else {\n this.splitView();\n }\n },\n /** toggle between showing only paired and split view */\n _clickShowOnlyPaired: function _clickShowOnlyPaired(ev) {\n //this.debug( 'click paired' );\n if (this.$(\".unpaired-columns\").is(\":visible\")) {\n this.hideUnpaired();\n } else {\n this.splitView();\n }\n },\n\n /** hide unpaired, show paired */\n hideUnpaired: function hideUnpaired(speed, callback) {\n this.unpairedPanelHidden = true;\n this.pairedPanelHidden = false;\n this._renderMiddle(speed, callback);\n },\n /** hide paired, show unpaired */\n hidePaired: function hidePaired(speed, callback) {\n this.unpairedPanelHidden = false;\n this.pairedPanelHidden = true;\n this._renderMiddle(speed, callback);\n },\n /** show both paired and unpaired (splitting evenly) */\n splitView: function splitView(speed, callback) {\n this.unpairedPanelHidden = this.pairedPanelHidden = false;\n this._renderMiddle(speed, callback);\n return this;\n },\n\n /** unpair all paired and do other super neat stuff which I'm not really sure about yet... */\n _clickUnpairAll: function _clickUnpairAll(ev) {\n this.metric(\"unpairAll\");\n this.unpairAll();\n },\n\n /** attempt to autopair */\n _clickAutopair: function _clickAutopair(ev) {\n var paired = this.autoPair();\n this.metric(\"autopair\", paired.length, this.unpaired.length);\n this.trigger(\"autopair\");\n },\n\n /** set the filters based on the data attributes of the button click target */\n _clickFilterChoice: function _clickFilterChoice(ev) {\n var $selected = $(ev.currentTarget);\n this.$(\".forward-unpaired-filter input\").val($selected.data(\"forward\"));\n this.$(\".reverse-unpaired-filter input\").val($selected.data(\"reverse\"));\n this._hideChooseFilters();\n this.trigger(\"filter-change\");\n },\n\n /** hide the choose filters popover */\n _hideChooseFilters: function _hideChooseFilters() {\n //TODO: update bootstrap and remove the following hack\n // see also: https://github.com/twbs/bootstrap/issues/10260\n this.$(\".choose-filters-link\").popover(\"hide\");\n this.$(\".popover\").css(\"display\", \"none\");\n },\n\n /** clear both filters */\n _clearFilters: function _clearFilters(ev) {\n this.$(\".forward-unpaired-filter input\").val(\"\");\n this.$(\".reverse-unpaired-filter input\").val(\"\");\n this.trigger(\"filter-change\");\n },\n\n // ........................................................................ unpaired\n /** select an unpaired dataset */\n _clickUnpairedDataset: function _clickUnpairedDataset(ev) {\n ev.stopPropagation();\n return this.toggleSelectUnpaired($(ev.currentTarget));\n },\n\n /** Toggle the selection of an unpaired dataset representation.\n * @param [jQuery] $dataset the unpaired dataset dom rep to select\n * @param [Boolean] options.force if defined, force selection based on T/F; otherwise, toggle\n */\n toggleSelectUnpaired: function toggleSelectUnpaired($dataset, options) {\n options = options || {};\n var dataset = $dataset.data(\"dataset\");\n\n var select = options.force !== undefined ? options.force : !$dataset.hasClass(\"selected\");\n\n //this.debug( id, options.force, $dataset, dataset );\n if (!$dataset.length || dataset === undefined) {\n return $dataset;\n }\n\n if (select) {\n $dataset.addClass(\"selected\");\n if (!options.waitToPair) {\n this.pairAllSelected();\n }\n } else {\n $dataset.removeClass(\"selected\");\n //delete dataset.selected;\n }\n return $dataset;\n },\n\n /** pair all the currently selected unpaired datasets */\n pairAllSelected: function pairAllSelected(options) {\n options = options || {};\n var self = this;\n var fwds = [];\n var revs = [];\n var pairs = [];\n self.$(\".unpaired-columns .forward-column .dataset.selected\").each(function () {\n fwds.push($(this).data(\"dataset\"));\n });\n self.$(\".unpaired-columns .reverse-column .dataset.selected\").each(function () {\n revs.push($(this).data(\"dataset\"));\n });\n fwds.length = revs.length = Math.min(fwds.length, revs.length);\n //this.debug( fwds );\n //this.debug( revs );\n fwds.forEach(function (fwd, i) {\n try {\n pairs.push(self._pair(fwd, revs[i], { silent: true }));\n } catch (err) {\n //TODO: preserve selected state of those that couldn't be paired\n //TODO: warn that some could not be paired\n self.error(err);\n }\n });\n if (pairs.length && !options.silent) {\n this.trigger(\"pair:new\", pairs);\n }\n return pairs;\n },\n\n /** clear the selection on all unpaired datasets */\n clearSelectedUnpaired: function clearSelectedUnpaired() {\n this.$(\".unpaired-columns .dataset.selected\").removeClass(\"selected\");\n },\n\n /** when holding down the shift key on a click, 'paint' the moused over datasets as selected */\n _mousedownUnpaired: function _mousedownUnpaired(ev) {\n if (ev.shiftKey) {\n var self = this;\n var $startTarget = $(ev.target).addClass(\"selected\");\n\n var moveListener = function moveListener(ev) {\n self.$(ev.target).filter(\".dataset\").addClass(\"selected\");\n };\n\n $startTarget.parent().on(\"mousemove\", moveListener);\n\n // on any mouseup, stop listening to the move and try to pair any selected\n $(document).one(\"mouseup\", function (ev) {\n $startTarget.parent().off(\"mousemove\", moveListener);\n self.pairAllSelected();\n });\n }\n },\n\n /** attempt to pair two datasets directly across from one another */\n _clickPairRow: function _clickPairRow(ev) {\n //if( !ev.currentTarget ){ return true; }\n var rowIndex = $(ev.currentTarget).index();\n\n var fwd = $(\".unpaired-columns .forward-column .dataset\").eq(rowIndex).data(\"dataset\");\n\n var rev = $(\".unpaired-columns .reverse-column .dataset\").eq(rowIndex).data(\"dataset\");\n\n //this.debug( 'row:', rowIndex, fwd, rev );\n this._pair(fwd, rev);\n },\n\n // ........................................................................ divider/partition\n /** start dragging the visible divider/partition between unpaired and paired panes */\n _startPartitionDrag: function _startPartitionDrag(ev) {\n var self = this;\n var startingY = ev.pageY;\n //this.debug( 'partition drag START:', ev );\n $(\"body\").css(\"cursor\", \"ns-resize\");\n self.$(\".flexible-partition-drag\").css(\"color\", \"black\");\n\n function endDrag(ev) {\n self.$(\".flexible-partition-drag\").css(\"color\", \"\");\n $(\"body\").css(\"cursor\", \"\").unbind(\"mousemove\", trackMouse);\n }\n function trackMouse(ev) {\n var offset = ev.pageY - startingY;\n if (!self.adjPartition(offset)) {\n $(\"body\").trigger(\"mouseup\");\n }\n self._adjUnpairedOnScrollbar();\n startingY += offset;\n }\n $(\"body\").mousemove(trackMouse);\n $(\"body\").one(\"mouseup\", endDrag);\n },\n\n /** adjust the parition up/down +/-adj pixels */\n adjPartition: function adjPartition(adj) {\n var $unpaired = this.$(\".unpaired-columns\");\n var $paired = this.$(\".paired-columns\");\n var unpairedHi = parseInt($unpaired.css(\"height\"), 10);\n var pairedHi = parseInt($paired.css(\"height\"), 10);\n //this.debug( adj, 'hi\\'s:', unpairedHi, pairedHi, unpairedHi + adj, pairedHi - adj );\n\n unpairedHi = Math.max(10, unpairedHi + adj);\n pairedHi = pairedHi - adj;\n\n var movingUpwards = adj < 0;\n // when the divider gets close to the top - lock into hiding the unpaired section\n if (movingUpwards) {\n if (this.unpairedPanelHidden) {\n return false;\n } else if (unpairedHi <= 10) {\n this.hideUnpaired();\n return false;\n }\n } else {\n if (this.unpairedPanelHidden) {\n $unpaired.show();\n this.unpairedPanelHidden = false;\n }\n }\n\n // when the divider gets close to the bottom - lock into hiding the paired section\n if (!movingUpwards) {\n if (this.pairedPanelHidden) {\n return false;\n } else if (pairedHi <= 15) {\n this.hidePaired();\n return false;\n }\n } else {\n if (this.pairedPanelHidden) {\n $paired.show();\n this.pairedPanelHidden = false;\n }\n }\n\n $unpaired.css({\n height: unpairedHi + \"px\",\n flex: \"0 0 auto\"\n });\n return true;\n },\n\n // ........................................................................ paired\n /** select a pair when clicked */\n selectPair: function selectPair(ev) {\n ev.stopPropagation();\n $(ev.currentTarget).toggleClass(\"selected\");\n },\n\n /** deselect all pairs */\n clearSelectedPaired: function clearSelectedPaired(ev) {\n this.$(\".paired-columns .dataset.selected\").removeClass(\"selected\");\n },\n\n /** rename a pair when the pair name is clicked */\n _clickPairName: function _clickPairName(ev) {\n ev.stopPropagation();\n var $name = $(ev.currentTarget);\n var $pair = $name.parent().parent();\n var index = $pair.index(\".dataset.paired\");\n var pair = this.paired[index];\n var response = prompt(\"Enter a new name for the pair:\", pair.name);\n if (response) {\n pair.name = response;\n // set a flag (which won't be passed in json creation) for manual naming so we don't overwrite these\n // when adding/removing extensions\n //hackish\n pair.customizedName = true;\n $name.text(pair.name);\n }\n },\n\n /** unpair this pair */\n _clickUnpair: function _clickUnpair(ev) {\n //if( !ev.currentTarget ){ return true; }\n var pairIndex = Math.floor($(ev.currentTarget).index(\".unpair-btn\"));\n //this.debug( 'pair:', pairIndex );\n this._unpair(this.paired[pairIndex]);\n },\n\n // ........................................................................ paired - drag and drop re-ordering\n //_dragenterPairedColumns : function( ev ){\n // this.debug( '_dragenterPairedColumns:', ev );\n //},\n //_dragleavePairedColumns : function( ev ){\n // //this.debug( '_dragleavePairedColumns:', ev );\n //},\n /** track the mouse drag over the paired list adding a placeholder to show where the drop would occur */\n _dragoverPairedColumns: function _dragoverPairedColumns(ev) {\n //this.debug( '_dragoverPairedColumns:', ev );\n ev.preventDefault();\n\n var $list = this.$(\".paired-columns .column-datasets\");\n this._checkForAutoscroll($list, ev.originalEvent.clientY);\n //this.debug( ev.originalEvent.clientX, ev.originalEvent.clientY );\n var $nearest = this._getNearestPairedDatasetLi(ev.originalEvent.clientY);\n\n $(\".element-drop-placeholder\").remove();\n var $placeholder = $('');\n if (!$nearest.length) {\n $list.append($placeholder);\n } else {\n $nearest.before($placeholder);\n }\n },\n\n /** If the mouse is near enough to the list's top or bottom, scroll the list */\n _checkForAutoscroll: function _checkForAutoscroll($element, y) {\n var AUTOSCROLL_SPEED = 2;\n var offset = $element.offset();\n var scrollTop = $element.scrollTop();\n var upperDist = y - offset.top;\n var lowerDist = offset.top + $element.outerHeight() - y;\n //this.debug( '_checkForAutoscroll:', scrollTop, upperDist, lowerDist );\n if (upperDist >= 0 && upperDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop - AUTOSCROLL_SPEED);\n } else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop + AUTOSCROLL_SPEED);\n }\n },\n\n /** get the nearest *previous* paired dataset PairView based on the mouse's Y coordinate.\n * If the y is at the end of the list, return an empty jQuery object.\n */\n _getNearestPairedDatasetLi: function _getNearestPairedDatasetLi(y) {\n var WIGGLE = 4;\n var lis = this.$(\".paired-columns .column-datasets li\").toArray();\n for (var i = 0; i < lis.length; i++) {\n var $li = $(lis[i]);\n var top = $li.offset().top;\n var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;\n if (top + halfHeight > y && top - halfHeight < y) {\n //this.debug( y, top + halfHeight, top - halfHeight )\n return $li;\n }\n }\n return $();\n },\n /** drop (dragged/selected PairViews) onto the list, re-ordering both the DOM and the internal array of pairs */\n _dropPairedColumns: function _dropPairedColumns(ev) {\n // both required for firefox\n ev.preventDefault();\n ev.dataTransfer.dropEffect = \"move\";\n\n var $nearest = this._getNearestPairedDatasetLi(ev.originalEvent.clientY);\n if ($nearest.length) {\n this.$dragging.insertBefore($nearest);\n } else {\n // no nearest before - insert after last element (unpair button)\n this.$dragging.insertAfter(this.$(\".paired-columns .unpair-btn\").last());\n }\n // resync the creator's list of paired based on the new DOM order\n this._syncPairsToDom();\n return false;\n },\n /** resync the creator's list of paired based on the DOM order of pairs */\n _syncPairsToDom: function _syncPairsToDom() {\n var newPaired = [];\n //TODO: doesn't seem wise to use the dom to store these - can't we sync another way?\n this.$(\".paired-columns .dataset.paired\").each(function () {\n newPaired.push($(this).data(\"pair\"));\n });\n //this.debug( newPaired );\n this.paired = newPaired;\n this._renderPaired();\n },\n /** drag communication with pair sub-views: dragstart */\n _pairDragstart: function _pairDragstart(ev, pair) {\n //this.debug( '_pairDragstart', ev, pair )\n // auto select the pair causing the event and move all selected\n pair.$el.addClass(\"selected\");\n var $selected = this.$(\".paired-columns .dataset.selected\");\n this.$dragging = $selected;\n },\n /** drag communication with pair sub-views: dragend - remove the placeholder */\n _pairDragend: function _pairDragend(ev, pair) {\n //this.debug( '_pairDragend', ev, pair )\n $(\".element-drop-placeholder\").remove();\n this.$dragging = null;\n },\n\n // ........................................................................ footer\n toggleExtensions: function toggleExtensions(force) {\n var self = this;\n self.removeExtensions = force !== undefined ? force : !self.removeExtensions;\n\n _.each(self.paired, function (pair) {\n // don't overwrite custom names\n if (pair.customizedName) {\n return;\n }\n pair.name = self._guessNameForPair(pair.forward, pair.reverse);\n });\n\n self._renderPaired();\n self._renderFooter();\n },\n\n // ------------------------------------------------------------------------ misc\n /** debug a dataset list */\n _printList: function _printList(list) {\n var self = this;\n _.each(list, function (e) {\n if (list === self.paired) {\n self._printPair(e);\n } else {\n self.debug(e);\n }\n });\n },\n\n /** print a pair Object */\n _printPair: function _printPair(pair) {\n this.debug(pair.forward.name, pair.reverse.name, \": ->\", pair.name);\n },\n\n /** string rep */\n toString: function toString() {\n return \"PairedCollectionCreator\";\n },\n\n templates: _.extend({}, _baseCreator2.default.CollectionCreatorMixin._creatorTemplates, {\n /** the header (not including help text) */\n header: _.template(['
\"].join(\"\")),\n\n /** the middle: unpaired, divider, and paired */\n middle: _.template([\n // contains two flex rows (rows that fill available space) and a divider btwn\n '
\"].join(\"\")),\n\n /** help content */\n helpContent: _.template([\"
\", (0, _localization2.default)([\"Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). \", \"These collections can be passed to tools and workflows in order to have analyses done on each member of \", \"the entire group. This interface allows you to create a collection, choose which datasets are paired, \", \"and re-order the final collection.\"].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Unpaired datasets are shown in the unpaired section ', \"(hover over the underlined words to highlight below). \", 'Paired datasets are shown in the paired section.', \"
To pair datasets, you can:\", \"
Click a dataset in the \", 'forward column ', \"to select it then click a dataset in the \", 'reverse column.', \"
\", '
Click one of the \"Pair these datasets\" buttons in the ', 'middle column ', \"to pair the datasets in a particular row.\", \"
\", '
Click \"Auto-pair\" ', \"to have your datasets automatically paired based on name.\", \"
\", \"
\"].join(\"\")), \"\", \"
\", (0, _localization2.default)([\"
You can filter what is shown in the unpaired sections by:\", \"
Entering partial dataset names in either the \", 'forward filter or ', 'reverse filter.', \"
\", \"
Choosing from a list of preset filters by clicking the \", '\"Choose filters\" link.', \"
Clearing the filters by clicking the \", '\"Clear filters\" link.', \"
\", \"
\"].join(\"\")), \"\", \"
\", (0, _localization2.default)([\"To unpair individual dataset pairs, click the \", 'unpair buttons ( ). ', 'Click the \"Unpair all\" link to unpair all pairs.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['You can include or remove the file extensions (e.g. \".fastq\") from your pair names by toggling the ', '\"Remove file extensions from pair names?\" control.'].join(\"\")), \"
\", \"
\", (0, _localization2.default)(['Once your collection is complete, enter a name and ', 'click \"Create list\". ', \"(Note: you do not have to pair all unpaired datasets to finish.)\"].join(\"\")), \"
\"].join(\"\"))\n })\n});\n\n//=============================================================================\n/** a modal version of the paired collection creator */\nvar pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(datasets, options) {\n var deferred = jQuery.Deferred();\n var creator;\n\n options = _.defaults(options || {}, {\n datasets: datasets,\n oncancel: function oncancel() {\n Galaxy.modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function oncreate(creator, response) {\n Galaxy.modal.hide();\n deferred.resolve(response);\n }\n });\n\n if (!window.Galaxy || !Galaxy.modal) {\n throw new Error(\"Galaxy or Galaxy.modal not found\");\n }\n\n creator = new PairedCollectionCreator(options);\n Galaxy.modal.show({\n title: \"Create a collection of paired datasets\",\n body: creator.$el,\n width: \"80%\",\n height: \"800px\",\n closing_events: true\n });\n creator.render();\n window.creator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n//=============================================================================\nfunction createListOfPairsCollection(collection, defaultHideSourceItems) {\n var elements = collection.toJSON();\n //TODO: validate elements\n return pairedCollectionCreatorModal(elements, {\n historyId: collection.historyId,\n defaultHideSourceItems: defaultHideSourceItems\n });\n}\n\n//=============================================================================\nexports.default = {\n PairedCollectionCreator: PairedCollectionCreator,\n pairedCollectionCreatorModal: pairedCollectionCreatorModal,\n createListOfPairsCollection: createListOfPairsCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0), __webpack_require__(0)))\n\n/***/ }),\n/* 163 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n//=============================================================================\n/**\n(Imported for edit distance algorith. From: https://gist.github.com/andrei-m/982927)\nCopyright (c) 2011 Andrei Mackenzie\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the\nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n// Compute the edit distance between the two given strings\n//exports.getEditDistance = function(a, b){\nfunction levenshteinDistance(a, b) {\n if (a.length === 0) {\n return b.length;\n }\n if (b.length === 0) {\n return a.length;\n }\n\n var matrix = [];\n\n // increment along the first column of each row\n var i;\n for (i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n\n // increment each column in the first row\n var j;\n for (j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n\n // Fill in the rest of the matrix\n for (i = 1; i <= b.length; i++) {\n for (j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution\n Math.min(matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j] + 1)); // deletion\n }\n }\n }\n\n //console.debug( '\\t\\t levenshteinDistance', a, b, matrix[b.length][a.length] );\n return matrix[b.length][a.length];\n}\n\n//=============================================================================\nexports.default = levenshteinDistance;\n\n/***/ }),\n/* 164 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _queryStringParsing = __webpack_require__(8);\n\nvar _queryStringParsing2 = _interopRequireDefault(_queryStringParsing);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Contains descriptive dictionaries describing user forms */\nvar Model = Backbone.Model.extend({\n initialize: function initialize(options) {\n options = options || {};\n options.user_id = options.user_id || Galaxy.user.id;\n this.set({\n user_id: options.user_id,\n information: {\n title: \"Manage information\",\n description: \"Edit your email, addresses and custom parameters or change your username.\",\n url: \"api/users/\" + options.user_id + \"/information/inputs\",\n icon: \"fa-user\",\n redirect: \"user\"\n },\n password: {\n title: \"Change password\",\n description: \"Allows you to change your login credentials.\",\n icon: \"fa-unlock-alt\",\n url: \"api/users/\" + options.user_id + \"/password/inputs\",\n submit_title: \"Save password\",\n redirect: \"user\"\n },\n communication: {\n title: \"Change communication settings\",\n description: \"Enable or disable the communication feature to chat with other users.\",\n url: \"api/users/\" + options.user_id + \"/communication/inputs\",\n icon: \"fa-comments-o\",\n redirect: \"user\"\n },\n permissions: {\n title: \"Set dataset permissions for new histories\",\n description: \"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.\",\n url: \"api/users/\" + options.user_id + \"/permissions/inputs\",\n icon: \"fa-users\",\n submit_title: \"Save permissions\",\n redirect: \"user\"\n },\n api_key: {\n title: \"Manage API key\",\n description: \"Access your current API key or create a new one.\",\n url: \"api/users/\" + options.user_id + \"/api_key/inputs\",\n icon: \"fa-key\",\n submit_title: \"Create a new key\",\n submit_icon: \"fa-check\"\n },\n toolbox_filters: {\n title: \"Manage Toolbox filters\",\n description: \"Customize your Toolbox by displaying or omitting sets of Tools.\",\n url: \"api/users/\" + options.user_id + \"/toolbox_filters/inputs\",\n icon: \"fa-filter\",\n submit_title: \"Save filters\",\n redirect: \"user\"\n },\n openids: {\n title: \"Manage OpenIDs\",\n description: \"Associate OpenIDs with your account.\",\n icon: \"fa-openid\",\n onclick: function onclick() {\n window.location.href = Galaxy.root + \"user/openid_manage?cntrller=user&use_panels=True\";\n }\n },\n custom_builds: {\n title: \"Manage custom builds\",\n description: \"Add or remove custom builds using history datasets.\",\n icon: \"fa-cubes\",\n onclick: function onclick() {\n window.location.href = Galaxy.root + \"custom_builds\";\n }\n },\n logout: {\n title: \"Sign out\",\n description: \"Click here to sign out of all sessions.\",\n icon: \"fa-sign-out\",\n onclick: function onclick() {\n Galaxy.modal.show({\n title: \"Sign out\",\n body: \"Do you want to continue and sign out of all active sessions?\",\n buttons: {\n Cancel: function Cancel() {\n Galaxy.modal.hide();\n },\n \"Sign out\": function SignOut() {\n window.location.href = Galaxy.root + \"user/logout?session_csrf_token=\" + Galaxy.session_csrf_token;\n }\n }\n });\n }\n }\n });\n }\n});\n\n/** View of the main user preference panel with links to individual user forms */\n/** User Preferences view */\nvar View = Backbone.View.extend({\n title: \"User Preferences\",\n initialize: function initialize() {\n this.model = new Model();\n this.setElement(\"\");\n this.render();\n },\n\n render: function render() {\n var self = this;\n var config = Galaxy.config;\n $.getJSON(Galaxy.root + \"api/users/\" + Galaxy.user.id, function (data) {\n self.$preferences = $(\"\").addClass(\"ui-panel\").append($(\"\").append(\"User preferences\")).append($(\"\").append(\"You are logged in as \" + _.escape(data.email) + \".\")).append(self.$table = $(\"
\").addClass(\"ui-panel-table\"));\n var message = _queryStringParsing2.default.get(\"message\");\n var status = _queryStringParsing2.default.get(\"status\");\n if (message && status) {\n self.$preferences.prepend(new _uiMisc2.default.Message({ message: message, status: status }).$el);\n }\n if (!config.use_remote_user) {\n self._addLink(\"information\");\n self._addLink(\"password\");\n }\n if (config.enable_communication_server) {\n self._addLink(\"communication\");\n }\n self._addLink(\"custom_builds\");\n self._addLink(\"permissions\");\n self._addLink(\"api_key\");\n if (config.has_user_tool_filters) {\n self._addLink(\"toolbox_filters\");\n }\n if (config.enable_openid && !config.use_remote_user) {\n self._addLink(\"openids\");\n }\n if (Galaxy.session_csrf_token) {\n self._addLink(\"logout\");\n }\n self.$preferences.append(self._templateFooter(data));\n self.$el.empty().append(self.$preferences);\n });\n },\n\n _addLink: function _addLink(action) {\n var options = this.model.get(action);\n var $row = $(this._templateLink(options));\n var $a = $row.find(\"a\");\n if (options.onclick) {\n $a.on(\"click\", function () {\n options.onclick();\n });\n } else {\n $a.attr(\"href\", Galaxy.root + \"user/\" + action);\n }\n this.$table.append($row);\n },\n\n _templateLink: function _templateLink(options) {\n return \"
\";\n },\n\n _templateFooter: function _templateFooter(options) {\n return \"
You are using \" + options.nice_total_disk_usage + \" of disk space in this Galaxy instance. \" + (Galaxy.config.enable_quotas ? \"Your disk quota is: \" + options.quota + \". \" : \"\") + \"Is your usage more than expected? See the documentation for tips on how to find all of the data in your account.
\";\n }\n});\n\nexports.default = {\n View: View,\n Model: Model\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 165 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nvar _uiTable = __webpack_require__(68);\n\nvar _uiTable2 = _interopRequireDefault(_uiTable);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** This class renders the chart configuration form. */\nvar Collection = Backbone.Collection.extend({\n comparator: function comparator(a, b) {\n a = a.get(\"name\");\n b = b.get(\"name\");\n return a > b ? 1 : a < b ? -1 : 0;\n }\n});\n\nvar View = Backbone.View.extend({\n initialize: function initialize(options) {\n var self = this;\n var history_id = Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.model.id;\n this.model = new Backbone.Model();\n this.model.url = Galaxy.root + \"api/histories/\" + history_id + \"/custom_builds_metadata\";\n this.collection = new Collection();\n this.collection.url = Galaxy.root + \"api/users/\" + Galaxy.user.id + \"/custom_builds\";\n this.message = new _uiMisc2.default.Message({});\n this.installed_builds = new _uiMisc2.default.Select.View({\n optional: true,\n onchange: function onchange() {\n self.installed_builds.value(null);\n },\n empty_text: \"List of available builds:\",\n error_text: \"No system installed builds available.\"\n });\n this.table = new _uiTable2.default.View({ cls: \"grid\", selectable: false });\n this.table.addHeader(\"Name\");\n this.table.addHeader(\"Key\");\n this.table.addHeader(\"Number of chroms/contigs\");\n this.table.addHeader(\"\");\n this.table.appendHeader();\n this.setElement($(\"\").append($(\"\").text(\"Current Custom Builds\")).append(this.table.$el).append(this.$installed = $(\"\").append($(\"\").text(\"System Installed Builds\").addClass(\"ui-margin-top\")).append(this.installed_builds.$el)).append($(\"\").text(\"Add a Custom Build\").addClass(\"ui-margin-top\")).append($(\"\").addClass(\"ui-column\").append($(\"\").addClass(\"ui-column-left\").append(this.message.$el).append(this.$form = $(\"\").addClass(\"ui-margin-top\"))).append(this.$help = $(\"\").addClass(\"ui-column-right\"))));\n this.listenTo(this.collection, \"add remove reset\", function () {\n self._renderTable();\n });\n this.listenTo(this.model, \"change\", function () {\n self._renderForm();\n });\n this.collection.fetch();\n this.model.fetch();\n },\n\n render: function render() {\n this._renderTable();\n this._renderForm();\n },\n\n _renderTable: function _renderTable() {\n var self = this;\n this.table.delAll();\n this.collection.sort();\n this.collection.each(function (model) {\n self.table.add(model.get(\"name\"));\n self.table.add(model.id);\n self.table.add(model.get(\"count\") !== undefined ? model.get(\"count\") : \"Processing...\");\n self.table.add(new _uiMisc2.default.ButtonIcon({\n icon: \"fa-trash-o\",\n cls: \"ui-button-icon-plain\",\n tooltip: \"Delete custom build.\",\n onclick: function onclick() {\n model.destroy();\n }\n }).$el);\n self.table.append(model.id);\n });\n },\n\n _renderForm: function _renderForm() {\n var self = this;\n var initial_type = \"fasta\";\n var form = new _formView2.default({\n inputs: [{\n type: \"text\",\n name: \"name\",\n label: \"Name\",\n help: \"Specify a build name e.g. Hamster.\"\n }, {\n type: \"text\",\n name: \"id\",\n label: \"Key\",\n help: \"Specify a build key e.g. hamster_v1.\"\n }, {\n name: \"len\",\n type: \"conditional\",\n test_param: {\n name: \"type\",\n label: \"Definition\",\n help: \"Provide the data source.\",\n type: \"select\",\n value: initial_type,\n data: [{\n value: \"fasta\",\n label: \"FASTA-file from history\"\n }, {\n value: \"file\",\n label: \"Len-file from disk\"\n }, {\n value: \"text\",\n label: \"Len-file by copy/paste\"\n }]\n },\n cases: [{\n value: \"fasta\",\n inputs: [{\n type: \"select\",\n name: \"value\",\n label: \"FASTA-file\",\n data: this.model.get(\"fasta_hdas\")\n }]\n }, {\n value: \"file\",\n inputs: [{\n type: \"upload\",\n name: \"value\",\n label: \"Len-file\",\n data: this.model.get(\"len_hdas\")\n }]\n }, {\n value: \"text\",\n inputs: [{\n type: \"text\",\n area: true,\n name: \"value\",\n label: \"Edit/Paste\"\n }]\n }]\n }],\n buttons: {\n save: new _uiMisc2.default.Button({\n icon: \"fa-save\",\n tooltip: \"Create new Build\",\n title: \"Save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function onclick() {\n var data = form.data.create();\n if (!data.id || !data.name) {\n self.message.update({\n message: \"All inputs are required.\",\n status: \"danger\"\n });\n } else {\n self.collection.create(data, {\n wait: true,\n success: function success(response) {\n if (response.get(\"message\")) {\n self.message.update({\n message: response.get(\"message\"),\n status: \"warning\"\n });\n } else {\n self.message.update({\n message: \"Successfully added a new custom build.\",\n status: \"success\"\n });\n }\n },\n error: function error(response, err) {\n var message = err && err.responseJSON && err.responseJSON.err_msg;\n self.message.update({\n message: message || \"Failed to create custom build.\",\n status: \"danger\"\n });\n }\n });\n }\n }\n })\n },\n onchange: function onchange() {\n var input_id = form.data.match(\"len|type\");\n if (input_id) {\n var input_field = form.field_list[input_id];\n self._renderHelp(input_field.value());\n }\n }\n });\n this.$form.empty().append(form.$el);\n var installed_builds = this.model.get(\"installed_builds\");\n if (installed_builds && installed_builds.length) {\n this.$installed.show();\n this.installed_builds.update(this.model.get(\"installed_builds\"));\n } else {\n this.$installed.hide();\n }\n this._renderHelp(initial_type);\n },\n\n _renderHelp: function _renderHelp(len_type) {\n this.$help.empty().addClass(\"alert alert-info\").html(len_type == \"fasta\" ? this._templateFasta() : this._templateLen());\n },\n\n _templateLen: function _templateLen() {\n return \"
Length Format
\" + \"
\" + \"The length format is two-column, separated by whitespace, of the form:\" + \"
chrom/contig length of chrom/contig
\" + \"\" + \"
\" + \"For example, the first few entries of mm9.len are as follows:\" + \"
Trackster uses this information to populate the select box for chrom/contig, and\" + \"to set the maximum basepair of the track browser. You may either upload a .len file\" + \"of this format (Len File option), or directly enter the information into the box \" + \"(Len Entry option).
\";\n },\n\n _templateFasta: function _templateFasta() {\n return \"
FASTA format
\" + \"
\" + \"This is a multi-fasta file from your current history that provides the genome\" + \"sequences for each chromosome/contig in your build.\" + \"
\" + \"
\" + \"Here is a snippet from an example multi-fasta file:\" + \"
\";\n }\n }\n});\n\n/** View of the main workflow list page */\nvar WorkflowListView = Backbone.View.extend({\n title: \"Workflows\",\n initialize: function initialize() {\n this.setElement(\"\");\n _.bindAll(this, \"adjustActiondropdown\");\n this.collection = new _workflowModel2.default.WorkflowCollection();\n this.collection.fetch().done(this.render());\n this.collection.bind(\"add\", this.appendItem);\n this.collection.on(\"sync\", this.render, this);\n },\n\n events: {\n dragleave: \"unhighlightDropZone\",\n drop: \"drop\",\n dragover: function dragover(ev) {\n $(\".hidden_description_layer\").addClass(\"dragover\");\n $(\".menubutton\").addClass(\"background-none\");\n ev.preventDefault();\n }\n },\n\n unhighlightDropZone: function unhighlightDropZone() {\n $(\".hidden_description_layer\").removeClass(\"dragover\");\n $(\".menubutton\").removeClass(\"background-none\");\n },\n\n drop: function drop(e) {\n // TODO: check that file is valid galaxy workflow\n this.unhighlightDropZone();\n e.preventDefault();\n var files = e.dataTransfer.files;\n var self = this;\n for (var i = 0, f; f = files[i]; i++) {\n self.readWorkflowFiles(f);\n }\n },\n\n readWorkflowFiles: function readWorkflowFiles(f) {\n var self = this;\n var reader = new FileReader();\n reader.onload = function (theFile) {\n var wf_json;\n try {\n wf_json = JSON.parse(reader.result);\n } catch (e) {\n mod_toastr.error(\"Could not read file '\" + f.name + \"'. Verify it is a valid Galaxy workflow\");\n wf_json = null;\n }\n if (wf_json) {\n self.collection.create(wf_json, {\n at: 0,\n wait: true,\n success: function success() {\n mod_toastr.success(\"Successfully imported workflow '\" + wf_json.name + \"'\");\n },\n error: function error(model, resp, options) {\n mod_toastr.error(options.errorThrown);\n }\n });\n }\n };\n reader.readAsText(f, \"utf-8\");\n },\n\n _showArgErrors: _.once(function () {\n // Parse args out of params, display if there's a message.\n var msg_text = _queryStringParsing2.default.get(\"message\");\n var msg_status = _queryStringParsing2.default.get(\"status\");\n if (msg_status === \"error\") {\n mod_toastr.error(_.escape(msg_text || \"Unknown Error, please report this to an administrator.\"));\n } else if (msg_text) {\n mod_toastr.info(_.escape(msg_text));\n }\n }),\n\n render: function render() {\n // Add workflow header\n var header = this._templateHeader();\n // Add the actions buttons\n var templateActions = this._templateActionButtons();\n var tableTemplate = this._templateWorkflowTable();\n this.$el.html(header + templateActions + tableTemplate);\n var self = this;\n _(this.collection.models).each(function (item) {\n // in case collection is not empty\n self.appendItem(item);\n self.confirmDelete(item);\n }, this);\n var minQueryLength = 3;\n this.searchWorkflow(this.$(\".search-wf\"), this.$(\".workflow-search tr\"), minQueryLength);\n this.adjustActiondropdown();\n this._showArgErrors();\n return this;\n },\n\n appendItem: function appendItem(item) {\n var workflowItemView = new WorkflowItemView({\n model: item,\n collection: this.collection\n });\n $(\".workflow-search\").append(workflowItemView.render().el);\n workflowItemView.renderTagEditor();\n },\n\n /** Add confirm box before removing/unsharing workflow */\n confirmDelete: function confirmDelete(workflow) {\n var $el_shared_wf_link = this.$(\".link-confirm-shared-\" + workflow.id);\n $el_shared_wf_link.click(function () {\n return window.confirm(\"Are you sure you want to remove the shared workflow '\" + workflow.attributes.name + \"'?\");\n });\n },\n\n /** Implement client side workflow search/filtering */\n searchWorkflow: function searchWorkflow($el_searchinput, $el_tabletr, min_querylen) {\n $el_searchinput.on(\"keyup\", function () {\n var query = $(this).val();\n // Filter when query is at least 3 characters\n // otherwise show all rows\n if (query.length >= min_querylen) {\n // Ignore the query's case using 'i'\n var regular_expression = new RegExp(query, \"i\");\n $el_tabletr.hide();\n $el_tabletr.filter(function () {\n // Apply regular expression on each row's text\n // and show when there is a match\n return regular_expression.test($(this).text());\n }).show();\n } else {\n $el_tabletr.show();\n }\n });\n },\n\n /** Ajust the position of dropdown with respect to table */\n adjustActiondropdown: function adjustActiondropdown() {\n $(this.el).on(\"show.bs.dropdown\", function () {\n $(this.el).css(\"overflow\", \"inherit\");\n });\n $(this.el).on(\"hide.bs.dropdown\", function () {\n $(this.el).css(\"overflow\", \"auto\");\n });\n },\n\n /** Template for no workflow */\n _templateNoWorkflow: function _templateNoWorkflow() {\n return '
You have no workflows.
';\n },\n\n /** Template for actions buttons */\n _templateActionButtons: function _templateActionButtons() {\n return \"
\";\n },\n\n /** Template for workflow table */\n _templateWorkflowTable: function _templateWorkflowTable() {\n var tableHtml = '
' + '
' + \"
Name
\" + \"
Tags
\" + \"
Owner
\" + \"
# of Steps
\" + \"
Published
\" + \"
Show in tools panel
\" + \"
\";\n return tableHtml + \"
Drop workflow files here to import
\";\n },\n\n /** Main template */\n _templateHeader: function _templateHeader() {\n return '
' + '
' + '' + \"
Your workflows
\" + \"
\" + \"
\";\n }\n});\n\nvar ImportWorkflowView = Backbone.View.extend({\n initialize: function initialize() {\n this.setElement(\"\");\n this.render();\n },\n\n /** Open page to import workflow */\n render: function render() {\n var self = this;\n $.getJSON(Galaxy.root + \"workflow/upload_import_workflow\", function (options) {\n self.$el.empty().append(self._mainTemplate(options));\n });\n },\n\n /** Template for the import workflow page */\n _mainTemplate: function _mainTemplate(options) {\n return \"
Click the link above to visit myExperiment and browse for Galaxy workflows.
\";\n }\n});\n\nexports.default = {\n View: WorkflowListView,\n ImportWorkflowView: ImportWorkflowView\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(1), __webpack_require__(0)))\n\n/***/ }),\n/* 168 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _baseMvc = __webpack_require__(5);\n\nvar _baseMvc2 = _interopRequireDefault(_baseMvc);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* global Backbone */\n// workflow model\n\nvar logNamespace = \"workflow\";\n//==============================================================================\n/** @class model for a single workflow.\n * @name WorkflowItem\n * @augments Backbone.Model\n */\nvar WorkflowItem = Backbone.Model.extend(_baseMvc2.default.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n urlRoot: Galaxy.root + \"api/workflows\",\n\n toJSON: function toJSON() {\n // need to overwrite this as endpoint expects the 'workflow' key in payload\n return { workflow: this.attributes };\n }\n});\n\n//==============================================================================\n/** @class collection for workflows.\n * @name WorkflowCollection\n * @augments Backbone.Collection\n */\nvar WorkflowCollection = Backbone.Collection.extend({\n model: WorkflowItem,\n url: Galaxy.root + \"api/workflows\"\n});\n\n//==============================================================================\n\nexports.default = {\n WorkflowItem: WorkflowItem,\n WorkflowCollection: WorkflowCollection\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))\n\n/***/ }),\n/* 169 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _gridView = __webpack_require__(12);\n\nvar _gridView2 = _interopRequireDefault(_gridView);\n\nvar _historyModel = __webpack_require__(38);\n\nvar _historyModel2 = _interopRequireDefault(_historyModel);\n\nvar _copyDialog = __webpack_require__(78);\n\nvar _copyDialog2 = _interopRequireDefault(_copyDialog);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** This class renders the grid list. */\nvar View = Backbone.View.extend({\n title: \"Histories\",\n initialize: function initialize(options) {\n var self = this;\n this.setElement($(\"\"));\n this.model = new Backbone.Model();\n _utils2.default.get({\n url: Galaxy.root + \"history/\" + options.action_id + \"?\" + $.param(Galaxy.params),\n success: function success(response) {\n response[\"dict_format\"] = true;\n _.each(response[\"operations\"], function (operation) {\n if (operation.label == \"Copy\") {\n operation.onclick = function (id) {\n self._showCopyDialog(id);\n };\n }\n });\n self.model.set(response);\n self.render();\n }\n });\n },\n\n render: function render() {\n var grid = new _gridView2.default(this.model.attributes);\n this.$el.empty().append(grid.$el);\n },\n\n _showCopyDialog: function _showCopyDialog(id) {\n var history = new _historyModel2.default.History({ id: id });\n history.fetch().fail(function () {\n alert(\"History could not be fetched. Please contact an administrator\");\n }).done(function () {\n (0, _copyDialog2.default)(history, {}).done(function () {\n if (window.parent && window.parent.Galaxy && window.parent.Galaxy.currHistoryPanel) {\n window.parent.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n window.location.reload(true);\n });\n });\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ }),\n/* 170 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Dataset edit attributes view */\nvar View = Backbone.View.extend({\n initialize: function initialize() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.render();\n },\n\n // Fetch data for the selected dataset and\n render: function render() {\n var data_url = Galaxy.root + \"api/datasets/\" + this.model.get(\"dataset_id\");\n\n var self = this;\n\n _utils2.default.get({\n url: data_url,\n success: function success(dataset) {\n var job_url = Galaxy.root + \"api/jobs/\" + dataset.creating_job + \"?full=True\";\n _utils2.default.get({\n url: job_url,\n success: function success(job) {\n var job_url = Galaxy.root + \"api/jobs/\" + dataset.creating_job + \"?full=True\";\n self.render_error_page(self, dataset, job);\n },\n error: function error(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the job.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n error: function error(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the dataset.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n\n /** Render the view */\n render_error_page: function render_error_page(self, dataset, job) {\n self.$el.empty().append(self._templateHeader());\n self.$el.append(\"
Dataset Error
\");\n self.$el.append(\"
An error occured while running the tool \" + job.tool_id + \".
\");\n self.$el.append(\"
Tool execution generated the following messages:
\");\n self.$el.append(\"
\" + job.stderr + \"
\");\n self.$el.append(\"
Report This Error\");\n self.$el.append(\"
Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.
\");\n self.$el.append(self._getBugFormTemplate(dataset, job));\n },\n\n /** Display actions messages */\n display_message: function display_message(response, $el, doNotClear, safe) {\n if (!safe) {\n if (doNotClear) {\n $el.append(new _uiMisc2.default.Message(response).$el);\n } else {\n $el.empty().html(new _uiMisc2.default.Message(response).$el);\n }\n } else {\n if (doNotClear) {\n $el.append(new _uiMisc2.default.UnescapedMessage(response).$el);\n } else {\n $el.empty().html(new _uiMisc2.default.UnescapedMessage(response).$el);\n }\n }\n },\n\n /** Main template */\n _templateHeader: function _templateHeader() {\n return '
' + '' + \"
\";\n },\n\n /** Convert tab template */\n _getBugFormTemplate: function _getBugFormTemplate(dataset, job) {\n var self = this;\n var inputs = [{\n help: \"Your email address\",\n options: [],\n type: \"text\",\n name: \"email\",\n label: \"Your email\",\n value: Galaxy.user.get(\"email\")\n }, {\n help: \"Any additional comments you can provide regarding what you were doing at the time of the bug.\",\n options: [],\n type: \"text\",\n area: true,\n name: \"message\",\n label: \"Message\"\n }];\n\n // TODO\n /*\n if (false && response.any_public) {\n inputs.push({\n name: \"public_consent\",\n label: \"Public Disclosure Consent\",\n help:\n \"This Galaxy is configured to report to one or more error reporting backends that public to the world. By selecting 'yes', you acknowledge that this bug report will be made public.\",\n value: String(Boolean(false)),\n options: [],\n type: \"boolean\"\n });\n }\n */\n\n var form = new _formView2.default({\n title: \"Error Report\",\n inputs: inputs,\n buttons: {\n save: new _uiMisc2.default.Button({\n icon: \"fa-bug\",\n title: \"Report\",\n cls: \"ui-button btn btn-primary\",\n floating: \"clear\",\n onclick: function onclick() {\n var form_data = form.data.create();\n var url = Galaxy.root + \"api/jobs/\" + job.id + \"/error\";\n form_data.dataset_id = dataset.id;\n self.submit(form_data, url);\n }\n })\n }\n });\n return form.$el;\n },\n\n /** Make ajax request */\n submit: function submit(form_data, url) {\n var self = this;\n // Some required metadata\n $.ajax({\n type: \"POST\",\n url: url,\n data: form_data,\n success: function success(response) {\n // Clear out the div\n self.$el.empty().append(self._templateHeader());\n // And display the messages.\n response.messages.forEach(function (message) {\n self.display_message({\n status: message[1],\n message: message[0],\n persistent: true\n }, self.$(\".response-message\"), true, true);\n });\n },\n error: function error(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while saving. Please fill all the required fields and try again.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0)))\n\n/***/ }),\n/* 171 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n/* WEBPACK VAR INJECTION */(function(Backbone, $, _) {\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _utils = __webpack_require__(3);\n\nvar _utils2 = _interopRequireDefault(_utils);\n\nvar _uiTabs = __webpack_require__(28);\n\nvar _uiTabs2 = _interopRequireDefault(_uiTabs);\n\nvar _uiMisc = __webpack_require__(6);\n\nvar _uiMisc2 = _interopRequireDefault(_uiMisc);\n\nvar _formView = __webpack_require__(9);\n\nvar _formView2 = _interopRequireDefault(_formView);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/** Dataset edit attributes view */\nvar View = Backbone.View.extend({\n initialize: function initialize() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.message = new _uiMisc2.default.Message({ persistent: true });\n this.tabs = this._createTabs();\n this.$el.append($(\"\").append(\"Edit dataset attributes\")).append(this.message.$el).append(\"\").append(this.tabs.$el).hide();\n this.render();\n },\n\n /** fetch data for the selected dataset and build forms */\n render: function render() {\n var self = this;\n $.ajax({\n url: Galaxy.root + \"dataset/get_edit?dataset_id=\" + self.model.get(\"dataset_id\"),\n success: function success(response) {\n !self.initial_message && self.message.update(response);\n self.initial_message = true;\n _.each(self.forms, function (form, key) {\n form.model.set(\"inputs\", response[key + \"_inputs\"]);\n form.model.set(\"hide_operations\", response[key + \"_disable\"]);\n form.render();\n });\n self.$el.show();\n },\n error: function error(response) {\n var err_msg = response.responseJSON && response.responseJSON.err_msg;\n self.message.update({\n status: \"danger\",\n message: err_msg || \"Error occured while loading the dataset.\"\n });\n }\n });\n },\n\n /** submit data to backend to update attributes */\n _submit: function _submit(operation, form) {\n var self = this;\n var data = form.data.create();\n data.dataset_id = this.model.get(\"dataset_id\");\n data.operation = operation;\n $.ajax({\n type: \"PUT\",\n url: Galaxy.root + \"dataset/set_edit\",\n data: data,\n success: function success(response) {\n self.message.update(response);\n self.render();\n self._reloadHistory();\n },\n error: function error(response) {\n var err_msg = response.responseJSON && response.responseJSON.err_msg;\n self.message.update({\n status: \"danger\",\n message: err_msg || \"Error occured while editing the dataset attributes.\"\n });\n }\n });\n },\n\n /** create tabs for different dataset attribute categories*/\n _createTabs: function _createTabs() {\n this.forms = {\n attribute: this._getAttribute(),\n conversion: this._getConversion(),\n datatype: this._getDatatype(),\n permission: this._getPermission()\n };\n var tabs = new _uiTabs2.default.View();\n tabs.add({\n id: \"attribute\",\n title: \"Attributes\",\n icon: \"fa fa-bars\",\n tooltip: \"Edit dataset attributes\",\n $el: this.forms.attribute.$el\n });\n tabs.add({\n id: \"convert\",\n title: \"Convert\",\n icon: \"fa-gear\",\n tooltip: \"Convert to new format\",\n $el: this.forms.conversion.$el\n });\n tabs.add({\n id: \"datatype\",\n title: \"Datatypes\",\n icon: \"fa-database\",\n tooltip: \"Change data type\",\n $el: this.forms.datatype.$el\n });\n tabs.add({\n id: \"permissions\",\n title: \"Permissions\",\n icon: \"fa-user\",\n tooltip: \"Permissions\",\n $el: this.forms.permission.$el\n });\n return tabs;\n },\n\n /** edit main attributes form */\n _getAttribute: function _getAttribute() {\n var self = this;\n var form = new _formView2.default({\n title: \"Edit attributes\",\n operations: {\n submit_attributes: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Save attributes of the dataset.\",\n icon: \"fa-floppy-o\",\n title: \"Save\",\n onclick: function onclick() {\n self._submit(\"attributes\", form);\n }\n }),\n submit_autodetect: new _uiMisc2.default.ButtonIcon({\n tooltip: \"This will inspect the dataset and attempt to correct the values of fields if they are not accurate.\",\n icon: \"fa-undo\",\n title: \"Auto-detect\",\n onclick: function onclick() {\n self._submit(\"autodetect\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** datatype conversion form */\n _getConversion: function _getConversion() {\n var self = this;\n var form = new _formView2.default({\n title: \"Convert to new format\",\n operations: {\n submit_conversion: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Convert the datatype to a new format.\",\n title: \"Convert datatype\",\n icon: \"fa-exchange\",\n onclick: function onclick() {\n self._submit(\"conversion\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** change datatype form */\n _getDatatype: function _getDatatype() {\n var self = this;\n var form = new _formView2.default({\n title: \"Change datatype\",\n operations: {\n submit_datatype: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Change the datatype to a new type.\",\n title: \"Change datatype\",\n icon: \"fa-exchange\",\n onclick: function onclick() {\n self._submit(\"datatype\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** dataset permissions form */\n _getPermission: function _getPermission() {\n var self = this;\n var form = new _formView2.default({\n title: \"Manage dataset permissions\",\n operations: {\n submit_permission: new _uiMisc2.default.ButtonIcon({\n tooltip: \"Save permissions.\",\n title: \"Save permissions\",\n icon: \"fa-floppy-o \",\n onclick: function onclick() {\n self._submit(\"permission\", form);\n }\n })\n }\n });\n return form;\n },\n\n /** reload Galaxy's history after updating dataset's attributes */\n _reloadHistory: function _reloadHistory() {\n if (window.Galaxy) {\n window.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n }\n});\n\nexports.default = {\n View: View\n};\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(0), __webpack_require__(1)))\n\n/***/ })\n],[138]);\n\n\n// WEBPACK FOOTER //\n// analysis.bundled.js","/**\n * Popover wrapper\n */\nimport Utils from \"utils/utils\";\nvar View = Backbone.View.extend({\n optionsDefault: {\n with_close: true,\n title: null,\n placement: \"top\",\n container: \"body\",\n body: null\n },\n\n initialize: function(options) {\n this.setElement(this._template());\n this.uid = Utils.uid();\n this.options = _.defaults(options || {}, this.optionsDefault);\n this.options.container.parent().append(this.el);\n this.$title = this.$(\".popover-title-label\");\n this.$close = this.$(\".popover-close\");\n this.$body = this.$(\".popover-content\");\n\n // add initial content\n this.options.body && this.append(this.options.body);\n\n // add event to hide if click is outside of popup and not on container\n var self = this;\n $(\"body\").on(`mousedown.${this.uid}`, e => {\n // the 'is' for buttons that trigger popups\n // the 'has' for icons within a button that triggers a popup\n self.visible &&\n !$(self.options.container).is(e.target) &&\n !$(self.el).is(e.target) &&\n $(self.el).has(e.target).length === 0 &&\n self.hide();\n });\n },\n\n /**\n * Render popover\n */\n render: function() {\n this.$title.html(this.options.title);\n this.$el\n .removeClass()\n .addClass(\"ui-popover popover fade in\")\n .addClass(this.options.placement);\n this.$el.css(this._get_placement(this.options.placement));\n\n // configure close option\n var self = this;\n if (this.options.with_close) {\n this.$close\n .on(\"click\", () => {\n self.hide();\n })\n .show();\n } else {\n this.$close.off().hide();\n }\n },\n\n /**\n * Set the popover title\n * @params{ String } newTitle - New popover title\n */\n title: function(newTitle) {\n if (newTitle !== undefined) {\n this.options.title = newTitle;\n this.$title.html(newTitle);\n }\n },\n\n /**\n * Show popover\n */\n show: function() {\n this.render();\n this.$el.show();\n this.visible = true;\n },\n\n /**\n * Hide popover\n */\n hide: function() {\n this.$el.hide();\n this.visible = false;\n },\n\n /**\n * Append new content to the popover\n * @params{ Object } $el - Dom element\n */\n append: function($el) {\n this.$body.append($el);\n },\n\n /**\n * Remove all content\n */\n empty: function() {\n this.$body.empty();\n },\n\n /**\n * Remove popover\n */\n remove: function() {\n $(\"body\").off(`mousedown.${this.uid}`);\n this.$el.remove();\n },\n\n /**\n * Improve popover location/placement\n */\n _get_placement: function(placement) {\n // get popover dimensions\n var width = this._get_width(this.$el);\n var height = this.$el.height();\n\n // get container details\n var $container = this.options.container;\n var container_width = this._get_width($container);\n var container_height = this._get_height($container);\n var container_position = $container.position();\n\n // get position\n var top;\n\n var left;\n top = left = 0;\n if ([\"top\", \"bottom\"].indexOf(placement) != -1) {\n left = container_position.left - width + (container_width + width) / 2;\n switch (placement) {\n case \"top\":\n top = container_position.top - height - 5;\n break;\n case \"bottom\":\n top = container_position.top + container_height + 5;\n break;\n }\n } else {\n top = container_position.top - height + (container_height + height) / 2;\n switch (placement) {\n case \"right\":\n left = container_position.left + container_width;\n break;\n }\n }\n return { top: top, left: left };\n },\n\n /**\n * Returns padding/margin corrected width\n */\n _get_width: function($el) {\n return (\n $el.width() +\n parseInt($el.css(\"padding-left\")) +\n parseInt($el.css(\"margin-left\")) +\n parseInt($el.css(\"padding-right\")) +\n parseInt($el.css(\"margin-right\"))\n );\n },\n\n /**\n * Returns padding corrected height\n */\n _get_height: function($el) {\n return $el.height() + parseInt($el.css(\"padding-top\")) + parseInt($el.css(\"padding-bottom\"));\n },\n\n /**\n * Return the popover template\n */\n _template: function(options) {\n return (\n '
' +\n '
' +\n '
' +\n '
' +\n '' +\n \"
\" +\n '
' +\n \"
\"\n );\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/ui/ui-popover.js","//==============================================================================\n/** Map of possible HDA/collection/job states to their string equivalents.\n * A port of galaxy.model.Dataset.states.\n */\nvar STATES = {\n // NOT ready states\n /** is uploading and not ready */\n UPLOAD: \"upload\",\n /** the job that will produce the dataset queued in the runner */\n QUEUED: \"queued\",\n /** the job that will produce the dataset is running */\n RUNNING: \"running\",\n /** metadata for the dataset is being discovered/set */\n SETTING_METADATA: \"setting_metadata\",\n\n // ready states\n /** was created without a tool */\n NEW: \"new\",\n /** has no data */\n EMPTY: \"empty\",\n /** has successfully completed running */\n OK: \"ok\",\n\n /** the job that will produce the dataset paused */\n PAUSED: \"paused\",\n /** metadata discovery/setting failed or errored (but otherwise ok) */\n FAILED_METADATA: \"failed_metadata\",\n //TODO: not in trans.app.model.Dataset.states - is in database\n /** not accessible to the current user (i.e. due to permissions) */\n NOT_VIEWABLE: \"noPermission\",\n /** deleted while uploading */\n DISCARDED: \"discarded\",\n /** the tool producing this dataset failed */\n ERROR: \"error\"\n};\n\nSTATES.READY_STATES = [\n STATES.OK,\n STATES.EMPTY,\n STATES.PAUSED,\n STATES.FAILED_METADATA,\n STATES.NOT_VIEWABLE,\n STATES.DISCARDED,\n STATES.ERROR\n];\n\nSTATES.NOT_READY_STATES = [STATES.UPLOAD, STATES.QUEUED, STATES.RUNNING, STATES.SETTING_METADATA, STATES.NEW];\n\n//==============================================================================\nexport default STATES;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/states.js","// dependencies\nimport Utils from \"utils/utils\";\n/**\n * A plugin for initializing select2 input items.\n * Make sure the select2 library itself is loaded beforehand.\n * Also the element to which select2 will be appended has to\n * be created before select2 initialization (and passed as option).\n */\nvar View = Backbone.View.extend({\n // options\n optionsDefault: {\n css: \"\",\n placeholder: \"No data available\",\n data: [],\n value: null,\n multiple: false,\n minimumInputLength: 0,\n // example format of initial data: \"id:name,55:anotherrole@role.com,27:role@role.com\"\n initialData: \"\"\n },\n\n // initialize\n initialize: function(options) {\n // configure options\n this.options = Utils.merge(options, this.optionsDefault);\n\n // create new element\n this.setElement(this._template(this.options));\n\n // check if container exists\n if (!this.options.container) {\n console.log(\"ui-select::initialize() : container not specified.\");\n return;\n }\n\n // add to dom\n this.options.container.append(this.$el);\n\n // link selection dictionary\n this.select_data = this.options.data;\n\n // refresh\n this._refresh();\n\n if (!this.options.multiple) {\n // initial value\n if (this.options.value) {\n this._setValue(this.options.value);\n }\n\n // add change event\n var self = this;\n if (this.options.onchange) {\n this.$el.on(\"change\", () => {\n self.options.onchange(self.value());\n });\n }\n }\n },\n\n // value\n value: function(new_value) {\n // get current id/value\n var before = this._getValue();\n\n // check if new_value is defined\n if (new_value !== undefined) {\n this._setValue(new_value);\n }\n\n // get current id/value\n var after = this._getValue();\n\n // fire onchange\n if (after != before && this.options.onchange) {\n this.options.onchange(after);\n }\n\n // return current value\n return after;\n },\n\n // label\n text: function() {\n return this.$el.select2(\"data\").text;\n },\n\n // disabled\n disabled: function() {\n return !this.$el.select2(\"enable\");\n },\n\n // enable\n enable: function() {\n this.$el.select2(\"enable\", true);\n },\n\n // disable\n disable: function() {\n this.$el.select2(\"enable\", false);\n },\n\n // add\n add: function(options) {\n // add options\n this.select_data.push({\n id: options.id,\n text: options.text\n });\n\n // refresh\n this._refresh();\n },\n\n // remove\n del: function(id) {\n // search option\n var index = this._getIndex(id);\n\n // check if found\n if (index != -1) {\n // remove options\n this.select_data.splice(index, 1);\n\n // refresh\n this._refresh();\n }\n },\n\n // remove\n remove: function() {\n this.$el.select2(\"destroy\");\n },\n\n // update\n update: function(options) {\n // copy options\n this.select_data = [];\n for (var key in options.data) {\n this.select_data.push(options.data[key]);\n }\n\n // refresh\n this._refresh();\n },\n\n // refresh\n _refresh: function() {\n // add select2 data based on type of input\n if (!this.options.multiple) {\n var selected = this._getValue();\n var select_opt = {\n data: this.select_data,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n dropdownAutoWidth: true\n };\n this.$el.select2(select_opt);\n // select previous value (if exists)\n this._setValue(selected);\n } else {\n var select_opt = {\n multiple: this.options.multiple,\n containerCssClass: this.options.css,\n placeholder: this.options.placeholder,\n minimumInputLength: this.options.minimumInputLength,\n ajax: this.options.ajax,\n dropdownCssClass: this.options.dropdownCssClass,\n escapeMarkup: this.options.escapeMarkup,\n formatResult: this.options.formatResult,\n formatSelection: this.options.formatSelection,\n initSelection: this.options.initSelection,\n initialData: this.options.initialData\n };\n this.$el.select2(select_opt);\n }\n },\n\n // get index\n _getIndex: function(value) {\n // returns the index of the searched value\n _.findIndex(this.select_data, { id: value });\n },\n\n // get value\n _getValue: function() {\n return this.$el.select2(\"val\");\n },\n\n // set value\n _setValue: function(new_value) {\n var index = this._getIndex(new_value);\n if (index == -1) {\n if (this.select_data.length > 0) {\n new_value = this.select_data[0].id;\n }\n }\n this.$el.select2(\"val\", new_value);\n },\n\n // element\n _template: function(options) {\n return ``;\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/ui/ui-select.js","import jQuery from \"jquery\";\n(\"use_strict\");\n\nvar $ = jQuery;\n//============================================================================\n/** Returns a jQuery object containing a clickable font-awesome button.\n * options:\n * tooltipConfig : option map for bootstrap tool tip\n * classes : array of class names (will always be classed as icon-btn)\n * disabled : T/F - add the 'disabled' class?\n * title : tooltip/title string\n * target : optional href target\n * href : optional href\n * faIcon : which font awesome icon to use\n * onclick : function to call when the button is clicked\n */\nvar faIconButton = options => {\n options = options || {};\n options.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n\n options.classes = [\"icon-btn\"].concat(options.classes || []);\n if (options.disabled) {\n options.classes.push(\"disabled\");\n }\n\n var html = [\n '',\n // could go with something less specific here - like 'html'\n '',\n \"\"\n ].join(\"\");\n var $button = $(html).tooltip(options.tooltipConfig);\n if (_.isFunction(options.onclick)) {\n $button.click(options.onclick);\n }\n return $button;\n};\n\n//============================================================================\nexport default faIconButton;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/ui/fa-icon-button.js","var Model = Backbone.Model.extend({\n defaults: {\n extension: \"auto\",\n genome: \"?\",\n url_paste: \"\",\n status: \"init\",\n info: null,\n file_name: \"\",\n file_mode: \"\",\n file_size: 0,\n file_type: null,\n file_path: \"\",\n file_data: null,\n percentage: 0,\n space_to_tab: false,\n to_posix_lines: true,\n enabled: true\n },\n reset: function(attr) {\n this.clear()\n .set(this.defaults)\n .set(attr);\n }\n});\nvar Collection = Backbone.Collection.extend({ model: Model });\nexport default { Model: Model, Collection: Collection };\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-model.js","import baseMVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n// =============================================================================\n/** A view on any model that has a 'tags' attribute (a list of tag strings)\n * Incorporates the select2 jQuery plugin for tags display/editing:\n * http://ivaynberg.github.io/select2/\n */\nvar TagsEditor = Backbone.View.extend(baseMVC.LoggableMixin)\n .extend(baseMVC.HiddenUntilActivatedViewMixin)\n .extend({\n tagName: \"div\",\n className: \"tags-display\",\n select_width: \"100%\",\n events: {},\n\n /** Set up listeners, parse options */\n initialize: function(options) {\n //console.debug( this, options );\n // only listen to the model only for changes to tags - re-render\n this.show_editor = false;\n if (options.usePrompt === false) {\n this.label = \"\";\n } else {\n this.label = ``;\n }\n this.workflow_mode = options.workflow_mode || false;\n if (this.workflow_mode) {\n this.events.click = \"showEditor\";\n this.events.keydown = \"keydownHandler\";\n }\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function() {\n var self = this;\n if (this.workflow_mode) {\n this.$el.html(this._workflowTemplate());\n } else {\n this.$el.html(this._defaultTemplate());\n }\n this.$input().select2({\n placeholder: \"Add tags\",\n width: this.workflow_mode ? this.width : this.select_width,\n tags: function() {\n // initialize possible tags in the dropdown based on all the tags the user has used so far\n return self._getTagsUsed();\n }\n });\n\n this._setUpBehaviors();\n return this;\n },\n\n _hashToName: function(tag) {\n if (tag.startsWith(\"#\")) {\n return `name:${tag.slice(1)}`;\n }\n return tag;\n },\n\n _nameToHash: function(tag) {\n if (tag.startsWith(\"name:\")) {\n tag = `#${tag.slice(5)}`;\n }\n return tag;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _defaultTemplate: function() {\n return [this.label, this._renderEditor()].join(\"\");\n },\n\n _workflowTemplate: function() {\n // Shows labels by default, event handler controls whether we show tags or editor\n return [this.show_editor ? this._renderEditor() : this._renderTags()].join(\" \");\n },\n\n keydownHandler: function(e) {\n switch (e.which) {\n // esc\n case 27:\n // hide the tag editor when pressing escape\n this.hideEditor();\n break;\n }\n },\n\n showEditor: function() {\n this.show_editor = true;\n this.render();\n },\n\n hideEditor: function() {\n this.show_editor = false;\n this.render();\n },\n\n _renderEditor: function() {\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n return ``;\n },\n\n _renderTags: function() {\n var tags = this.model.get(\"tags\");\n var addButton = \"static/images/fugue/tag--plus.png\";\n var renderedArray = [];\n _.each(tags, tag => {\n tag = tag.indexOf(\"name:\") == 0 ? tag.slice(5) : tag;\n var renderString = `${tag}`;\n renderedArray.push(renderString);\n });\n if (renderedArray.length === 0) {\n // If there are no tags to render we just show the add-tag-button\n renderedArray.push(``);\n }\n return renderedArray.join(\" \");\n },\n\n /** @returns {String} the sorted, comma-separated tags from the model */\n tagsToCSV: function() {\n var self = this;\n var tagsArray = this.model.get(\"tags\");\n if (!_.isArray(tagsArray) || _.isEmpty(tagsArray)) {\n return \"\";\n }\n return tagsArray\n .map(tag => _.escape(self._nameToHash(tag)))\n .sort()\n .join(\",\");\n },\n\n /** @returns {jQuery} the input for this view */\n $input: function() {\n return this.$el.find(\"input.tags-input\");\n },\n\n /** @returns {String[]} all tags used by the current user */\n _getTagsUsed: function() {\n //TODO: global\n var self = this;\n return _.map(Galaxy.user.get(\"tags_used\"), self._nameToHash);\n },\n\n /** set up any event listeners on the view's DOM (mostly handled by select2) */\n _setUpBehaviors: function() {\n var self = this;\n this.$input().on(\"change\", event => {\n // Modify any 'hashtag' 'nametags'\n event.val = _.map(event.val, self._hashToName);\n // save the model's tags in either remove or added event\n self.model.save({ tags: event.val });\n // if it's new, add the tag to the users tags\n if (event.added) {\n //??: solve weird behavior in FF on test.galaxyproject.org where\n // event.added.text is string object: 'String{ 0=\"o\", 1=\"n\", 2=\"e\" }'\n self._addNewTagToTagsUsed(`${event.added.text}`);\n }\n });\n },\n\n /** add a new tag (if not already there) to the list of all tags used by the user\n * @param {String} newTag the tag to add to the list of used\n */\n _addNewTagToTagsUsed: function(newTag) {\n //TODO: global\n var tagsUsed = Galaxy.user.get(\"tags_used\");\n if (!_.contains(tagsUsed, newTag)) {\n tagsUsed.push(newTag);\n tagsUsed.sort();\n Galaxy.user.set(\"tags_used\", tagsUsed);\n }\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function() {\n this.$input.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function() {\n return [\"TagsEditor(\", `${this.model}`, \")\"].join(\"\");\n }\n });\n\nexport default {\n TagsEditor: TagsEditor\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/tag.js","import jQuery from \"jquery\";\nvar $ = jQuery;\nimport QUERY_STRING from \"utils/query-string-parsing\";\nimport Ui from \"mvc/ui/ui-misc\";\n\nvar Router = Backbone.Router.extend({\n // TODO: not many client routes at this point - fill and remove from server.\n // since we're at root here, this may be the last to be routed entirely on the client.\n initialize: function(page, options) {\n this.page = page;\n this.options = options;\n },\n\n /** helper to push a new navigation state */\n push: function(url, data) {\n data = data || {};\n data.__identifer = Math.random()\n .toString(36)\n .substr(2);\n if (!$.isEmptyObject(data)) {\n url += url.indexOf(\"?\") == -1 ? \"?\" : \"&\";\n url += $.param(data, true);\n }\n Galaxy.params = data;\n this.navigate(url, { trigger: true });\n },\n\n /** override to parse query string into obj and send to each route */\n execute: function(callback, args, name) {\n Galaxy.debug(\"router execute:\", callback, args, name);\n var queryObj = QUERY_STRING.parse(args.pop());\n args.push(queryObj);\n if (callback) {\n if (this.authenticate(args, name)) {\n callback.apply(this, args);\n } else {\n this.access_denied();\n }\n }\n },\n\n authenticate: function(args, name) {\n return true;\n },\n\n access_denied: function() {\n this.page.display(\n new Ui.Message({\n status: \"danger\",\n message: \"You must be logged in with proper credentials to make this request.\",\n persistent: true\n })\n );\n }\n});\n\nexport default Router;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/layout/router.js","/** This renders the content of the settings popup, allowing users to specify flags i.e. for space-to-tab conversion **/\nimport Utils from \"utils/utils\";\nexport default Backbone.View.extend({\n options: {\n class_check: \"fa-check-square-o\",\n class_uncheck: \"fa-square-o\",\n parameters: [\n {\n id: \"space_to_tab\",\n title: \"Convert spaces to tabs\"\n },\n {\n id: \"to_posix_lines\",\n title: \"Use POSIX standard\"\n }\n ]\n },\n\n initialize: function(options) {\n var self = this;\n this.model = options.model;\n this.setElement($(\"\").addClass(\"upload-settings\"));\n this.$el.append($(\"\").addClass(\"upload-settings-cover\"));\n this.$el.append(\n $(\"
\").append(parameter.title))\n );\n });\n this.$cover[(this.model.get(\"enabled\") && \"hide\") || \"show\"]();\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-settings.js","/** This renders the content of the ftp popup **/\nimport Utils from \"utils/utils\";\nexport default Backbone.View.extend({\n initialize: function(options) {\n var self = this;\n this.model = new Backbone.Model({\n cls: \"upload-ftp\",\n class_add: \"upload-icon-button fa fa-square-o\",\n class_remove: \"upload-icon-button fa fa-check-square-o\",\n class_partial: \"upload-icon-button fa fa-minus-square-o\",\n help_enabled: true,\n help_text: `This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at ${\n options.ftp_upload_site\n } using your Galaxy credentials.`,\n collection: null,\n onchange: function() {},\n onadd: function() {},\n onremove: function() {}\n }).set(options);\n this.collection = this.model.get(\"collection\");\n this.setElement(this._template());\n this.$content = this.$(\".upload-ftp-content\");\n this.$wait = this.$(\".upload-ftp-wait\");\n this.$help = this.$(\".upload-ftp-help\");\n this.$number = this.$(\".upload-ftp-number\");\n this.$disk = this.$(\".upload-ftp-disk\");\n this.$body = this.$(\".upload-ftp-body\");\n this.$warning = this.$(\".upload-ftp-warning\");\n this.$select = this.$(\".upload-ftp-select-all\");\n this.render();\n },\n\n render: function() {\n var self = this;\n this.$wait.show();\n this.$content.hide();\n this.$warning.hide();\n this.$help.hide();\n $.ajax({\n url: `${Galaxy.root}api/remote_files`,\n method: \"GET\",\n success: function(ftp_files) {\n self.model.set(\"ftp_files\", ftp_files);\n self._index();\n self._renderTable();\n },\n error: function() {\n self._renderTable();\n }\n });\n },\n\n /** Fill table with ftp entries */\n _renderTable: function() {\n var self = this;\n var ftp_files = this.model.get(\"ftp_files\");\n this.rows = [];\n if (ftp_files && ftp_files.length > 0) {\n this.$body.empty();\n var size = 0;\n _.each(ftp_files, ftp_file => {\n self.rows.push(self._renderRow(ftp_file));\n size += ftp_file.size;\n });\n this.$number.html(`${ftp_files.length} files`);\n this.$disk.html(Utils.bytesToString(size, true));\n if (this.collection) {\n this.$(\"._has_collection\").show();\n this.$select\n .addClass(this.model.get(\"class_add\"))\n .off()\n .on(\"click\", () => {\n self._all();\n });\n this._refresh();\n }\n this.$content.show();\n } else {\n this.$warning.show();\n }\n this.model.get(\"help_enabled\") && this.$help.show();\n this.$wait.hide();\n },\n\n /** Add row */\n _renderRow: function(ftp_file) {\n var self = this;\n var options = this.model.attributes;\n var $it = $(this._templateRow(ftp_file));\n var $icon = $it.find(\".icon\");\n this.$body.append($it);\n if (this.collection) {\n var model_index = this.ftp_index[ftp_file.path];\n $icon.addClass(model_index === undefined ? options.class_add : options.class_remove);\n $it.on(\"click\", () => {\n self._switch($icon, ftp_file);\n self._refresh();\n });\n } else {\n $it.on(\"click\", () => {\n options.onchange(ftp_file);\n });\n }\n return $icon;\n },\n\n /** Create ftp index */\n _index: function() {\n var self = this;\n this.ftp_index = {};\n this.collection &&\n this.collection.each(model => {\n if (model.get(\"file_mode\") == \"ftp\") {\n self.ftp_index[model.get(\"file_path\")] = model.id;\n }\n });\n },\n\n /** Select all event handler */\n _all: function() {\n var options = this.model.attributes;\n var ftp_files = this.model.get(\"ftp_files\");\n var add = this.$select.hasClass(options.class_add);\n for (var index in ftp_files) {\n var ftp_file = ftp_files[index];\n var model_index = this.ftp_index[ftp_file.path];\n if ((model_index === undefined && add) || (model_index !== undefined && !add)) {\n this._switch(this.rows[index], ftp_file);\n }\n }\n this._refresh();\n },\n\n /** Handle collection changes */\n _switch: function($icon, ftp_file) {\n $icon.removeClass();\n var options = this.model.attributes;\n var model_index = this.ftp_index[ftp_file.path];\n if (model_index === undefined) {\n var new_index = options.onadd(ftp_file);\n $icon.addClass(options.class_remove);\n this.ftp_index[ftp_file.path] = new_index;\n } else {\n options.onremove(model_index);\n $icon.addClass(options.class_add);\n this.ftp_index[ftp_file.path] = undefined;\n }\n },\n\n /** Refresh select all button state */\n _refresh: function() {\n var counts = _.reduce(\n this.ftp_index,\n (memo, element) => {\n element !== undefined && memo++;\n return memo;\n },\n 0\n );\n this.$select.removeClass();\n if (counts == 0) {\n this.$select.addClass(this.model.get(\"class_add\"));\n } else {\n this.$select.addClass(\n counts == this.rows.length ? this.model.get(\"class_remove\") : this.model.get(\"class_partial\")\n );\n }\n },\n\n /** Template of row */\n _templateRow: function(options) {\n return `
${_.escape(\n options.path\n )}
${Utils.bytesToString(options.size)}
${\n options.ctime\n }
`;\n },\n\n /** Template of main view */\n _template: function() {\n return `
${this.model.get(\n \"help_text\"\n )}
Available files:
Name
Size
Created
Your FTP directory does not contain any files.
`;\n (\"
\");\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-ftp.js","/** This renders a popover with extension details **/\nimport Utils from \"utils/utils\";\nimport Popover from \"mvc/ui/ui-popover\";\nexport default Backbone.View.extend({\n initialize: function(options) {\n this.model = new Backbone.Model(options);\n this.setElement(\"\");\n this.render();\n },\n\n render: function() {\n var self = this;\n var options = this.model.attributes;\n var description = _.findWhere(options.list, {\n id: options.extension\n });\n this.extension_popup && this.extension_popup.remove();\n this.extension_popup = new Popover.View({\n placement: options.placement || \"bottom\",\n container: options.$el\n });\n this.extension_popup.title(options.title);\n this.extension_popup.empty();\n this.extension_popup.append(this._templateDescription(description));\n this.extension_popup.show();\n },\n\n /** Template for extensions description */\n _templateDescription: function(options) {\n if (options.description) {\n var tmpl = options.description;\n if (options.description_url) {\n tmpl += ` (read more)`;\n }\n return tmpl;\n } else {\n return \"There is no description available for this file extension.\";\n }\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/upload-extension.js","/*\n galaxy upload plugins - requires FormData and XMLHttpRequest\n*/\n($ => {\n // add event properties\n jQuery.event.props.push(\"dataTransfer\");\n\n /**\n Posts file data to the API\n */\n $.uploadpost = config => {\n // parse options\n var cnf = $.extend(\n {},\n {\n data: {},\n success: function() {},\n error: function() {},\n progress: function() {},\n url: null,\n maxfilesize: 2048,\n error_filesize: \"File exceeds 2GB. Please use a FTP client.\",\n error_default: \"Please make sure the file is available.\",\n error_server: \"Upload request failed.\",\n error_login: \"Uploads require you to log in.\"\n },\n config\n );\n\n // link data\n var data = cnf.data;\n\n // check errors\n if (data.error_message) {\n cnf.error(data.error_message);\n return;\n }\n\n // construct form data\n var form = new FormData();\n for (var key in data.payload) {\n form.append(key, data.payload[key]);\n }\n\n // add files to submission\n var sizes = 0;\n for (var key in data.files) {\n var d = data.files[key];\n form.append(d.name, d.file, d.file.name);\n sizes += d.file.size;\n }\n\n // check file size, unless it's an ftp file\n if (sizes > 1048576 * cnf.maxfilesize) {\n cnf.error(cnf.error_filesize);\n return;\n }\n\n // prepare request\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", cnf.url, true);\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n xhr.setRequestHeader(\"Cache-Control\", \"no-cache\");\n xhr.setRequestHeader(\"X-Requested-With\", \"XMLHttpRequest\");\n\n // captures state changes\n xhr.onreadystatechange = () => {\n // check for request completed, server connection closed\n if (xhr.readyState == xhr.DONE) {\n // parse response\n var response = null;\n var extra_info = \"\";\n if (xhr.responseText) {\n try {\n response = jQuery.parseJSON(xhr.responseText);\n extra_info = response.err_msg;\n } catch (e) {\n response = xhr.responseText;\n extra_info = response;\n }\n }\n // pass any error to the error option\n if (xhr.status < 200 || xhr.status > 299) {\n var text = xhr.statusText;\n if (xhr.status == 403) {\n text = cnf.error_login;\n } else if (xhr.status == 0) {\n text = cnf.error_server;\n } else if (!text) {\n text = cnf.error_default;\n }\n cnf.error(`${text} (${xhr.status}). ${extra_info}`);\n } else {\n cnf.success(response);\n }\n }\n };\n\n // prepare upload progress\n xhr.upload.addEventListener(\n \"progress\",\n e => {\n if (e.lengthComputable) {\n cnf.progress(Math.round(e.loaded * 100 / e.total));\n }\n },\n false\n );\n\n // send request\n Galaxy.emit.debug(\"uploadbox::uploadpost()\", \"Posting following data.\", cnf);\n xhr.send(form);\n };\n\n /**\n Handles the upload events drag/drop etc.\n */\n $.fn.uploadinput = function(options) {\n // initialize\n var el = this;\n var opts = $.extend(\n {},\n {\n ondragover: function() {},\n ondragleave: function() {},\n onchange: function() {},\n multiple: false\n },\n options\n );\n\n // append hidden upload field\n var $input = $(``);\n el.append(\n $input.change(function(e) {\n opts.onchange(e.target.files);\n $(this).val(\"\");\n })\n );\n\n // drag/drop events\n el.on(\"drop\", e => {\n opts.ondragleave(e);\n if (e.dataTransfer) {\n opts.onchange(e.dataTransfer.files);\n e.preventDefault();\n }\n });\n el.on(\"dragover\", e => {\n e.preventDefault();\n opts.ondragover(e);\n });\n el.on(\"dragleave\", e => {\n e.stopPropagation();\n opts.ondragleave(e);\n });\n\n // exports\n return {\n dialog: function() {\n $input.trigger(\"click\");\n }\n };\n };\n\n /**\n Handles the upload queue and events such as drag/drop etc.\n */\n $.fn.uploadbox = function(options) {\n // parse options\n var opts = $.extend(\n {},\n {\n dragover: function() {},\n dragleave: function() {},\n announce: function(d) {},\n initialize: function(d) {},\n progress: function(d, m) {},\n success: function(d, m) {},\n error: function(d, m) {\n alert(m);\n },\n complete: function() {}\n },\n options\n );\n\n // file queue\n var queue = {};\n\n // queue index/length counter\n var queue_index = 0;\n var queue_length = 0;\n\n // indicates if queue is currently running\n var queue_running = false;\n var queue_stop = false;\n\n // element\n var uploadinput = $(this).uploadinput({\n multiple: true,\n onchange: function(files) {\n add(files);\n },\n ondragover: options.ondragover,\n ondragleave: options.ondragleave\n });\n\n // add new files to upload queue\n function add(files) {\n if (files && files.length && !queue_running) {\n var index = undefined;\n _.each(files, (file, key) => {\n if (\n file.mode !== \"new\" &&\n _.filter(queue, f => f.name === file.name && f.size === file.size).length\n ) {\n file.duplicate = true;\n }\n });\n _.each(files, file => {\n if (!file.duplicate) {\n index = String(queue_index++);\n queue[index] = file;\n opts.announce(index, queue[index]);\n queue_length++;\n }\n });\n return index;\n }\n }\n\n // remove file from queue\n function remove(index) {\n if (queue[index]) {\n delete queue[index];\n queue_length--;\n }\n }\n\n // process an upload, recursive\n function process() {\n // validate\n if (queue_length == 0 || queue_stop) {\n queue_stop = false;\n queue_running = false;\n opts.complete();\n return;\n } else {\n queue_running = true;\n }\n\n // get an identifier from the queue\n var index = -1;\n for (var key in queue) {\n index = key;\n break;\n }\n\n // get current file from queue\n var file = queue[index];\n\n // remove from queue\n remove(index);\n\n // create and submit data\n $.uploadpost({\n url: opts.url,\n data: opts.initialize(index),\n success: function(message) {\n opts.success(index, message);\n process();\n },\n error: function(message) {\n opts.error(index, message);\n process();\n },\n progress: function(percentage) {\n opts.progress(index, percentage);\n }\n });\n }\n\n /*\n public interface\n */\n\n // open file browser for selection\n function select() {\n uploadinput.dialog();\n }\n\n // remove all entries from queue\n function reset(index) {\n for (index in queue) {\n remove(index);\n }\n }\n\n // initiate upload process\n function start() {\n if (!queue_running) {\n queue_running = true;\n process();\n }\n }\n\n // stop upload process\n function stop() {\n queue_stop = true;\n }\n\n // set options\n function configure(options) {\n opts = $.extend({}, opts, options);\n return opts;\n }\n\n // verify browser compatibility\n function compatible() {\n return window.File && window.FormData && window.XMLHttpRequest && window.FileList;\n }\n\n // export functions\n return {\n select: select,\n add: add,\n remove: remove,\n start: start,\n stop: stop,\n reset: reset,\n configure: configure,\n compatible: compatible\n };\n };\n})(jQuery);\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/uploadbox.js","import HDCA from \"mvc/history/hdca-model\";\nimport STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport baseCreator from \"mvc/collection/base-creator\";\nimport UI_MODAL from \"mvc/ui/ui-modal\";\nimport naturalSort from \"utils/natural-sort\";\nimport _l from \"utils/localization\";\nimport \"ui/hoverhighlight\";\n\nvar logNamespace = \"collections\";\n\n/*==============================================================================\nTODO:\n use proper Element model and not just json\n straighten out createFn, collection.createHDCA\n possibly stop using modals for this\n It would be neat to do a drag and drop\n\n==============================================================================*/\n/** A view for both DatasetDCEs and NestedDCDCEs\n * (things that implement collection-model:DatasetCollectionElementMixin)\n */\nvar DatasetCollectionElementView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))\n tagName: \"li\",\n className: \"collection-element\",\n\n initialize: function(attributes) {\n this.element = attributes.element || {};\n this.selected = attributes.selected || false;\n },\n\n render: function() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el\n .attr(\"data-element-id\", this.element.id)\n .attr(\"draggable\", true)\n .html(this.template({ element: this.element }))\n .get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n if (this.selected) {\n this.$el.addClass(\"selected\");\n }\n return this;\n },\n\n //TODO: lots of unused space in the element - possibly load details and display them horiz.\n template: _.template(\n [\n '',\n \"<%- element.name %>\",\n \"\",\n '\"\n ].join(\"\")\n ),\n\n /** select this element and pub */\n select: function(toggle) {\n this.$el.toggleClass(\"selected\", toggle);\n this.trigger(\"select\", {\n source: this,\n selected: this.$el.hasClass(\"selected\")\n });\n },\n\n /** animate the removal of this element and pub */\n discard: function() {\n var view = this;\n var parentWidth = this.$el.parent().width();\n this.$el.animate({ \"margin-right\": parentWidth }, \"fast\", () => {\n view.trigger(\"discard\", {\n source: view\n });\n view.destroy();\n });\n },\n\n /** remove the DOM and any listeners */\n destroy: function() {\n this.off();\n this.$el.remove();\n },\n\n events: {\n click: \"_click\",\n \"click .name\": \"_clickName\",\n \"click .discard\": \"_clickDiscard\",\n\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** select when the li is clicked */\n _click: function(ev) {\n ev.stopPropagation();\n this.select(ev);\n },\n\n /** rename a pair when the name is clicked */\n _clickName: function(ev) {\n ev.stopPropagation();\n ev.preventDefault();\n\n var promptString = [\n _l(\"Enter a new name for the element\"),\n \":\\n(\",\n _l(\"Note that changing the name here will not rename the dataset\"),\n \")\"\n ].join(\"\");\n\n var response = prompt(`${_l(\"Enter a new name for the element\")}:`, this.element.name);\n\n if (response) {\n this.element.name = response;\n this.render();\n }\n //TODO: cancelling with ESC leads to closure of the creator...\n },\n\n /** discard when the discard button is clicked */\n _clickDiscard: function(ev) {\n ev.stopPropagation();\n this.discard();\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.element));\n\n this.$el.addClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragstart\", [this]);\n },\n\n /** dragging for re-ordering */\n _dragend: function(ev) {\n this.$el.removeClass(\"dragging\");\n this.$el.parent().trigger(\"collection-element.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function() {\n return \"DatasetCollectionElementView()\";\n }\n});\n\n// ============================================================================\n/** An interface for building collections.\n */\nvar ListCollectionCreator = Backbone.View.extend(BASE_MVC.LoggableMixin)\n .extend(baseCreator.CollectionCreatorMixin)\n .extend({\n _logNamespace: logNamespace,\n\n /** the class used to display individual elements */\n elementViewClass: DatasetCollectionElementView,\n /** the class this creator will create and save */\n collectionClass: HDCA.HistoryListDatasetCollection,\n className: \"list-collection-creator collection-creator flex-row-container\",\n\n /** minimum number of valid elements to start with in order to build a collection of this type */\n minElements: 1,\n\n defaultAttributes: {\n //TODO: remove - use new collectionClass().save()\n /** takes elements and creates the proper collection - returns a promise */\n creationFn: function() {\n throw new TypeError(\"no creation fn for creator\");\n },\n /** fn to call when the collection is created (scoped to this) */\n oncreate: function() {},\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n oncancel: function() {},\n /** distance from list edge to begin autoscrolling list */\n autoscrollDist: 24,\n /** Color passed to hoverhighlight */\n highlightClr: \"rgba( 64, 255, 255, 1.0 )\"\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\"\n },\n\n /** set up initial options, instance vars, behaviors */\n initialize: function(attributes) {\n this.metric(\"ListCollectionCreator.initialize\", attributes);\n var creator = this;\n _.each(this.defaultAttributes, (value, key) => {\n value = attributes[key] || value;\n creator[key] = value;\n });\n\n /** unordered, original list - cache to allow reversal */\n creator.initialElements = attributes.elements || [];\n\n this._setUpCommonSettings(attributes);\n this._instanceSetUp();\n this._elementsSetUp();\n this._setUpBehaviors();\n },\n\n /** set up instance vars */\n _instanceSetUp: function() {\n /** Ids of elements that have been selected by the user - to preserve over renders */\n this.selectedIds = {};\n /** DOM elements currently being dragged */\n this.$dragging = null;\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n },\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data */\n _elementsSetUp: function() {\n //this.debug( '-- _dataSetUp' );\n /** a list of invalid elements and the reasons they aren't valid */\n this.invalidElements = [];\n //TODO: handle fundamental problem of syncing DOM, views, and list here\n /** data for list in progress */\n this.workingElements = [];\n /** views for workingElements */\n this.elementViews = [];\n\n // copy initial list, sort, add ids if needed\n this.workingElements = this.initialElements.slice(0);\n this._ensureElementIds();\n this._validateElements();\n this._mangleDuplicateNames();\n this._sortElements();\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureElementIds: function() {\n this.workingElements.forEach(element => {\n if (!element.hasOwnProperty(\"id\")) {\n element.id = _.uniqueId();\n }\n });\n return this.workingElements;\n },\n\n /** separate working list into valid and invalid elements for this collection */\n _validateElements: function() {\n var creator = this;\n var existingNames = {};\n creator.invalidElements = [];\n\n this.workingElements = this.workingElements.filter(element => {\n var problem = creator._isElementInvalid(element);\n if (problem) {\n creator.invalidElements.push({\n element: element,\n text: problem\n });\n }\n return !problem;\n });\n return this.workingElements;\n },\n\n /** describe what is wrong with a particular element if anything */\n _isElementInvalid: function(element) {\n if (element.history_content_type !== \"dataset\") {\n return _l(\"is not a dataset\");\n }\n var validState = element.state === STATES.OK || _.contains(STATES.NOT_READY_STATES, element.state);\n if (!validState) {\n return _l(\"has errored, is paused, or is not accessible\");\n }\n if (element.deleted || element.purged) {\n return _l(\"has been deleted or purged\");\n }\n return null;\n },\n\n /** mangle duplicate names using a mac-like '(counter)' addition to any duplicates */\n _mangleDuplicateNames: function() {\n var SAFETY = 900;\n var counter = 1;\n var existingNames = {};\n this.workingElements.forEach(element => {\n var currName = element.name;\n while (existingNames.hasOwnProperty(currName)) {\n currName = `${element.name} (${counter})`;\n counter += 1;\n if (counter >= SAFETY) {\n throw new Error(\"Safety hit in while loop - thats impressive\");\n }\n }\n element.name = currName;\n existingNames[element.name] = true;\n });\n },\n\n /** sort a list of elements */\n _sortElements: function(list) {\n // // currently only natural sort by name\n // this.workingElements.sort( function( a, b ){ return naturalSort( a.name, b.name ); });\n // return this.workingElements;\n },\n\n // ------------------------------------------------------------------------ rendering\n // templates : ListCollectionCreator.templates,\n /** render the entire interface */\n render: function(speed, callback) {\n //this.debug( '-- _render' );\n if (this.workingElements.length < this.minElements) {\n return this._renderInvalid(speed, callback);\n }\n\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.$(\".collection-name\").focus();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render a simplified interface aimed at telling the user why they can't move forward */\n _renderInvalid: function(speed, callback) {\n //this.debug( '-- _render' );\n this.$el.empty().html(\n this.templates.invalidInitial({\n problems: this.invalidElements,\n elements: this.workingElements\n })\n );\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function(speed, callback) {\n var $header = this.$(\".header\")\n .empty()\n .html(this.templates.header())\n .find(\".help-content\")\n .prepend($(this.templates.helpContent()));\n //TODO: should only show once despite calling _renderHeader again\n if (this.invalidElements.length) {\n this._invalidElementsAlert();\n }\n return $header;\n },\n\n /** render the middle including the elements */\n _renderMiddle: function(speed, callback) {\n var $middle = this.$(\".middle\")\n .empty()\n .html(this.templates.middle());\n this._renderList(speed);\n return $middle;\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function() {\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", this.highlightClr);\n },\n\n /** build and show an alert describing any elements that could not be included due to problems */\n _invalidElementsAlert: function() {\n this._showAlert(\n this.templates.invalidElements({\n problems: this.invalidElements\n }),\n \"alert-warning\"\n );\n },\n\n _disableNameAndCreate: function(disable) {\n disable = !_.isUndefined(disable) ? disable : true;\n if (disable) {\n this.$(\".collection-name\").prop(\"disabled\", true);\n this.$(\".create-collection\").toggleClass(\"disabled\", true);\n // } else {\n // this.$( '.collection-name' ).prop( 'disabled', false );\n // this.$( '.create-collection' ).removeClass( 'disable' );\n }\n },\n\n // ------------------------------------------------------------------------ rendering elements\n /** conv. to the main list display DOM */\n $list: function() {\n return this.$(\".collection-elements\");\n },\n\n /** show or hide the clear selected control based on the num of selected elements */\n _renderClearSelected: function() {\n if (_.size(this.selectedIds)) {\n this.$(\".collection-elements-controls > .clear-selected\").show();\n } else {\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n }\n },\n\n /** render the elements in order (or a warning if no elements found) */\n _renderList: function(speed, callback) {\n //this.debug( '-- _renderList' );\n var creator = this;\n\n var $tmp = jQuery(\"\");\n var $list = creator.$list();\n\n _.each(this.elementViews, view => {\n view.destroy();\n creator.removeElementView(view);\n });\n\n // if( !this.workingElements.length ){\n // this._renderNoValidElements();\n // return;\n // }\n\n creator.workingElements.forEach(element => {\n var elementView = creator._createElementView(element);\n $tmp.append(elementView.$el);\n });\n\n creator._renderClearSelected();\n $list.empty().append($tmp.children());\n _.invoke(creator.elementViews, \"render\");\n\n if ($list.height() > $list.css(\"max-height\")) {\n $list.css(\"border-width\", \"1px 0px 1px 0px\");\n } else {\n $list.css(\"border-width\", \"0px\");\n }\n },\n\n /** create an element view, cache in elementViews, set up listeners, and return */\n _createElementView: function(element) {\n var elementView = new this.elementViewClass({\n //TODO: use non-generic class or not all\n // model : COLLECTION.DatasetDCE( element )\n element: element,\n selected: _.has(this.selectedIds, element.id)\n });\n this.elementViews.push(elementView);\n this._listenToElementView(elementView);\n return elementView;\n },\n\n /** listen to any element events */\n _listenToElementView: function(view) {\n var creator = this;\n creator.listenTo(view, {\n select: function(data) {\n var element = data.source.element;\n if (data.selected) {\n creator.selectedIds[element.id] = true;\n } else {\n delete creator.selectedIds[element.id];\n }\n creator.trigger(\"elements:select\", data);\n },\n discard: function(data) {\n creator.trigger(\"elements:discard\", data);\n }\n });\n },\n\n /** add a new element view based on the json in element */\n addElementView: function(element) {\n //TODO: workingElements is sorted, add element in appropo index\n // add element, sort elements, find element index\n // var view = this._createElementView( element );\n // return view;\n },\n\n /** stop listening to view and remove from caches */\n removeElementView: function(view) {\n delete this.selectedIds[view.element.id];\n this._renderClearSelected();\n\n this.elementViews = _.without(this.elementViews, view);\n this.stopListening(view);\n },\n\n /** render a message in the list that no elements remain to create a collection */\n _renderNoElementsLeft: function() {\n this._disableNameAndCreate(true);\n this.$(\".collection-elements\").append(this.templates.noElementsLeft());\n },\n\n // /** render a message in the list that no valid elements were found to create a collection */\n // _renderNoValidElements : function(){\n // this._disableNameAndCreate( true );\n // this.$( '.collection-elements' ).append( this.templates.noValidElements() );\n // },\n\n // ------------------------------------------------------------------------ API\n /** convert element into JSON compatible with the collections API */\n _elementToJSON: function(element) {\n // return element.toJSON();\n return element;\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function(name) {\n if (!this.workingElements.length) {\n var message = `${_l(\"No valid elements for final list\")}. `;\n message += `${_l(\"Cancel\")} `;\n message += _l(\"or\");\n message += ` ${_l(\"start over\")}.`;\n this._showAlert(message);\n return;\n }\n\n var creator = this;\n\n var elements = this.workingElements.map(element => creator._elementToJSON(element));\n\n creator.blocking = true;\n return creator\n .creationFn(elements, name, creator.hideOriginals)\n .always(() => {\n creator.blocking = false;\n })\n .fail((xhr, status, message) => {\n creator.trigger(\"error\", {\n xhr: xhr,\n status: status,\n message: _l(\"An error occurred while creating this collection\")\n });\n })\n .done(function(response, message, xhr) {\n creator.trigger(\"collection:created\", response, message, xhr);\n creator.metric(\"collection:created\", response);\n if (typeof creator.oncreate === \"function\") {\n creator.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n // ------------------------------------------------------------------------ events\n /** set up event handlers on self */\n _setUpBehaviors: function() {\n this.on(\"error\", this._errorHandler);\n\n this.once(\"rendered\", function() {\n this.trigger(\"rendered:initial\", this);\n });\n\n this.on(\"elements:select\", function(data) {\n this._renderClearSelected();\n });\n\n this.on(\"elements:discard\", function(data) {\n var element = data.source.element;\n this.removeElementView(data.source);\n\n this.workingElements = _.without(this.workingElements, element);\n if (!this.workingElements.length) {\n this._renderNoElementsLeft();\n }\n });\n\n //this.on( 'all', function(){\n // this.info( arguments );\n //});\n return this;\n },\n\n /** handle errors with feedback and details to the user (if available) */\n _errorHandler: function(data) {\n this.error(data);\n\n var creator = this;\n var content = data.message || _l(\"An error occurred\");\n if (data.xhr) {\n var xhr = data.xhr;\n var message = data.message;\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += `: ${_l(\"Galaxy could not be reached and may be updating.\")}${_l(\n \" Try again in a few minutes.\"\n )}`;\n } else if (xhr.responseJSON) {\n content += `:
${JSON.stringify(xhr.responseJSON)}
`;\n } else {\n content += `: ${message}`;\n }\n }\n creator._showAlert(content, \"alert-danger\");\n },\n\n events: {\n // header\n \"click .more-help\": \"_clickMoreHelp\",\n \"click .less-help\": \"_clickLessHelp\",\n \"click .main-help\": \"_toggleHelp\",\n \"click .header .alert button\": \"_hideAlert\",\n\n \"click .reset\": \"reset\",\n \"click .clear-selected\": \"clearSelectedElements\",\n\n // elements - selection\n \"click .collection-elements\": \"clearSelectedElements\",\n\n // elements - drop target\n // 'dragenter .collection-elements': '_dragenterElements',\n // 'dragleave .collection-elements': '_dragleaveElements',\n \"dragover .collection-elements\": \"_dragoverElements\",\n \"drop .collection-elements\": \"_dropElements\",\n\n // these bubble up from the elements as custom events\n \"collection-element.dragstart .collection-elements\": \"_elementDragstart\",\n \"collection-element.dragend .collection-elements\": \"_elementDragend\",\n\n // footer\n \"change .collection-name\": \"_changeName\",\n \"keydown .collection-name\": \"_nameCheckForEnter\",\n \"change .hide-originals\": \"_changeHideOriginals\",\n \"click .cancel-create\": \"_cancelCreate\",\n \"click .create-collection\": \"_clickCreate\" //,\n },\n\n // ........................................................................ elements\n /** reset all data to the initial state */\n reset: function() {\n this._instanceSetUp();\n this._elementsSetUp();\n this.render();\n },\n\n /** deselect all elements */\n clearSelectedElements: function(ev) {\n this.$(\".collection-elements .collection-element\").removeClass(\"selected\");\n this.$(\".collection-elements-controls > .clear-selected\").hide();\n },\n\n //_dragenterElements : function( ev ){\n // //this.debug( '_dragenterElements:', ev );\n //},\n //TODO: if selected are dragged out of the list area - remove the placeholder - cuz it won't work anyway\n // _dragleaveElements : function( ev ){\n // //this.debug( '_dragleaveElements:', ev );\n // },\n\n /** track the mouse drag over the list adding a placeholder to show where the drop would occur */\n _dragoverElements: function(ev) {\n //this.debug( '_dragoverElements:', ev );\n ev.preventDefault();\n\n var $list = this.$list();\n this._checkForAutoscroll($list, ev.originalEvent.clientY);\n var $nearest = this._getNearestElement(ev.originalEvent.clientY);\n\n //TODO: no need to re-create - move instead\n this.$(\".element-drop-placeholder\").remove();\n var $placeholder = $('');\n if (!$nearest.length) {\n $list.append($placeholder);\n } else {\n $nearest.before($placeholder);\n }\n },\n\n /** If the mouse is near enough to the list's top or bottom, scroll the list */\n _checkForAutoscroll: function($element, y) {\n var AUTOSCROLL_SPEED = 2;\n var offset = $element.offset();\n var scrollTop = $element.scrollTop();\n var upperDist = y - offset.top;\n var lowerDist = offset.top + $element.outerHeight() - y;\n if (upperDist >= 0 && upperDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop - AUTOSCROLL_SPEED);\n } else if (lowerDist >= 0 && lowerDist < this.autoscrollDist) {\n $element.scrollTop(scrollTop + AUTOSCROLL_SPEED);\n }\n },\n\n /** get the nearest element based on the mouse's Y coordinate.\n * If the y is at the end of the list, return an empty jQuery object.\n */\n _getNearestElement: function(y) {\n var WIGGLE = 4;\n\n var lis = this.$(\".collection-elements li.collection-element\").toArray();\n\n for (var i = 0; i < lis.length; i++) {\n var $li = $(lis[i]);\n var top = $li.offset().top;\n var halfHeight = Math.floor($li.outerHeight() / 2) + WIGGLE;\n if (top + halfHeight > y && top - halfHeight < y) {\n return $li;\n }\n }\n return $();\n },\n\n /** drop (dragged/selected elements) onto the list, re-ordering the internal list */\n _dropElements: function(ev) {\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n // both required for firefox\n ev.preventDefault();\n ev.dataTransfer.dropEffect = \"move\";\n\n // insert before the nearest element or after the last.\n var $nearest = this._getNearestElement(ev.clientY);\n if ($nearest.length) {\n this.$dragging.insertBefore($nearest);\n } else {\n // no nearest before - insert after last element\n this.$dragging.insertAfter(this.$(\".collection-elements .collection-element\").last());\n }\n // resync the creator's list based on the new DOM order\n this._syncOrderToDom();\n return false;\n },\n\n /** resync the creator's list of elements based on the DOM order */\n _syncOrderToDom: function() {\n var creator = this;\n var newElements = [];\n //TODO: doesn't seem wise to use the dom to store these - can't we sync another way?\n this.$(\".collection-elements .collection-element\").each(function() {\n var id = $(this).attr(\"data-element-id\");\n\n var element = _.findWhere(creator.workingElements, {\n id: id\n });\n\n if (element) {\n newElements.push(element);\n } else {\n console.error(\"missing element: \", id);\n }\n });\n this.workingElements = newElements;\n this._renderList();\n },\n\n /** drag communication with element sub-views: dragstart */\n _elementDragstart: function(ev, element) {\n // auto select the element causing the event and move all selected\n element.select(true);\n this.$dragging = this.$(\".collection-elements .collection-element.selected\");\n },\n\n /** drag communication with element sub-views: dragend - remove the placeholder */\n _elementDragend: function(ev, element) {\n $(\".element-drop-placeholder\").remove();\n this.$dragging = null;\n },\n\n // ------------------------------------------------------------------------ templates\n //TODO: move to require text plugin and load these as text\n //TODO: underscore currently unnecc. bc no vars are used\n //TODO: better way of localizing text-nodes in long strings\n /** underscore template fns attached to class */\n templates: _.extend({}, baseCreator.CollectionCreatorMixin._creatorTemplates, {\n /** the header (not including help text) */\n header: _.template(\n [\n '
\",\n _l(\n [\n \"Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and \",\n \"workflows in order to have analyses done on each member of the entire group. This interface allows \",\n \"you to create a collection and re-order the final collection.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n \"Rename elements in the list by clicking on \",\n 'the existing name.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n \"Discard elements from the final created list by clicking on the \",\n '\"Discard\" button.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n \"Reorder the list by clicking and dragging elements. Select multiple elements by clicking on \",\n 'them and you can then move those selected by dragging the ',\n \"entire group. Deselect them by clicking them again or by clicking the \",\n 'the \"Clear selected\" link.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'Click the \"Start over\" link to begin again as if you had just opened ',\n \"the interface.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n ['Click the \"Cancel\" button to exit the interface.'].join(\n \"\"\n )\n ),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n 'Once your collection is complete, enter a name and ',\n 'click \"Create list\".'\n ].join(\"\")\n ),\n \"
\"\n ].join(\"\")\n ),\n\n /** shown in list when all elements are discarded */\n invalidElements: _.template(\n [\n _l(\"The following selections could not be included due to problems:\"),\n \"
<% _.each( problems, function( problem ){ %>\",\n \"
<%- problem.element.name %>: <%- problem.text %>
\",\n \"<% }); %>
\"\n ].join(\"\")\n ),\n\n /** shown in list when all elements are discarded */\n noElementsLeft: _.template(\n [\n '
\"\n ].join(\"\")\n ),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(\n [\n '
',\n '
',\n '',\n \"<% if( _.size( problems ) ){ %>\",\n _l(\"The following selections could not be included due to problems\"),\n \":\",\n \"
<% _.each( problems, function( problem ){ %>\",\n \"
<%- problem.element.name %>: <%- problem.text %>
\",\n \"<% }); %>
\",\n \"<% } else if( _.size( elements ) < 1 ){ %>\",\n _l(\"No datasets were selected\"),\n \".\",\n \"<% } %>\",\n \" \",\n _l(\"At least one element is needed for the collection\"),\n \". \",\n _l(\"You may need to \"),\n '',\n _l(\"cancel\"),\n \" \",\n _l(\"and reselect new elements\"),\n \".\",\n \"\",\n \"
\",\n \"
\",\n '\"\n ].join(\"\")\n )\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function() {\n return \"ListCollectionCreator\";\n }\n });\n\n//=============================================================================\n/** Create a modal and load its body with the given CreatorClass creator type\n * @returns {Deferred} resolved when creator has built a collection.\n */\nvar collectionCreatorModal = function _collectionCreatorModal(elements, options, CreatorClass) {\n var deferred = jQuery.Deferred();\n var modal = Galaxy.modal || new UI_MODAL.View();\n var creator;\n\n options = _.defaults(options || {}, {\n elements: elements,\n oncancel: function() {\n modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function(creator, response) {\n modal.hide();\n deferred.resolve(response);\n }\n });\n\n creator = new CreatorClass(options);\n modal.show({\n title: options.title || _l(\"Create a collection\"),\n body: creator.$el,\n width: \"80%\",\n height: \"100%\",\n closing_events: true\n });\n creator.render();\n window._collectionCreator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n/** List collection flavor of collectionCreatorModal. */\nvar listCollectionCreatorModal = function _listCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = _l(\"Create a collection from a list of datasets\");\n return collectionCreatorModal(elements, options, ListCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a list collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createListCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = listCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function(elements, name, hideSourceItems) {\n elements = elements.map(element => ({\n id: element.id,\n name: element.name,\n\n //TODO: this allows for list:list even if the filter above does not - reconcile\n src: element.history_content_type === \"dataset\" ? \"hda\" : \"hdca\"\n }));\n return contents.createHDCA(elements, \"list\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexport default {\n DatasetCollectionElementView: DatasetCollectionElementView,\n ListCollectionCreator: ListCollectionCreator,\n\n collectionCreatorModal: collectionCreatorModal,\n listCollectionCreatorModal: listCollectionCreatorModal,\n createListCollection: createListCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/list-collection-creator.js","import DC_MODEL from \"mvc/collection/collection-model\";\nimport HISTORY_CONTENT from \"mvc/history/history-content-model\";\nimport _l from \"utils/localization\";\n\n/*==============================================================================\n\nModels for DatasetCollections contained within a history.\n\nTODO:\n these might be compactable to one class if some duplication with\n collection-model is used.\n\n==============================================================================*/\nvar hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;\n\nvar ListDC = DC_MODEL.ListDatasetCollection;\nvar PairDC = DC_MODEL.PairDatasetCollection;\nvar ListPairedDC = DC_MODEL.ListPairedDatasetCollection;\nvar ListOfListsDC = DC_MODEL.ListOfListsDatasetCollection;\n\n//==============================================================================\n/** Override to post to contents route w/o id. */\nfunction buildHDCASave(_super) {\n return function _save(attributes, options) {\n if (this.isNew()) {\n options = options || {};\n options.url = `${this.urlRoot + this.get(\"history_id\")}/contents`;\n attributes = attributes || {};\n attributes.type = \"dataset_collection\";\n }\n return _super.call(this, attributes, options);\n };\n}\n\n//==============================================================================\n/** @class Backbone model for List Dataset Collection within a History.\n */\nvar HistoryListDatasetCollection = ListDC.extend(hcontentMixin).extend(\n /** @lends HistoryListDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(ListDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for Pair Dataset Collection within a History.\n * @constructs\n */\nvar HistoryPairDatasetCollection = PairDC.extend(hcontentMixin).extend(\n /** @lends HistoryPairDatasetCollection.prototype */ {\n defaults: _.extend(_.clone(PairDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(PairDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${PairDC.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for List of Pairs Dataset Collection within a History. */\nvar HistoryListPairedDatasetCollection = ListPairedDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListPairedDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:paired\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListPairedDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `History${ListPairedDC.prototype.toString.call(this)}`;\n }\n});\n\n//==============================================================================\n/** @class Backbone model for List of Lists Dataset Collection within a History. */\nvar HistoryListOfListsDatasetCollection = ListOfListsDC.extend(hcontentMixin).extend({\n defaults: _.extend(_.clone(ListOfListsDC.prototype.defaults), {\n history_content_type: \"dataset_collection\",\n collection_type: \"list:list\",\n model_class: \"HistoryDatasetCollectionAssociation\"\n }),\n\n /** Override to post to contents route w/o id. */\n save: buildHDCASave(ListOfListsDC.prototype.save),\n\n /** String representation. */\n toString: function() {\n return `HistoryListOfListsDatasetCollection(${this.get(\"name\")})`;\n }\n});\n\n//==============================================================================\nexport default {\n HistoryListDatasetCollection: HistoryListDatasetCollection,\n HistoryPairDatasetCollection: HistoryPairDatasetCollection,\n HistoryListPairedDatasetCollection: HistoryListPairedDatasetCollection,\n HistoryListOfListsDatasetCollection: HistoryListOfListsDatasetCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hdca-model.js","import DATASET_MODEL from \"mvc/dataset/dataset-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/*\nNotes:\n\nTerminology:\n DatasetCollection/DC : a container of datasets or nested DatasetCollections\n Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection\n HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history\n\n\nThis all seems too complex unfortunately:\n\n- Terminology collision between DatasetCollections (DCs) and Backbone Collections.\n- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*\n either a dataset or a nested DC. This would make the hierarchy much taller. I've\n decided to merge the contained JSON with the DC element json - making the 'has a'\n relation into an 'is a' relation. This seems simpler to me and allowed a lot of\n DRY in both models and views, but may make tracking or tracing within these models\n more difficult (since DatasetCollectionElements are now *also* DatasetAssociations\n or DatasetCollections (nested)). This also violates the rule of thumb about\n favoring aggregation over inheritance.\n- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.\n These each should a) be usable on their own, b) be usable in the context of\n nesting within a collection model (at least in the case of ListPaired), and\n c) be usable within the context of other container models (like History or\n LibraryFolder, etc.). I've tried to separate/extract classes in order to\n handle those three situations, but it's proven difficult to do in a simple,\n readable manner.\n- Ideally, histories and libraries would inherit from the same server models as\n dataset collections do since they are (in essence) dataset collections themselves -\n making the whole nested structure simpler. This would be a large, error-prone\n refactoring and migration.\n\nMany of the classes and heirarchy are meant as extension points so, while the\nrelations and flow may be difficult to understand initially, they'll allow us to\nhandle the growth or flux dataset collection in the future (w/o actually implementing\nany YAGNI).\n\n*/\n//_________________________________________________________________________________________________ ELEMENTS\n/** @class mixin for Dataset collection elements.\n * When collection elements are passed from the API, the underlying element is\n * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).\n * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues\n * effectively changing a DCE from a container to a subclass (has a --> is a).\n */\nvar DatasetCollectionElementMixin = {\n /** default attributes used by elements in a dataset collection */\n defaults: {\n model_class: \"DatasetCollectionElement\",\n element_identifier: null,\n element_index: null,\n element_type: null\n },\n\n /** merge the attributes of the sub-object 'object' into this model */\n _mergeObject: function(attributes) {\n // if we don't preserve and correct ids here, the element id becomes the object id\n // and collision in backbone's _byId will occur and only\n _.extend(attributes, attributes.object, {\n element_id: attributes.id\n });\n delete attributes.object;\n return attributes;\n },\n\n /** override to merge this.object into this */\n constructor: function(attributes, options) {\n // console.debug( '\\t DatasetCollectionElement.constructor:', attributes, options );\n attributes = this._mergeObject(attributes);\n this.idAttribute = \"element_id\";\n Backbone.Model.apply(this, arguments);\n },\n\n /** when the model is fetched, merge this.object into this */\n parse: function(response, options) {\n var attributes = response;\n attributes = this._mergeObject(attributes);\n return attributes;\n }\n};\n\n/** @class Concrete class of Generic DatasetCollectionElement */\nvar DatasetCollectionElement = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(DatasetCollectionElementMixin)\n .extend({ _logNamespace: \"collections\" });\n\n//==============================================================================\n/** @class Base/Abstract Backbone collection for Generic DCEs. */\nvar DCECollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends DCECollection.prototype */ {\n _logNamespace: \"collections\",\n\n model: DatasetCollectionElement,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetCollectionElementCollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a dataset collection element that is a dataset (HDA).\n */\nvar DatasetDCE = DATASET_MODEL.DatasetAssociation.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends DatasetDCE.prototype */ {\n /** url fn */\n url: function() {\n // won't always be an hda\n if (!this.has(\"history_id\")) {\n console.warn(\"no endpoint for non-hdas within a collection yet\");\n // (a little silly since this api endpoint *also* points at hdas)\n return `${Galaxy.root}api/datasets`;\n }\n return `${Galaxy.root}api/histories/${this.get(\"history_id\")}/contents/${this.get(\"id\")}`;\n },\n\n defaults: _.extend(\n {},\n DATASET_MODEL.DatasetAssociation.prototype.defaults,\n DatasetCollectionElementMixin.defaults\n ),\n\n _downloadQueryParameters: function() {\n var fileExt = this.get(\"file_ext\");\n var elementIdentifier = this.get(\"element_identifier\");\n var parentHdcaId = this.get(\"parent_hdca_id\");\n return `?to_ext=${fileExt}&hdca_id=${parentHdcaId}&element_identifier=${elementIdentifier}`;\n },\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually for now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t DatasetDCE.constructor:\", attributes, options);\n //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function() {\n return this.elements && this.elements.length;\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.get(\"element_identifier\");\n return `DatasetDCE({objStr})`;\n }\n }\n )\n);\n\n//==============================================================================\n/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).\n */\nvar DatasetDCECollection = DCECollection.extend(\n /** @lends DatasetDCECollection.prototype */ {\n model: DatasetDCE,\n\n /** String representation. */\n toString: function() {\n return [\"DatasetDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//_________________________________________________________________________________________________ COLLECTIONS\n/** @class Backbone model for Dataset Collections.\n * The DC API returns an array of JSON objects under the attribute elements.\n * This model:\n * - removes that array/attribute ('elements') from the model,\n * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),\n * - passes that json onto the bbone collection\n * - caches the bbone collection in this.elements\n */\nvar DatasetCollection = Backbone.Model.extend(BASE_MVC.LoggableMixin)\n .extend(BASE_MVC.SearchableModelMixin)\n .extend(\n /** @lends DatasetCollection.prototype */ {\n _logNamespace: \"collections\",\n\n /** default attributes for a model */\n defaults: {\n /* 'list', 'paired', or 'list:paired' */\n collection_type: null,\n //??\n deleted: false\n },\n\n /** Which class to use for elements */\n collectionClass: DCECollection,\n\n /** set up: create elements instance var and (on changes to elements) update them */\n initialize: function(model, options) {\n this.debug(`${this}(DatasetCollection).initialize:`, model, options, this);\n this.elements = this._createElementsModel();\n this.on(\"change:elements\", function() {\n this.log(\"change:elements\");\n //TODO: prob. better to update the collection instead of re-creating it\n this.elements = this._createElementsModel();\n });\n },\n\n /** move elements model attribute to full collection */\n _createElementsModel: function() {\n this.debug(`${this}._createElementsModel`, this.collectionClass, this.get(\"elements\"), this.elements);\n //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?\n var elements = this.get(\"elements\") || [];\n this.unset(\"elements\", { silent: true });\n var self = this;\n _.each(elements, (element, index) => {\n _.extend(element, {\n parent_hdca_id: self.get(\"id\")\n });\n });\n this.elements = new this.collectionClass(elements);\n //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );\n return this.elements;\n },\n\n // ........................................................................ common queries\n /** pass the elements back within the model json when this is serialized */\n toJSON: function() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n if (this.elements) {\n json.elements = this.elements.toJSON();\n }\n return json;\n },\n\n /** Is this collection in a 'ready' state no processing (for the collection) is left\n * to do on the server.\n */\n inReadyState: function() {\n var populated = this.get(\"populated\");\n return this.isDeletedOrPurged() || populated;\n },\n\n //TODO:?? the following are the same interface as DatasetAssociation - can we combine?\n /** Does the DC contain any elements yet? Is a fetch() required? */\n hasDetails: function() {\n return this.elements.length !== 0;\n },\n\n /** Given the filters, what models in this.elements would be returned? */\n getVisibleContents: function(filters) {\n // filters unused for now\n return this.elements;\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Is this collection deleted or purged? */\n isDeletedOrPurged: function() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n // ........................................................................ searchable\n /** searchable attributes for collections */\n searchAttributes: [\"name\", \"tags\"],\n\n // ........................................................................ misc\n /** String representation */\n toString: function() {\n var idAndName = [this.get(\"id\"), this.get(\"name\") || this.get(\"element_identifier\")];\n return `DatasetCollection(${idAndName.join(\",\")})`;\n }\n }\n );\n\n//==============================================================================\n/** Model for a DatasetCollection containing datasets (non-nested).\n */\nvar ListDatasetCollection = DatasetCollection.extend(\n /** @lends ListDatasetCollection.prototype */ {\n /** override since we know the collection will only contain datasets */\n collectionClass: DatasetDCECollection,\n\n /** String representation. */\n toString: function() {\n return `List${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//==============================================================================\n/** Model for a DatasetCollection containing fwd/rev datasets (a list of 2).\n */\nvar PairDatasetCollection = ListDatasetCollection.extend(\n /** @lends PairDatasetCollection.prototype */ {\n /** String representation. */\n toString: function() {\n return `Pair${DatasetCollection.prototype.toString.call(this)}`;\n }\n }\n);\n\n//_________________________________________________________________________________________________ NESTED COLLECTIONS\n// this is where things get weird, man. Weird.\n//TODO: it might be possible to compact all the following...I think.\n//==============================================================================\n/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection\n * (a nested collection). Currently only list:paired.\n */\nvar NestedDCDCE = DatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedDCDCE.prototype */ {\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** call the mixin constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).\n */\nvar NestedDCDCECollection = DCECollection.extend(\n /** @lends NestedDCDCECollection.prototype */ {\n /** This is a collection of nested collections */\n model: NestedDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a paired dataset collection within a list:paired dataset collection.\n */\nvar NestedPairDCDCE = PairDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedPairDCDCE.prototype */ {\n //TODO:?? possibly rename to NestedDatasetCollection?\n\n // because all objects have constructors (as this hashmap would even if this next line wasn't present)\n // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model\n // - re-apply manually it now\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedPairDCDCE.constructor:\", attributes, options);\n //DatasetCollection.constructor.call( this, attributes, options );\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedPairDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection for a backbone collection containing paired dataset collections.\n */\nvar NestedPairDCDCECollection = NestedDCDCECollection.extend(\n /** @lends PairDCDCECollection.prototype */ {\n /** We know this collection is composed of only nested pair collections */\n model: NestedPairDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedPairDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains DatasetCollections (pairs).\n */\nvar ListPairedDatasetCollection = DatasetCollection.extend(\n /** @lends ListPairedDatasetCollection.prototype */ {\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedPairDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListPairedDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\n/** @class Backbone model for a list dataset collection within a list:list dataset collection. */\nvar NestedListDCDCE = ListDatasetCollection.extend(\n BASE_MVC.mixin(\n DatasetCollectionElementMixin,\n /** @lends NestedListDCDCE.prototype */ {\n /** This is both a collection and a collection element - call the constructor */\n constructor: function(attributes, options) {\n this.debug(\"\\t NestedListDCDCE.constructor:\", attributes, options);\n DatasetCollectionElementMixin.constructor.call(this, attributes, options);\n },\n\n /** String representation. */\n toString: function() {\n var objStr = this.object ? `${this.object}` : this.get(\"element_identifier\");\n return [\"NestedListDCDCE(\", objStr, \")\"].join(\"\");\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection containing list dataset collections. */\nvar NestedListDCDCECollection = NestedDCDCECollection.extend({\n /** We know this collection is composed of only nested pair collections */\n model: NestedListDCDCE,\n\n /** String representation. */\n toString: function() {\n return [\"NestedListDCDCECollection(\", this.length, \")\"].join(\"\");\n }\n});\n\n//==============================================================================\n/** @class Backbone Model for a DatasetCollection (list) that contains other lists. */\nvar ListOfListsDatasetCollection = DatasetCollection.extend({\n /** list:paired is the only collection that itself contains collections */\n collectionClass: NestedListDCDCECollection,\n\n /** String representation. */\n toString: function() {\n return [\"ListOfListsDatasetCollection(\", this.get(\"name\"), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n ListDatasetCollection: ListDatasetCollection,\n PairDatasetCollection: PairDatasetCollection,\n ListPairedDatasetCollection: ListPairedDatasetCollection,\n ListOfListsDatasetCollection: ListOfListsDatasetCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-model.js","import HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport UTILS from \"utils/utils\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Model for a Galaxy history resource - both a record of user\n * tool use and a collection of the datasets those tools produced.\n * @name History\n * @augments Backbone.Model\n */\nvar History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(\n BASE_MVC.mixin(\n BASE_MVC.SearchableModelMixin,\n /** @lends History.prototype */ {\n _logNamespace: \"history\",\n\n /** ms between fetches when checking running jobs/datasets for updates */\n UPDATE_DELAY: 4000,\n\n // values from api (may need more)\n defaults: {\n model_class: \"History\",\n id: null,\n name: \"Unnamed History\",\n state: \"new\",\n\n deleted: false,\n contents_active: {},\n contents_states: {}\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n\n contentsClass: HISTORY_CONTENTS.HistoryContents,\n\n /** What model fields to search with */\n searchAttributes: [\"name\", \"annotation\", \"tags\"],\n\n /** Adding title and singular tag */\n searchAliases: {\n title: \"name\",\n tag: \"tags\"\n },\n\n // ........................................................................ set up/tear down\n /** Set up the model\n * @param {Object} historyJSON model data for this History\n * @param {Object} options any extra settings including logger\n */\n initialize: function(historyJSON, options) {\n options = options || {};\n this.logger = options.logger || null;\n this.log(`${this}.initialize:`, historyJSON, options);\n\n /** HistoryContents collection of the HDAs contained in this history. */\n this.contents = new this.contentsClass([], {\n history: this,\n historyId: this.get(\"id\"),\n order: options.order\n });\n\n this._setUpListeners();\n this._setUpCollectionListeners();\n\n /** cached timeout id for the dataset updater */\n this.updateTimeoutId = null;\n },\n\n /** set up any event listeners for this history including those to the contained HDAs\n * events: error:contents if an error occurred with the contents collection\n */\n _setUpListeners: function() {\n // if the model's id changes ('current' or null -> an actual id), update the contents history_id\n return this.on({\n error: function(model, xhr, options, msg, details) {\n this.clearUpdateTimeout();\n },\n \"change:id\": function(model, newId) {\n if (this.contents) {\n this.contents.historyId = newId;\n }\n }\n });\n },\n\n /** event handlers for the contents submodels */\n _setUpCollectionListeners: function() {\n if (!this.contents) {\n return this;\n }\n // bubble up errors\n return this.listenTo(this.contents, {\n error: function() {\n this.trigger.apply(this, jQuery.makeArray(arguments));\n }\n });\n },\n\n // ........................................................................ derived attributes\n /** */\n contentsShown: function() {\n var contentsActive = this.get(\"contents_active\");\n var shown = contentsActive.active || 0;\n shown += this.contents.includeDeleted ? contentsActive.deleted : 0;\n shown += this.contents.includeHidden ? contentsActive.hidden : 0;\n return shown;\n },\n\n /** convert size in bytes to a more human readable version */\n nice_size: function() {\n var size = this.get(\"size\");\n return size ? UTILS.bytesToString(size, true, 2) : _l(\"(empty)\");\n },\n\n /** override to add nice_size */\n toJSON: function() {\n return _.extend(Backbone.Model.prototype.toJSON.call(this), {\n nice_size: this.nice_size()\n });\n },\n\n /** override to allow getting nice_size */\n get: function(key) {\n if (key === \"nice_size\") {\n return this.nice_size();\n }\n return Backbone.Model.prototype.get.apply(this, arguments);\n },\n\n // ........................................................................ common queries\n /** T/F is this history owned by the current user (Galaxy.user)\n * Note: that this will return false for an anon user even if the history is theirs.\n */\n ownedByCurrUser: function() {\n // no currUser\n if (!Galaxy || !Galaxy.user) {\n return false;\n }\n // user is anon or history isn't owned\n if (Galaxy.user.isAnonymous() || Galaxy.user.id !== this.get(\"user_id\")) {\n return false;\n }\n return true;\n },\n\n /** Return the number of running jobs assoc with this history (note: unknown === 0) */\n numOfUnfinishedJobs: function() {\n var unfinishedJobIds = this.get(\"non_ready_jobs\");\n return unfinishedJobIds ? unfinishedJobIds.length : 0;\n },\n\n /** Return the number of running hda/hdcas in this history (note: unknown === 0) */\n numOfUnfinishedShownContents: function() {\n return this.contents.runningAndActive().length || 0;\n },\n\n // ........................................................................ updates\n _fetchContentRelatedAttributes: function() {\n var contentRelatedAttrs = [\"size\", \"non_ready_jobs\", \"contents_active\", \"hid_counter\"];\n return this.fetch({\n data: $.param({\n keys: contentRelatedAttrs.join(\",\")\n })\n });\n },\n\n /** check for any changes since the last time we updated (or fetch all if ) */\n refresh: function(options) {\n // console.log( this + '.refresh' );\n options = options || {};\n\n // note if there was no previous update time, all summary contents will be fetched\n var lastUpdateTime = this.lastUpdateTime;\n // if we don't flip this, then a fully-fetched list will not be re-checked via fetch\n this.contents.allFetched = false;\n var fetchFn =\n this.contents.currentPage !== 0\n ? () => this.contents.fetchPage(this.contents.currentPage)\n : () => this.contents.fetchUpdated(lastUpdateTime);\n // note: if there was no previous update time, all summary contents will be fetched\n return fetchFn().done((response, status, xhr) => {\n var serverResponseDatetime;\n try {\n serverResponseDatetime = new Date(xhr.getResponseHeader(\"Date\"));\n } catch (err) {}\n this.lastUpdateTime = serverResponseDatetime || new Date();\n this.checkForUpdates(options);\n });\n },\n\n /** continuously fetch updated contents every UPDATE_DELAY ms if this history's datasets or jobs are unfinished */\n checkForUpdates: function(options) {\n // console.log( this + '.checkForUpdates' );\n options = options || {};\n var delay = this.UPDATE_DELAY;\n if (!this.id) {\n return;\n }\n\n var _delayThenUpdate = () => {\n // prevent buildup of updater timeouts by clearing previous if any, then set new and cache id\n this.clearUpdateTimeout();\n this.updateTimeoutId = setTimeout(() => {\n this.refresh(options);\n }, delay);\n };\n\n // if there are still datasets in the non-ready state, recurse into this function with the new time\n var nonReadyContentCount = this.numOfUnfinishedShownContents();\n // console.log( 'nonReadyContentCount:', nonReadyContentCount );\n if (nonReadyContentCount > 0) {\n _delayThenUpdate();\n } else {\n // no datasets are running, but currently runnning jobs may still produce new datasets\n // see if the history has any running jobs and continue to update if so\n // (also update the size for the user in either case)\n this._fetchContentRelatedAttributes().done(historyData => {\n // console.log( 'non_ready_jobs:', historyData.non_ready_jobs );\n if (this.numOfUnfinishedJobs() > 0) {\n _delayThenUpdate();\n } else {\n // otherwise, let listeners know that all updates have stopped\n this.trigger(\"ready\");\n }\n });\n }\n },\n\n /** clear the timeout and the cached timeout id */\n clearUpdateTimeout: function() {\n if (this.updateTimeoutId) {\n clearTimeout(this.updateTimeoutId);\n this.updateTimeoutId = null;\n }\n },\n\n // ........................................................................ ajax\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** fetch this histories data (using options) then it's contents (using contentsOptions) */\n fetchWithContents: function(options, contentsOptions) {\n options = options || {};\n var self = this;\n\n // console.log( this + '.fetchWithContents' );\n // TODO: push down to a base class\n options.view = \"dev-detailed\";\n\n // fetch history then use history data to fetch (paginated) contents\n return this.fetch(options).then(function getContents(history) {\n self.contents.history = self;\n self.contents.setHistoryId(history.id);\n return self.fetchContents(contentsOptions);\n });\n },\n\n /** fetch this histories contents, adjusting options based on the stored history preferences */\n fetchContents: function(options) {\n options = options || {};\n var self = this;\n\n // we're updating, reset the update time\n self.lastUpdateTime = new Date();\n return self.contents.fetchCurrentPage(options);\n },\n\n /** save this history, _Mark_ing it as deleted (just a flag) */\n _delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */\n purge: function(options) {\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true, purged: true }, options);\n },\n /** save this history, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** Make a copy of this history on the server\n * @param {Boolean} current if true, set the copy as the new current history (default: true)\n * @param {String} name name of new history (default: none - server sets to: Copy of )\n * @fires copied passed this history and the response JSON from the copy\n * @returns {xhr}\n */\n copy: function(current, name, allDatasets) {\n current = current !== undefined ? current : true;\n if (!this.id) {\n throw new Error(\"You must set the history ID before copying it.\");\n }\n\n var postData = { history_id: this.id };\n if (current) {\n postData.current = true;\n }\n if (name) {\n postData.name = name;\n }\n if (!allDatasets) {\n postData.all_datasets = false;\n }\n postData.view = \"dev-detailed\";\n\n var history = this;\n var copy = jQuery.post(this.urlRoot, postData);\n // if current - queue to setAsCurrent before firing 'copied'\n if (current) {\n return copy.then(response => {\n var newHistory = new History(response);\n return newHistory.setAsCurrent().done(() => {\n history.trigger(\"copied\", history, response);\n });\n });\n }\n return copy.done(response => {\n history.trigger(\"copied\", history, response);\n });\n },\n\n setAsCurrent: function() {\n var history = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/set_as_current?id=${this.id}`);\n\n xhr.done(() => {\n history.trigger(\"set-as-current\", history);\n });\n return xhr;\n },\n\n // ........................................................................ misc\n toString: function() {\n return `History(${this.get(\"id\")},${this.get(\"name\")})`;\n }\n }\n )\n);\n\n//==============================================================================\nvar _collectionSuper = CONTROLLED_FETCH_COLLECTION.InfinitelyScrollingCollection;\n/** @class A collection of histories (per user)\n * that maintains the current history as the first in the collection.\n * New or copied histories become the current history.\n */\nvar HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n model: History,\n /** @type {String} initial order used by collection */\n order: \"update_time\",\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: 10,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 10,\n\n initialize: function(models, options) {\n options = options || {};\n this.log(\"HistoryCollection.initialize\", models, options);\n _collectionSuper.prototype.initialize.call(this, models, options);\n\n /** @type {boolean} should deleted histories be included */\n this.includeDeleted = options.includeDeleted || false;\n\n /** @type {String} encoded id of the history that's current */\n this.currentHistoryId = options.currentHistoryId;\n\n this.setUpListeners();\n // note: models are sent to reset *after* this fn ends; up to this point\n // the collection *is empty*\n },\n\n urlRoot: `${Galaxy.root}api/histories`,\n url: function() {\n return this.urlRoot;\n },\n\n /** set up reflexive event handlers */\n setUpListeners: function setUpListeners() {\n return this.on({\n // when a history is deleted, remove it from the collection (if optionally set to do so)\n \"change:deleted\": function(history) {\n // TODO: this becomes complicated when more filters are used\n this.debug(\"change:deleted\", this.includeDeleted, history.get(\"deleted\"));\n if (!this.includeDeleted && history.get(\"deleted\")) {\n this.remove(history);\n }\n },\n // listen for a history copy, setting it to current\n copied: function(original, newData) {\n this.setCurrent(new History(newData, []));\n },\n // when a history is made current, track the id in the collection\n \"set-as-current\": function(history) {\n var oldCurrentId = this.currentHistoryId;\n this.trigger(\"no-longer-current\", oldCurrentId);\n this.currentHistoryId = history.id;\n }\n });\n },\n\n /** override to change view */\n _buildFetchData: function(options) {\n return _.extend(_collectionSuper.prototype._buildFetchData.call(this, options), {\n view: \"dev-detailed\"\n });\n },\n\n /** override to filter out deleted and purged */\n _buildFetchFilters: function(options) {\n var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n } else {\n // force API to return both deleted and non\n //TODO: when the API is updated, remove this\n filters.deleted = null;\n }\n return _.defaults(superFilters, filters);\n },\n\n /** override to fetch current as well (as it may be outside the first 10, etc.) */\n fetchFirst: function(options) {\n var self = this;\n // TODO: batch?\n var xhr = $.when();\n if (this.currentHistoryId) {\n xhr = _collectionSuper.prototype.fetchFirst.call(self, {\n silent: true,\n limit: 1,\n filters: {\n // without these a deleted current history will return [] here and block the other xhr\n purged: \"\",\n deleted: \"\",\n \"encoded_id-in\": this.currentHistoryId\n }\n });\n }\n return xhr.then(() => {\n options = options || {};\n options.offset = 0;\n return self.fetchMore(options);\n });\n },\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_collectionSuper.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", {\n ascending: true\n }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n size: BASE_MVC.buildComparator(\"size\", {\n ascending: false\n }),\n \"size-asc\": BASE_MVC.buildComparator(\"size\", {\n ascending: true\n })\n }),\n\n /** override to always have the current history first */\n sort: function(options) {\n options = options || {};\n var silent = options.silent;\n var currentHistory = this.remove(this.get(this.currentHistoryId));\n _collectionSuper.prototype.sort.call(this, _.defaults({ silent: true }, options));\n this.unshift(currentHistory, { silent: true });\n if (!silent) {\n this.trigger(\"sort\", this, options);\n }\n return this;\n },\n\n /** create a new history and by default set it to be the current history */\n create: function create(data, hdas, historyOptions, xhrOptions) {\n //TODO: .create is actually a collection function that's overridden here\n var collection = this;\n\n var xhr = jQuery.getJSON(`${Galaxy.root}history/create_new_current`);\n return xhr.done(newData => {\n collection.setCurrent(new History(newData, [], historyOptions || {}));\n });\n },\n\n /** set the current history to the given history, placing it first in the collection.\n * Pass standard bbone options for use in unshift.\n * @triggers new-current passed history and this collection\n */\n setCurrent: function(history, options) {\n options = options || {};\n // new histories go in the front\n this.unshift(history, options);\n this.currentHistoryId = history.get(\"id\");\n if (!options.silent) {\n this.trigger(\"new-current\", history, this);\n }\n return this;\n },\n\n toString: function toString() {\n return `HistoryCollection(${this.length},current:${this.currentHistoryId})`;\n }\n});\n\n//==============================================================================\nexport default {\n History: History,\n HistoryCollection: HistoryCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-model.js","import CONTROLLED_FETCH_COLLECTION from \"mvc/base/controlled-fetch-collection\";\nimport HDA_MODEL from \"mvc/history/hda-model\";\nimport HDCA_MODEL from \"mvc/history/hdca-model\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport AJAX_QUEUE from \"utils/ajax-queue\";\n\n//==============================================================================\nvar _super = CONTROLLED_FETCH_COLLECTION.PaginatedCollection;\n/** @class Backbone collection for history content.\n * NOTE: history content seems like a dataset collection, but differs in that it is mixed:\n * each element can be either an HDA (dataset) or a DatasetCollection and co-exist on\n * the same level.\n * Dataset collections on the other hand are not mixed and (so far) can only contain either\n * HDAs or child dataset collections on one level.\n * This is why this does not inherit from any of the DatasetCollections (currently).\n */\nvar HistoryContents = _super.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: \"history\",\n\n // ........................................................................ set up\n limitPerPage: 500,\n\n /** @type {Integer} how many contents per call to fetch when using progressivelyFetchDetails */\n limitPerProgressiveFetch: 500,\n\n /** @type {String} order used here and when fetching from server */\n order: \"hid\",\n\n /** root api url */\n urlRoot: `${Galaxy.root}api/histories`,\n\n /** complete api url */\n url: function() {\n return `${this.urlRoot}/${this.historyId}/contents`;\n },\n\n /** Set up */\n initialize: function(models, options) {\n options = options || {};\n _super.prototype.initialize.call(this, models, options);\n\n this.history = options.history || null;\n this.setHistoryId(options.historyId || null);\n /** @type {Boolean} does this collection contain and fetch deleted elements */\n this.includeDeleted = options.includeDeleted || this.includeDeleted;\n /** @type {Boolean} does this collection contain and fetch non-visible elements */\n this.includeHidden = options.includeHidden || this.includeHidden;\n\n // backbonejs uses collection.model.prototype.idAttribute to determine if a model is *already* in a collection\n // and either merged or replaced. In this case, our 'model' is a function so we need to add idAttribute\n // manually here - if we don't, contents will not merge but be replaced/swapped.\n this.model.prototype.idAttribute = \"type_id\";\n },\n\n // ........................................................................ composite collection\n /** since history content is a mix, override model fn into a factory, creating based on history_content_type */\n model: function(attrs, options) {\n if (attrs.history_content_type === \"dataset\") {\n return new HDA_MODEL.HistoryDatasetAssociation(attrs, options);\n } else if (attrs.history_content_type === \"dataset_collection\") {\n switch (attrs.collection_type) {\n case \"list\":\n return new HDCA_MODEL.HistoryListDatasetCollection(attrs, options);\n case \"paired\":\n return new HDCA_MODEL.HistoryPairDatasetCollection(attrs, options);\n case \"list:paired\":\n return new HDCA_MODEL.HistoryListPairedDatasetCollection(attrs, options);\n case \"list:list\":\n return new HDCA_MODEL.HistoryListOfListsDatasetCollection(attrs, options);\n }\n // This is a hack inside a hack:\n // Raise a plain object with validationError to fake a model.validationError\n // (since we don't have a model to use validate with)\n // (the outer hack being the mixed content/model function in this collection)\n var msg = `Unknown collection_type: ${attrs.collection_type}`;\n console.warn(msg, attrs);\n return { validationError: msg };\n }\n return {\n validationError: `Unknown history_content_type: ${attrs.history_content_type}`\n };\n },\n\n setHistoryId: function(newId) {\n this.historyId = newId;\n this._setUpWebStorage();\n },\n\n /** Set up client side storage. Currently PersistanStorage keyed under 'history:' */\n _setUpWebStorage: function(initialSettings) {\n // TODO: use initialSettings\n if (!this.historyId) {\n return;\n }\n this.storage = new HISTORY_PREFS.HistoryPrefs({\n id: HISTORY_PREFS.HistoryPrefs.historyStorageKey(this.historyId)\n });\n this.trigger(\"new-storage\", this.storage, this);\n\n this.on({\n \"include-deleted\": function(newVal) {\n this.storage.includeDeleted(newVal);\n },\n \"include-hidden\": function(newVal) {\n this.storage.includeHidden(newVal);\n }\n });\n\n this.includeDeleted = this.storage.includeDeleted() || false;\n this.includeHidden = this.storage.includeHidden() || false;\n return this;\n },\n\n // ........................................................................ common queries\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: _.extend(_.clone(_super.prototype.comparators), {\n name: BASE_MVC.buildComparator(\"name\", { ascending: true }),\n \"name-dsc\": BASE_MVC.buildComparator(\"name\", {\n ascending: false\n }),\n hid: BASE_MVC.buildComparator(\"hid\", { ascending: false }),\n \"hid-asc\": BASE_MVC.buildComparator(\"hid\", { ascending: true })\n }),\n\n /** Get every model in this collection not in a 'ready' state (running). */\n running: function() {\n return this.filter(c => !c.inReadyState());\n },\n\n /** return contents that are not ready and not deleted/hidden */\n runningAndActive: function() {\n return this.filter(\n c =>\n !c.inReadyState() &&\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** Get the model with the given hid\n * @param {Int} hid the hid to search for\n * @returns {HistoryDatasetAssociation} the model with the given hid or undefined if not found\n */\n getByHid: function(hid) {\n // note: there *can* be more than one content with a given hid, this finds the first based on order\n return this.findWhere({ hid: hid });\n },\n\n /** return true if all contents have details */\n haveDetails: function() {\n return this.all(c => c.hasDetails());\n },\n\n // ........................................................................ hidden / deleted\n /** return a new contents collection of only hidden items */\n hidden: function() {\n return this.filter(c => c.hidden());\n },\n\n /** return a new contents collection of only hidden items */\n deleted: function() {\n return this.filter(c => c.get(\"deleted\"));\n },\n\n /** return a new contents collection of only hidden items */\n visibleAndUndeleted: function() {\n return this.filter(\n c =>\n c.get(\"visible\") &&\n // TODO: deletedOrPurged?\n !c.get(\"deleted\")\n );\n },\n\n /** create a setter in order to publish the change */\n setIncludeDeleted: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeDeleted) {\n this.includeDeleted = setting;\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-deleted\", setting, this);\n }\n },\n\n /** create a setter in order to publish the change */\n setIncludeHidden: function(setting, options) {\n if (_.isBoolean(setting) && setting !== this.includeHidden) {\n this.includeHidden = setting;\n options = options || {};\n if (_.result(options, \"silent\")) {\n return;\n }\n this.trigger(\"include-hidden\", setting, this);\n }\n },\n\n // ........................................................................ ajax\n // ............ controlled fetch collection\n /** override to get expanded ids from sessionStorage and pass to API as details */\n fetch: function(options) {\n options = options || {};\n if (this.historyId && !options.details) {\n var prefs = HISTORY_PREFS.HistoryPrefs.get(this.historyId).toJSON();\n if (!_.isEmpty(prefs.expandedIds)) {\n options.details = _.values(prefs.expandedIds).join(\",\");\n }\n }\n return _super.prototype.fetch.call(this, options);\n },\n\n // ............. ControlledFetch stuff\n /** override to include the API versioning flag */\n _buildFetchData: function(options) {\n return _.extend(_super.prototype._buildFetchData.call(this, options), {\n v: \"dev\"\n });\n },\n\n /** Extend to include details and version */\n _fetchParams: _super.prototype._fetchParams.concat([\n // TODO: remove (the need for) both\n /** version */\n \"v\",\n /** dataset ids to get full details of */\n \"details\"\n ]),\n\n /** override to add deleted/hidden filters */\n _buildFetchFilters: function(options) {\n var superFilters = _super.prototype._buildFetchFilters.call(this, options) || {};\n var filters = {};\n if (!this.includeDeleted) {\n filters.deleted = false;\n filters.purged = false;\n }\n if (!this.includeHidden) {\n filters.visible = true;\n }\n return _.defaults(superFilters, filters);\n },\n\n // ............ paginated collection\n getTotalItemCount: function() {\n return this.history.contentsShown();\n },\n\n // ............ history contents specific ajax\n /** override to filter requested contents to those updated after the Date 'since' */\n fetchUpdated: function(since, options) {\n if (since) {\n options = options || { filters: {} };\n options.remove = false;\n options.filters = {\n \"update_time-ge\": since.toISOString(),\n // workflows will produce hidden datasets (non-output datasets) that still\n // need to be updated in the collection or they'll update forever\n // we can remove the default visible filter by using an 'empty' value\n visible: \"\"\n };\n }\n return this.fetch(options);\n },\n\n /** fetch all the deleted==true contents of this collection */\n fetchDeleted: function(options) {\n options = options || {};\n options.filters = _.extend(options.filters, {\n // all deleted, purged or not\n deleted: true,\n purged: undefined\n });\n options.remove = false;\n\n this.trigger(\"fetching-deleted\", this);\n return this.fetch(options).always(() => {\n this.trigger(\"fetching-deleted-done\", this);\n });\n },\n\n /** fetch all the visible==false contents of this collection */\n fetchHidden: function(options) {\n options = options || {};\n var self = this;\n options.filters = _.extend(options.filters, {\n visible: false\n });\n options.remove = false;\n\n self.trigger(\"fetching-hidden\", self);\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-hidden-done\", self);\n });\n },\n\n /** fetch detailed model data for all contents in this collection */\n fetchAllDetails: function(options) {\n options = options || {};\n var detailsFlag = { details: \"all\" };\n options.data = _.extend(options.data || {}, detailsFlag);\n return this.fetch(options);\n },\n\n /** specialty fetch method for retrieving the element_counts of all hdcas in the history */\n fetchCollectionCounts: function(options) {\n options = options || {};\n options.keys = [\"type_id\", \"element_count\"].join(\",\");\n options.filters = _.extend(options.filters || {}, {\n history_content_type: \"dataset_collection\"\n });\n options.remove = false;\n return this.fetch(options);\n },\n\n // ............. quasi-batch ops\n // TODO: to batch\n /** helper that fetches using filterParams then calls save on each fetched using updateWhat as the save params */\n _filterAndUpdate: function(filterParams, updateWhat) {\n var self = this;\n var idAttribute = self.model.prototype.idAttribute;\n var updateArgs = [updateWhat];\n\n return self.fetch({ filters: filterParams, remove: false }).then(fetched => {\n // convert filtered json array to model array\n fetched = fetched.reduce((modelArray, currJson, i) => {\n var model = self.get(currJson[idAttribute]);\n return model ? modelArray.concat(model) : modelArray;\n }, []);\n return self.ajaxQueue(\"save\", updateArgs, fetched);\n });\n },\n\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function(ajaxFn, args, collection) {\n collection = collection || this.models;\n return new AJAX_QUEUE.AjaxQueue(\n collection\n .slice()\n .reverse()\n .map((content, i) => {\n var fn = _.isString(ajaxFn) ? content[ajaxFn] : ajaxFn;\n return () => fn.apply(content, args);\n })\n ).deferred;\n },\n\n /** fetch contents' details in batches of limitPerCall - note: only get searchable details here */\n progressivelyFetchDetails: function(options) {\n options = options || {};\n var deferred = jQuery.Deferred();\n var self = this;\n var limit = options.limitPerCall || self.limitPerProgressiveFetch;\n // TODO: only fetch tags and annotations if specifically requested\n var searchAttributes = HDA_MODEL.HistoryDatasetAssociation.prototype.searchAttributes;\n var detailKeys = searchAttributes.join(\",\");\n\n function _recursivelyFetch(offset) {\n offset = offset || 0;\n var _options = _.extend(_.clone(options), {\n view: \"summary\",\n keys: detailKeys,\n limit: limit,\n offset: offset,\n reset: offset === 0,\n remove: false\n });\n\n _.defer(() => {\n self.fetch\n .call(self, _options)\n .fail(deferred.reject)\n .done(response => {\n deferred.notify(response, limit, offset);\n if (response.length !== limit) {\n self.allFetched = true;\n deferred.resolve(response, limit, offset);\n } else {\n _recursivelyFetch(offset + limit);\n }\n });\n });\n }\n _recursivelyFetch();\n return deferred;\n },\n\n /** does some bit of JSON represent something that can be copied into this contents collection */\n isCopyable: function(contentsJSON) {\n var copyableModelClasses = [\"HistoryDatasetAssociation\", \"HistoryDatasetCollectionAssociation\"];\n return (\n _.isObject(contentsJSON) && contentsJSON.id && _.contains(copyableModelClasses, contentsJSON.model_class)\n );\n },\n\n /** copy an existing, accessible hda into this collection */\n copy: function(json) {\n // TODO: somehow showhorn all this into 'save'\n var id;\n\n var type;\n var contentType;\n if (_.isString(json)) {\n id = json;\n contentType = \"hda\";\n type = \"dataset\";\n } else {\n id = json.id;\n contentType =\n {\n HistoryDatasetAssociation: \"hda\",\n LibraryDatasetDatasetAssociation: \"ldda\",\n HistoryDatasetCollectionAssociation: \"hdca\"\n }[json.model_class] || \"hda\";\n type = contentType === \"hdca\" ? \"dataset_collection\" : \"dataset\";\n }\n var collection = this;\n\n var xhr = jQuery\n .ajax(this.url(), {\n method: \"POST\",\n contentType: \"application/json\",\n data: JSON.stringify({\n content: id,\n source: contentType,\n type: type\n })\n })\n .done(response => {\n collection.add([response], { parse: true });\n })\n .fail((error, status, message) => {\n collection.trigger(\"error\", collection, xhr, {}, \"Error copying contents\", {\n type: type,\n id: id,\n source: contentType\n });\n });\n\n return xhr;\n },\n\n /** create a new HDCA in this collection */\n createHDCA: function(elementIdentifiers, collectionType, name, hideSourceItems, options) {\n // normally collection.create returns the new model, but we need the promise from the ajax, so we fake create\n //precondition: elementIdentifiers is an array of plain js objects\n // in the proper form to create the collectionType\n var hdca = this.model({\n history_content_type: \"dataset_collection\",\n collection_type: collectionType,\n history_id: this.historyId,\n name: name,\n hide_source_items: hideSourceItems || false,\n // should probably be able to just send in a bunch of json here and restruct per class\n // note: element_identifiers is now (incorrectly) an attribute\n element_identifiers: elementIdentifiers\n // do not create the model on the client until the ajax returns\n });\n return hdca.save(options);\n },\n\n // ........................................................................ searching\n /** return true if all contents have the searchable attributes */\n haveSearchDetails: function() {\n return (\n this.allFetched &&\n this.all((\n content // null (which is a valid returned annotation value)\n ) =>\n // will return false when using content.has( 'annotation' )\n //TODO: a bit hacky - formalize\n _.has(content.attributes, \"annotation\")\n )\n );\n },\n\n /** return a new collection of contents whose attributes contain the substring matchesWhat */\n matches: function(matchesWhat) {\n return this.filter(content => content.matches(matchesWhat));\n },\n\n // ........................................................................ misc\n /** In this override, copy the historyId to the clone */\n clone: function() {\n var clone = Backbone.Collection.prototype.clone.call(this);\n clone.historyId = this.historyId;\n return clone;\n },\n\n /** String representation. */\n toString: function() {\n return [\"HistoryContents(\", [this.historyId, this.length].join(), \")\"].join(\"\");\n }\n});\n\n//==============================================================================\nexport default {\n HistoryContents: HistoryContents\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-contents.js","import BASE_MVC from \"mvc/base-mvc\";\n\nvar logNamespace = \"history\";\n\n// ============================================================================\n/** session storage for individual history preferences */\nvar HistoryPrefs = BASE_MVC.SessionStorageModel.extend(\n /** @lends HistoryPrefs.prototype */ {\n //TODO:?? move to user prefs?\n defaults: {\n //TODO:?? expandedIds to array?\n expandedIds: {},\n show_deleted: false,\n show_hidden: false\n },\n\n /** add an hda id to the hash of expanded hdas */\n addExpanded: function(model) {\n //TODO: use type_id and not model\n var current = this.get(\"expandedIds\");\n current[model.id] = model.get(\"id\");\n this.save(\"expandedIds\", current);\n },\n\n /** remove an hda id from the hash of expanded hdas */\n removeExpanded: function(model) {\n var current = this.get(\"expandedIds\");\n delete current[model.id];\n this.save(\"expandedIds\", current);\n },\n\n isExpanded: function(contentId) {\n return _.result(this.get(\"expandedIds\"), contentId, false);\n },\n\n allExpanded: function() {\n return _.values(this.get(\"expandedIds\"));\n },\n\n clearExpanded: function() {\n this.set(\"expandedIds\", {});\n },\n\n includeDeleted: function(val) {\n // moving the invocation here so other components don't need to know the key\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_deleted\", val);\n }\n return this.get(\"show_deleted\");\n },\n\n includeHidden: function(val) {\n // TODO: change this key later\n if (!_.isUndefined(val)) {\n this.set(\"show_hidden\", val);\n }\n return this.get(\"show_hidden\");\n },\n\n toString: function() {\n return `HistoryPrefs(${this.id})`;\n }\n },\n {\n // ........................................................................ class vars\n // class lvl for access w/o instantiation\n storageKeyPrefix: \"history:\",\n\n /** key string to store each histories settings under */\n historyStorageKey: function historyStorageKey(historyId) {\n if (!historyId) {\n throw new Error(`HistoryPrefs.historyStorageKey needs valid id: ${historyId}`);\n }\n // single point of change\n return HistoryPrefs.storageKeyPrefix + historyId;\n },\n\n /** return the existing storage for the history with the given id (or create one if it doesn't exist) */\n get: function get(historyId) {\n return new HistoryPrefs({\n id: HistoryPrefs.historyStorageKey(historyId)\n });\n },\n\n /** clear all history related items in sessionStorage */\n clearAll: function clearAll(historyId) {\n for (var key in sessionStorage) {\n if (key.indexOf(HistoryPrefs.storageKeyPrefix) === 0) {\n sessionStorage.removeItem(key);\n }\n }\n }\n }\n);\n\n//==============================================================================\nexport default {\n HistoryPrefs: HistoryPrefs\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-preferences.js","import BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"list\";\n//==============================================================================\n/** A view which, when first rendered, shows only summary data/attributes, but\n * can be expanded to show further details (and optionally fetch those\n * details from the server).\n */\nvar ExpandableView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: Although the reasoning behind them is different, this shares a lot with HiddenUntilActivated above: combine them\n //PRECONDITION: model must have method hasDetails\n //PRECONDITION: subclasses must have templates.el and templates.details\n\n initialize: function(attributes) {\n /** are the details of this view expanded/shown or not? */\n this.expanded = attributes.expanded || false;\n this.log(\"\\t expanded:\", this.expanded);\n this.fxSpeed = attributes.fxSpeed !== undefined ? attributes.fxSpeed : this.fxSpeed;\n },\n\n // ........................................................................ render main\n /** jq fx speed */\n fxSpeed: \"fast\",\n\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function(speed) {\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n * If the view is already expanded, build the details as well.\n */\n _buildNewRender: function() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = $(this.templates.el(this.model.toJSON(), this));\n if (this.expanded) {\n this.$details($newRender).replaceWith(this._renderDetails().show());\n }\n return $newRender;\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var view = this;\n\n if (speed === 0) {\n view._swapNewRender($newRender);\n view.trigger(\"rendered\", view);\n } else {\n $(view).queue(\"fx\", [\n next => {\n view.$el.fadeOut(speed, next);\n },\n next => {\n view._swapNewRender($newRender);\n next();\n },\n next => {\n view.$el.fadeIn(speed, next);\n },\n next => {\n view.trigger(\"rendered\", view);\n next();\n }\n ]);\n }\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function($newRender) {\n return this.$el\n .empty()\n .attr(\"class\", _.isFunction(this.className) ? this.className() : this.className)\n .append($newRender.children());\n },\n\n /** set up js behaviors, event handlers for elements within the given container\n * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)\n //make_popup_menus( $where );\n $where.find(\"[title]\").tooltip({ placement: \"bottom\" });\n },\n\n // ......................................................................... details\n /** shortcut to details DOM (as jQ) */\n $details: function($where) {\n $where = $where || this.$el;\n return $where.find(\"> .details\");\n },\n\n /** build the DOM for the details and set up behaviors on it */\n _renderDetails: function() {\n var $newDetails = $(this.templates.details(this.model.toJSON(), this));\n this._setUpBehaviors($newDetails);\n return $newDetails;\n },\n\n // ......................................................................... expansion/details\n /** Show or hide the details\n * @param {Boolean} expand if true, expand; if false, collapse\n */\n toggleExpanded: function(expand) {\n expand = expand === undefined ? !this.expanded : expand;\n if (expand) {\n this.expand();\n } else {\n this.collapse();\n }\n return this;\n },\n\n /** Render and show the full, detailed body of this view including extra data and controls.\n * note: if the model does not have detailed data, fetch that data before showing the body\n * @fires expanded when a body has been expanded\n */\n expand: function() {\n var view = this;\n return view._fetchModelDetails().always(() => {\n view._expand();\n });\n },\n\n /** Check for model details and, if none, fetch them.\n * @returns {jQuery.promise} the model.fetch.xhr if details are being fetched, an empty promise if not\n */\n _fetchModelDetails: function() {\n if (!this.model.hasDetails()) {\n return this.model.fetch();\n }\n return jQuery.when();\n },\n\n /** Inner fn called when expand (public) has fetched the details */\n _expand: function() {\n var view = this;\n var $newDetails = view._renderDetails();\n view.$details().replaceWith($newDetails);\n // needs to be set after the above or the slide will not show\n view.expanded = true;\n view.$details().slideDown(view.fxSpeed, () => {\n view.trigger(\"expanded\", view);\n });\n },\n\n /** Hide the body/details of an HDA.\n * @fires collapsed when a body has been collapsed\n */\n collapse: function() {\n this.debug(`${this}(ExpandableView).collapse`);\n var view = this;\n view.expanded = false;\n this.$details().slideUp(view.fxSpeed, () => {\n view.trigger(\"collapsed\", view);\n });\n }\n});\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * Inherits from Expandable, Selectable, Draggable.\n * The DOM contains warnings, a title bar, and a series of primary action controls.\n * Primary actions are meant to be easily accessible item functions (such as delete)\n * that are rendered in the title bar.\n *\n * Details are rendered when the user clicks the title bar or presses enter/space when\n * the title bar is in focus.\n *\n * Designed as a base class for history panel contents - but usable elsewhere (I hope).\n */\nvar ListItemView = ExpandableView.extend(\n BASE_MVC.mixin(BASE_MVC.SelectableViewMixin, BASE_MVC.DraggableViewMixin, {\n tagName: \"div\",\n className: \"list-item\",\n\n /** Set up the base class and all mixins */\n initialize: function(attributes) {\n ExpandableView.prototype.initialize.call(this, attributes);\n BASE_MVC.SelectableViewMixin.initialize.call(this, attributes);\n BASE_MVC.DraggableViewMixin.initialize.call(this, attributes);\n this._setUpListeners();\n },\n\n /** event listeners */\n _setUpListeners: function() {\n // hide the primary actions in the title bar when selectable and narrow\n this.on(\n \"selectable\",\n function(isSelectable) {\n if (isSelectable) {\n this.$(\".primary-actions\").hide();\n } else {\n this.$(\".primary-actions\").show();\n }\n },\n this\n );\n return this;\n },\n\n // ........................................................................ rendering\n /** In this override, call methods to build warnings, titlebar and primary actions */\n _buildNewRender: function() {\n var $newRender = ExpandableView.prototype._buildNewRender.call(this);\n $newRender.children(\".warnings\").replaceWith(this._renderWarnings());\n $newRender.children(\".title-bar\").replaceWith(this._renderTitleBar());\n $newRender.children(\".primary-actions\").append(this._renderPrimaryActions());\n $newRender.find(\"> .title-bar .subtitle\").replaceWith(this._renderSubtitle());\n return $newRender;\n },\n\n /** In this override, render the selector controls and set up dragging before the swap */\n _swapNewRender: function($newRender) {\n ExpandableView.prototype._swapNewRender.call(this, $newRender);\n if (this.selectable) {\n this.showSelector(0);\n }\n if (this.draggable) {\n this.draggableOn();\n }\n return this.$el;\n },\n\n /** Render any warnings the item may need to show (e.g. \"I'm deleted\") */\n _renderWarnings: function() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.warnings, templateFn => {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderTitleBar: function() {\n return $(this.templates.titleBar(this.model.toJSON(), this));\n },\n\n /** Return an array of jQ objects containing common/easily-accessible item controls */\n _renderPrimaryActions: function() {\n // override this\n return [];\n },\n\n /** Render the title bar (the main/exposed SUMMARY dom element) */\n _renderSubtitle: function() {\n return $(this.templates.subtitle(this.model.toJSON(), this));\n },\n\n // ......................................................................... events\n /** event map */\n events: {\n // expand the body when the title is clicked or when in focus and space or enter is pressed\n \"click .title-bar\": \"_clickTitleBar\",\n \"keydown .title-bar\": \"_keyDownTitleBar\",\n \"click .selector\": \"toggleSelect\"\n },\n\n /** expand when the title bar is clicked */\n _clickTitleBar: function(event) {\n event.stopPropagation();\n if (event.altKey) {\n this.toggleSelect(event);\n if (!this.selectable) {\n this.showSelector();\n }\n } else {\n this.toggleExpanded();\n }\n },\n\n /** expand when the title bar is in focus and enter or space is pressed */\n _keyDownTitleBar: function(event) {\n // bail (with propagation) if keydown and not space or enter\n var KEYCODE_SPACE = 32;\n\n var KEYCODE_RETURN = 13;\n if (\n event &&\n event.type === \"keydown\" &&\n (event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN)\n ) {\n this.toggleExpanded();\n event.stopPropagation();\n return false;\n }\n return true;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `ListItemView(${modelString})`;\n }\n })\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListItemView.prototype.templates = (() => {\n var elTemplato = BASE_MVC.wrapTemplate([\n '
\",\n // space for title bar buttons - gen. floated to the right\n '',\n '',\n\n // expandable area for more details\n '',\n \"
\"\n ]);\n\n var warnings = {};\n\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display\n '
',\n //TODO: prob. belongs in dataset-list-item\n '',\n '
',\n '<%- element.name %>',\n \"
\",\n '',\n \"
\"\n ],\n \"element\"\n );\n\n var subtitleTemplate = BASE_MVC.wrapTemplate([\n // override this\n ''\n ]);\n\n var detailsTemplate = BASE_MVC.wrapTemplate([\n // override this\n ''\n ]);\n\n return {\n el: elTemplato,\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate,\n details: detailsTemplate\n };\n})();\n\n//==============================================================================\n/** A view that is displayed in some larger list/grid/collection.\n * *AND* can display some sub-list of it's own when expanded (e.g. dataset collections).\n * This list will 'foldout' when the item is expanded depending on this.foldoutStyle:\n * If 'foldout': will expand vertically to show the nested list\n * If 'drilldown': will overlay the parent list\n *\n * Inherits from ListItemView.\n *\n * _renderDetails does the work of creating this.details: a sub-view that shows the nested list\n */\nvar FoldoutListItemView = ListItemView.extend({\n /** If 'foldout': show the sub-panel inside the expanded item\n * If 'drilldown': only fire events and handle by pub-sub\n * (allow the panel containing this item to attach it, hide itself, etc.)\n */\n foldoutStyle: \"foldout\",\n /** Panel view class to instantiate for the sub-panel */\n foldoutPanelClass: null,\n\n /** override to:\n * add attributes foldoutStyle and foldoutPanelClass for config poly\n * disrespect attributes.expanded if drilldown\n */\n initialize: function(attributes) {\n if (this.foldoutStyle === \"drilldown\") {\n this.expanded = false;\n }\n this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;\n this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;\n\n ListItemView.prototype.initialize.call(this, attributes);\n this.foldout = this._createFoldoutPanel();\n },\n\n /** in this override, attach the foldout panel when rendering details */\n _renderDetails: function() {\n if (this.foldoutStyle === \"drilldown\") {\n return $();\n }\n var $newDetails = ListItemView.prototype._renderDetails.call(this);\n return this._attachFoldout(this.foldout, $newDetails);\n },\n\n /** In this override, handle collection expansion. */\n _createFoldoutPanel: function() {\n var model = this.model;\n var FoldoutClass = this._getFoldoutPanelClass(model);\n var options = this._getFoldoutPanelOptions(model);\n\n var foldout = new FoldoutClass(\n _.extend(options, {\n model: model\n })\n );\n\n return foldout;\n },\n\n /** Stub to return proper foldout panel class */\n _getFoldoutPanelClass: function() {\n // override\n return this.foldoutPanelClass;\n },\n\n /** Stub to return proper foldout panel options */\n _getFoldoutPanelOptions: function() {\n return {\n // propagate foldout style down\n foldoutStyle: this.foldoutStyle,\n fxSpeed: this.fxSpeed\n };\n },\n\n /** Render the foldout panel inside the view, hiding controls */\n _attachFoldout: function(foldout, $whereTo) {\n $whereTo = $whereTo || this.$(\"> .details\");\n this.foldout = foldout.render(0);\n foldout.$(\"> .controls\").hide();\n return $whereTo.append(foldout.$el);\n },\n\n /** In this override, branch on foldoutStyle to show expanded */\n expand: function() {\n var view = this;\n return view._fetchModelDetails().always(() => {\n if (view.foldoutStyle === \"foldout\") {\n view._expand();\n } else if (view.foldoutStyle === \"drilldown\") {\n view._expandByDrilldown();\n }\n });\n },\n\n /** For drilldown, set up close handler and fire expanded:drilldown\n * containing views can listen to this and handle other things\n * (like hiding themselves) by listening for expanded/collapsed:drilldown\n */\n _expandByDrilldown: function() {\n var view = this;\n // attachment and rendering done by listener\n view.listenTo(view.foldout, \"close\", () => {\n view.trigger(\"collapsed:drilldown\", view, view.foldout);\n });\n view.trigger(\"expanded:drilldown\", view, view.foldout);\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nFoldoutListItemView.prototype.templates = (() => {\n var detailsTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n // override with more info (that goes above the panel)\n \"
\"\n ],\n \"collection\"\n );\n\n return _.extend({}, ListItemView.prototype.templates, {\n details: detailsTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n ExpandableView: ExpandableView,\n ListItemView: ListItemView,\n FoldoutListItemView: FoldoutListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/list/list-item.js","import LIST_ITEM from \"mvc/list/list-item\";\nimport STATES from \"mvc/dataset/states\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"dataset\";\n/*==============================================================================\nTODO:\n straighten out state rendering and templates used\n inaccessible/STATES.NOT_VIEWABLE is a special case\n simplify button rendering\n\n==============================================================================*/\nvar _super = LIST_ITEM.ListItemView;\n/** @class Read only list view for either LDDAs, HDAs, or HDADCEs.\n * Roughly, any DatasetInstance (and not a raw Dataset).\n */\nvar DatasetListItemView = _super.extend(\n /** @lends DatasetListItemView.prototype */ {\n _logNamespace: logNamespace,\n\n className: `${_super.prototype.className} dataset`,\n //TODO:?? doesn't exactly match an hda's type_id\n id: function() {\n return [\"dataset\", this.model.get(\"id\")].join(\"-\");\n },\n\n /** Set up: instance vars, options, and event handlers */\n initialize: function(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(`${this}.initialize:`, attributes);\n _super.prototype.initialize.call(this, attributes);\n\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n },\n\n /** event listeners */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n var self = this;\n\n // re-rendering on any model changes\n return self.listenTo(self.model, {\n change: function(model) {\n // if the model moved into the ready state and is expanded without details, fetch those details now\n if (\n self.model.changedAttributes().state &&\n self.model.inReadyState() &&\n self.expanded &&\n !self.model.hasDetails()\n ) {\n // normally, will render automatically (due to fetch -> change),\n // but! setting_metadata sometimes doesn't cause any other changes besides state\n // so, not rendering causes it to seem frozen in setting_metadata state\n self.model.fetch({ silent: true }).done(() => {\n self.render();\n });\n } else {\n if (_.has(model.changed, \"tags\") && _.keys(model.changed).length === 1) {\n // If only the tags have changed, rerender specifically\n // the titlebar region. Otherwise default to the full\n // render.\n self.$(\".nametags\").html(self._renderNametags());\n } else {\n self.render();\n }\n }\n }\n });\n },\n\n // ......................................................................... expandable\n /** In this override, only get details if in the ready state, get rerunnable if in other states.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... removal\n /** Remove this view's html from the DOM and remove all event listeners.\n * @param {Number or String} speed jq effect speed\n * @param {Function} callback an optional function called when removal is done (scoped to this view)\n */\n remove: function(speed, callback) {\n var view = this;\n speed = speed || this.fxSpeed;\n this.$el.fadeOut(speed, () => {\n Backbone.View.prototype.remove.call(view);\n if (callback) {\n callback.call(view);\n }\n });\n },\n\n // ......................................................................... rendering\n /* TODO:\n dataset states are the issue primarily making dataset rendering complex\n each state should have it's own way of displaying/set of details\n often with different actions that can be applied\n throw in deleted/purged/visible and things get complicated easily\n I've considered (a couple of times) - creating a view for each state\n - but recreating the view during an update...seems wrong\n */\n /** In this override, add the dataset state as a class for use with state-based CSS */\n _swapNewRender: function($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n if (this.model.has(\"state\")) {\n this.$el.addClass(`state-${this.model.get(\"state\")}`);\n }\n return this.$el;\n },\n\n // ................................................................................ titlebar\n /** In this override, add the dataset display button. */\n _renderPrimaryActions: function() {\n // render just the display for read-only\n return [this._renderDisplayButton()];\n },\n\n /** Render icon-button to display dataset data */\n _renderDisplayButton: function() {\n // don't show display if not viewable or not accessible\n var state = this.model.get(\"state\");\n if (state === STATES.NOT_VIEWABLE || state === STATES.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n\n var displayBtnData = {\n target: this.linkTarget,\n classes: \"display-btn\"\n };\n\n // show a disabled display if the data's been purged\n if (this.model.get(\"purged\")) {\n displayBtnData.disabled = true;\n displayBtnData.title = _l(\"Cannot display datasets removed from disk\");\n\n // disable if still uploading\n } else if (state === STATES.UPLOAD) {\n displayBtnData.disabled = true;\n displayBtnData.title = _l(\"This dataset must finish uploading before it can be viewed\");\n\n // disable if still new\n } else if (state === STATES.NEW) {\n displayBtnData.disabled = true;\n displayBtnData.title = _l(\"This dataset is not yet viewable\");\n } else {\n displayBtnData.title = _l(\"View data\");\n\n // default link for dataset\n displayBtnData.href = this.model.urls.display;\n\n // add frame manager option onclick event\n var self = this;\n displayBtnData.onclick = ev => {\n if (Galaxy.frame && Galaxy.frame.active) {\n // Add dataset to frames.\n Galaxy.frame.addDataset(self.model.get(\"id\"));\n ev.preventDefault();\n }\n };\n }\n displayBtnData.faIcon = \"fa-eye\";\n return faIconButton(displayBtnData);\n },\n\n // ......................................................................... rendering details\n /** Render the enclosing div of the hda body and, if expanded, the html in the body\n * @returns {jQuery} rendered DOM\n */\n _renderDetails: function() {\n //TODO: generalize to be allow different details for each state\n\n // no access - render nothing but a message\n if (this.model.get(\"state\") === STATES.NOT_VIEWABLE) {\n return $(this.templates.noAccess(this.model.toJSON(), this));\n }\n\n var $details = _super.prototype._renderDetails.call(this);\n $details\n .find(\".actions .left\")\n .empty()\n .append(this._renderSecondaryActions());\n $details\n .find(\".summary\")\n .html(this._renderSummary())\n .prepend(this._renderDetailMessages());\n $details.find(\".display-applications\").html(this._renderDisplayApplications());\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /** Defer to the appropo summary rendering fn based on state */\n _renderSummary: function() {\n var json = this.model.toJSON();\n var summaryRenderFn = this.templates.summaries[json.state];\n summaryRenderFn = summaryRenderFn || this.templates.summaries.unknown;\n return summaryRenderFn(json, this);\n },\n\n /** Render messages to be displayed only when the details are shown */\n _renderDetailMessages: function() {\n var view = this;\n var $warnings = $('');\n var json = view.model.toJSON();\n //TODO:! unordered (map)\n _.each(view.templates.detailMessages, templateFn => {\n $warnings.append($(templateFn(json, view)));\n });\n return $warnings;\n },\n\n /** Render the external display application links */\n _renderDisplayApplications: function() {\n if (this.model.isDeletedOrPurged()) {\n return \"\";\n }\n // render both old and new display apps using the same template\n return [\n this.templates.displayApplications(this.model.get(\"display_apps\"), this),\n this.templates.displayApplications(this.model.get(\"display_types\"), this)\n ].join(\"\");\n },\n\n // ......................................................................... secondary/details actions\n /** A series of links/buttons for less commonly used actions: re-run, info, etc. */\n _renderSecondaryActions: function() {\n this.debug(\"_renderSecondaryActions\");\n switch (this.model.get(\"state\")) {\n case STATES.NOT_VIEWABLE:\n return [];\n case STATES.OK:\n case STATES.FAILED_METADATA:\n case STATES.ERROR:\n return [this._renderDownloadButton(), this._renderShowParamsButton()];\n }\n return [this._renderShowParamsButton()];\n },\n\n /** Render icon-button to show the input and output (stdout/err) for the job that created this.\n * @returns {jQuery} rendered DOM\n */\n _renderShowParamsButton: function() {\n // gen. safe to show in all cases\n return faIconButton({\n title: _l(\"View details\"),\n classes: \"params-btn\",\n href: this.model.urls.show_params,\n target: this.linkTarget,\n faIcon: \"fa-info-circle\",\n onclick: function(ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Dataset details\",\n url: this.href\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n }\n });\n },\n\n /** Render icon-button/popupmenu to download the data (and/or the associated meta files (bai, etc.)) for this.\n * @returns {jQuery} rendered DOM\n */\n _renderDownloadButton: function() {\n // don't show anything if the data's been purged\n if (this.model.get(\"purged\") || !this.model.hasData()) {\n return null;\n }\n\n // return either: a popupmenu with links to download assoc. meta files (if there are meta files)\n // or a single download icon-button (if there are no meta files)\n if (!_.isEmpty(this.model.get(\"meta_files\"))) {\n return this._renderMetaFileDownloadButton();\n }\n\n return $(\n [\n '`,\n '',\n \"\"\n ].join(\"\")\n );\n },\n\n /** Render the download button which opens a dropdown with links to download assoc. meta files (indeces, etc.) */\n _renderMetaFileDownloadButton: function() {\n var urls = this.model.urls;\n return $(\n [\n '
'],\n \"dataset\"\n );\n\n // messages to be displayed only within the details section ('below the fold')\n var detailMessageTemplates = {\n resubmitted: BASE_MVC.wrapTemplate([\n // deleted not purged\n \"<% if( model.resubmitted ){ %>\",\n '
',\n _l(\"The job creating this dataset has been resubmitted\"),\n \"
\",\n \"<% } %>\"\n ])\n };\n\n // this is applied to both old and new style display apps\n var displayApplicationsTemplate = BASE_MVC.wrapTemplate(\n [\n \"<% _.each( apps, function( app ){ %>\",\n '
\"\n ],\n \"collection\"\n );\n\n // use element identifier\n var subtitleTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n '<% var countText = collection.element_count? ( collection.element_count + \" \" ) : \"\"; %>',\n '<% if( collection.collection_type === \"list\" ){ %>',\n _l(\"a list of <%- countText %>datasets\"),\n '<% } else if( collection.collection_type === \"paired\" ){ %>',\n _l(\"a pair of datasets\"),\n '<% } else if( collection.collection_type === \"list:paired\" ){ %>',\n _l(\"a list of <%- countText %>dataset pairs\"),\n '<% } else if( collection.collection_type === \"list:list\" ){ %>',\n _l(\"a list of <%- countText %>dataset lists\"),\n \"<% } %>\",\n \"
\"\n ],\n \"collection\"\n );\n\n return _.extend({}, FoldoutListItemView.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate,\n subtitle: subtitleTemplate\n });\n})();\n\n//==============================================================================\n/** @class Read only view for DatasetCollectionElement.\n */\nvar DCEListItemView = ListItemView.extend(\n /** @lends DCEListItemView.prototype */ {\n /** add the DCE class to the list item */\n className: `${ListItemView.prototype.className} dataset-collection-element`,\n\n /** set up */\n initialize: function(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DCEListItemView.initialize:\", attributes);\n ListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DCEListItemView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDCEListItemView.prototype.templates = (() => {\n // use the element identifier here - since that will persist and the user will need it\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n '
',\n '<%- element.element_identifier %>',\n \"
\",\n '',\n \"
\"\n ],\n \"element\"\n );\n\n return _.extend({}, ListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation\n * (a dataset contained in a dataset collection).\n */\nvar DatasetDCEListItemView = DATASET_LI.DatasetListItemView.extend(\n /** @lends DatasetDCEListItemView.prototype */ {\n className: `${DATASET_LI.DatasetListItemView.prototype.className} dataset-collection-element`,\n\n /** set up */\n initialize: function(attributes) {\n if (attributes.logger) {\n this.logger = this.model.logger = attributes.logger;\n }\n this.log(\"DatasetDCEListItemView.initialize:\", attributes);\n DATASET_LI.DatasetListItemView.prototype.initialize.call(this, attributes);\n },\n\n /** In this override, only get details if in the ready state.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DatasetDCEListItemView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetDCEListItemView.prototype.templates = (() => {\n // use the element identifier here and not the dataset name\n //TODO:?? can we steal the DCE titlebar?\n var titleBarTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n '',\n '
',\n '<%- element.element_identifier %>',\n \"
\",\n \"
\"\n ],\n \"element\"\n );\n\n return _.extend({}, DATASET_LI.DatasetListItemView.prototype.templates, {\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection\n * (a nested DC).\n */\nvar NestedDCDCEListItemView = DCListItemView.extend(\n /** @lends NestedDCDCEListItemView.prototype */ {\n className: `${DCListItemView.prototype.className} dataset-collection-element`,\n\n /** In this override, add the state as a class for use with state-based CSS */\n _swapNewRender: function($newRender) {\n DCListItemView.prototype._swapNewRender.call(this, $newRender);\n var state = this.model.get(\"state\") || \"ok\";\n this.$el.addClass(`state-${state}`);\n return this.$el;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `NestedDCDCEListItemView(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n DCListItemView: DCListItemView,\n DCEListItemView: DCEListItemView,\n DatasetDCEListItemView: DatasetDCEListItemView,\n NestedDCDCEListItemView: NestedDCDCEListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-li.js","/** Generic form view */\nimport Form from \"mvc/form/form-view\";\nimport Ui from \"mvc/ui/ui-misc\";\nvar View = Backbone.View.extend({\n initialize: function(options) {\n this.model = new Backbone.Model(options);\n this.url = this.model.get(\"url\");\n this.redirect = this.model.get(\"redirect\");\n this.setElement(\"\");\n this.render();\n },\n\n render: function() {\n var self = this;\n $.ajax({\n url: Galaxy.root + this.url,\n type: \"GET\"\n })\n .done(response => {\n var options = $.extend({}, self.model.attributes, response);\n var form = new Form({\n title: options.title,\n message: options.message,\n status: options.status || \"warning\",\n icon: options.icon,\n inputs: options.inputs,\n buttons: {\n submit: new Ui.Button({\n tooltip: options.submit_tooltip,\n title: options.submit_title || \"Save\",\n icon: options.submit_icon || \"fa-save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function() {\n self._submit(form);\n }\n })\n }\n });\n self.$el.empty().append(form.$el);\n })\n .fail(response => {\n self.$el.empty().append(\n new Ui.Message({\n message: `Failed to load resource ${self.url}.`,\n status: \"danger\",\n persistent: true\n }).$el\n );\n });\n },\n\n _submit: function(form) {\n var self = this;\n $.ajax({\n url: Galaxy.root + self.url,\n data: JSON.stringify(form.data.create()),\n type: \"PUT\",\n contentType: \"application/json\"\n })\n .done(response => {\n var success_message = {\n message: response.message,\n status: \"success\",\n persistent: false\n };\n if (self.redirect) {\n window.location = `${Galaxy.root + self.redirect}?${$.param(success_message)}`;\n } else {\n form.data.matchModel(response, (input, input_id) => {\n form.field_list[input_id].value(input.value);\n });\n self._showMessage(form, success_message);\n }\n })\n .fail(response => {\n self._showMessage(form, {\n message: response.responseJSON.err_msg,\n status: \"danger\",\n persistent: false\n });\n });\n },\n\n _showMessage: function(form, options) {\n var $panel = form.$el\n .parents()\n .filter(function() {\n return [\"auto\", \"scroll\"].indexOf($(this).css(\"overflow\")) != -1;\n })\n .first();\n $panel.animate({ scrollTop: 0 }, 500);\n form.message.update(options);\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/form/form-wrapper.js","import STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"dataset\";\n//==============================================================================\nvar searchableMixin = BASE_MVC.SearchableModelMixin;\n/** @class base model for any DatasetAssociation (HDAs, LDDAs, DatasetCollectionDAs).\n * No knowledge of what type (HDA/LDDA/DCDA) should be needed here.\n * The DA's are made searchable (by attribute) by mixing in SearchableModelMixin.\n */\nvar DatasetAssociation = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(\n BASE_MVC.mixin(\n searchableMixin,\n /** @lends DatasetAssociation.prototype */ {\n _logNamespace: logNamespace,\n\n /** default attributes for a model */\n defaults: {\n state: STATES.NEW,\n deleted: false,\n purged: false,\n name: \"(unnamed dataset)\",\n accessible: true,\n // sniffed datatype (sam, tabular, bed, etc.)\n data_type: \"\",\n file_ext: \"\",\n file_size: 0,\n\n // array of associated file types (eg. [ 'bam_index', ... ])\n meta_files: [],\n\n misc_blurb: \"\",\n misc_info: \"\",\n\n tags: []\n // do NOT default on annotation, as this default is valid and will be passed on 'save'\n // which is incorrect behavior when the model is only partially fetched (annos are not passed in summary data)\n //annotation : ''\n },\n\n /** instance vars and listeners */\n initialize: function(attributes, options) {\n this.debug(`${this}(Dataset).initialize`, attributes, options);\n\n //!! this state is not in trans.app.model.Dataset.states - set it here -\n if (!this.get(\"accessible\")) {\n this.set(\"state\", STATES.NOT_VIEWABLE);\n }\n\n /** Datasets rely/use some web controllers - have the model generate those URLs on startup */\n this.urls = this._generateUrls();\n\n this._setUpListeners();\n },\n\n /** returns misc. web urls for rendering things like re-run, display, etc. */\n _generateUrls: function() {\n var id = this.get(\"id\");\n if (!id) {\n return {};\n }\n var urls = {\n purge: `datasets/${id}/purge_async`,\n display: `datasets/${id}/display/?preview=True`,\n edit: `datasets/edit?dataset_id=${id}`,\n download: `datasets/${id}/display${this._downloadQueryParameters()}`,\n report_error: `dataset/errors?id=${id}`,\n rerun: `tool_runner/rerun?id=${id}`,\n show_params: `datasets/${id}/show_params`,\n visualization: \"visualization\",\n meta_download: `dataset/get_metadata_file?hda_id=${id}&metadata_name=`\n };\n _.each(urls, (value, key) => {\n urls[key] = Galaxy.root + value;\n });\n this.urls = urls;\n return urls;\n },\n\n _downloadQueryParameters: function() {\n return `?to_ext=${this.get(\"file_ext\")}`;\n },\n\n /** set up any event listeners\n * event: state:ready fired when this DA moves into/is already in a ready state\n */\n _setUpListeners: function() {\n // if the state has changed and the new state is a ready state, fire an event\n this.on(\"change:state\", function(currModel, newState) {\n this.log(`${this} has changed state:`, currModel, newState);\n if (this.inReadyState()) {\n this.trigger(\"state:ready\", currModel, newState, this.previous(\"state\"));\n }\n });\n // the download url (currently) relies on having a correct file extension\n this.on(\"change:id change:file_ext\", function(currModel) {\n this._generateUrls();\n });\n },\n\n // ........................................................................ common queries\n /** override to add urls */\n toJSON: function() {\n var json = Backbone.Model.prototype.toJSON.call(this);\n //console.warn( 'returning json?' );\n //return json;\n return _.extend(json, {\n urls: this.urls\n });\n },\n\n /** Is this dataset deleted or purged? */\n isDeletedOrPurged: function() {\n return this.get(\"deleted\") || this.get(\"purged\");\n },\n\n /** Is this dataset in a 'ready' state; where 'Ready' states are states where no\n * processing (for the ds) is left to do on the server.\n */\n inReadyState: function() {\n var ready = _.contains(STATES.READY_STATES, this.get(\"state\"));\n return this.isDeletedOrPurged() || ready;\n },\n\n /** Does this model already contain detailed data (as opposed to just summary level data)? */\n hasDetails: function() {\n // if it's inaccessible assume it has everything it needs\n if (!this.get(\"accessible\")) {\n return true;\n }\n return this.has(\"annotation\");\n },\n\n /** Convenience function to match dataset.has_data. */\n hasData: function() {\n return this.get(\"file_size\") > 0;\n },\n\n // ........................................................................ ajax\n fetch: function(options) {\n var dataset = this;\n return Backbone.Model.prototype.fetch.call(this, options).always(() => {\n dataset._generateUrls();\n });\n },\n\n /** override to use actual Dates objects for create/update times */\n parse: function(response, options) {\n var parsed = Backbone.Model.prototype.parse.call(this, response, options);\n if (parsed.create_time) {\n parsed.create_time = new Date(parsed.create_time);\n }\n if (parsed.update_time) {\n parsed.update_time = new Date(parsed.update_time);\n }\n return parsed;\n },\n\n /** override to wait by default */\n save: function(attrs, options) {\n options = options || {};\n options.wait = _.isUndefined(options.wait) ? true : options.wait;\n return Backbone.Model.prototype.save.call(this, attrs, options);\n },\n\n //NOTE: subclasses of DA's will need to implement url and urlRoot in order to have these work properly\n /** save this dataset, _Mark_ing it as deleted (just a flag) */\n delete: function(options) {\n if (this.get(\"deleted\")) {\n return jQuery.when();\n }\n return this.save({ deleted: true }, options);\n },\n /** save this dataset, _Mark_ing it as undeleted */\n undelete: function(options) {\n if (!this.get(\"deleted\") || this.get(\"purged\")) {\n return jQuery.when();\n }\n return this.save({ deleted: false }, options);\n },\n\n /** remove the file behind this dataset from the filesystem (if permitted) */\n purge: function _purge(options) {\n //TODO: use, override model.destroy, HDA.delete({ purge: true })\n if (this.get(\"purged\")) {\n return jQuery.when();\n }\n options = options || {};\n options.url = this.urls.purge;\n\n //TODO: ideally this would be a DELETE call to the api\n // using purge async for now\n var hda = this;\n\n var xhr = jQuery.ajax(options);\n xhr.done((message, status, responseObj) => {\n hda.set({ deleted: true, purged: true });\n });\n xhr.fail((xhr, status, message) => {\n // Exception messages are hidden within error page including: '...not allowed in this Galaxy instance.'\n // unbury and re-add to xhr\n var error = _l(\"Unable to purge dataset\");\n var messageBuriedInUnfortunatelyFormattedError =\n \"Removal of datasets by users \" + \"is not allowed in this Galaxy instance\";\n if (xhr.responseJSON && xhr.responseJSON.error) {\n error = xhr.responseJSON.error;\n } else if (xhr.responseText.indexOf(messageBuriedInUnfortunatelyFormattedError) !== -1) {\n error = messageBuriedInUnfortunatelyFormattedError;\n }\n xhr.responseText = error;\n hda.trigger(\"error\", hda, xhr, options, _l(error), {\n error: error\n });\n });\n return xhr;\n },\n\n // ........................................................................ searching\n /** what attributes of an HDA will be used in a text search */\n searchAttributes: [\"name\", \"file_ext\", \"genome_build\", \"misc_blurb\", \"misc_info\", \"annotation\", \"tags\"],\n\n /** our attr keys don't often match the labels we display to the user - so, when using\n * attribute specifiers ('name=\"bler\"') in a term, allow passing in aliases for the\n * following attr keys.\n */\n searchAliases: {\n title: \"name\",\n format: \"file_ext\",\n database: \"genome_build\",\n blurb: \"misc_blurb\",\n description: \"misc_blurb\",\n info: \"misc_info\",\n tag: \"tags\"\n },\n\n // ........................................................................ misc\n /** String representation */\n toString: function() {\n var nameAndId = this.get(\"id\") || \"\";\n if (this.get(\"name\")) {\n nameAndId = `\"${this.get(\"name\")}\",${nameAndId}`;\n }\n return `Dataset(${nameAndId})`;\n }\n }\n )\n);\n\n//==============================================================================\n/** @class Backbone collection for dataset associations.\n */\nvar DatasetAssociationCollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends HistoryContents.prototype */ {\n _logNamespace: logNamespace,\n\n model: DatasetAssociation,\n\n /** root api url */\n urlRoot: `${Galaxy.root}api/datasets`,\n\n /** url fn */\n url: function() {\n return this.urlRoot;\n },\n\n // ........................................................................ common queries\n /** Get the ids of every item in this collection\n * @returns array of encoded ids\n */\n ids: function() {\n return this.map(item => item.get(\"id\"));\n },\n\n /** Get contents that are not ready\n * @returns array of content models\n */\n notReady: function() {\n return this.filter(content => !content.inReadyState());\n },\n\n /** return true if any datasets don't have details */\n haveDetails: function() {\n return this.all(dataset => dataset.hasDetails());\n },\n\n // ........................................................................ ajax\n /** using a queue, perform ajaxFn on each of the models in this collection */\n ajaxQueue: function(ajaxFn, options) {\n var deferred = jQuery.Deferred();\n var startingLength = this.length;\n var responses = [];\n\n if (!startingLength) {\n deferred.resolve([]);\n return deferred;\n }\n\n // use reverse order (stylistic choice)\n var ajaxFns = this.chain()\n .reverse()\n .map((dataset, i) => () => {\n var xhr = ajaxFn.call(dataset, options);\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(response => {\n deferred.notify({\n curr: i,\n total: startingLength,\n response: response,\n model: dataset\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(response => {\n responses.push(response);\n if (ajaxFns.length) {\n ajaxFns.shift()();\n } else {\n deferred.resolve(responses);\n }\n });\n })\n .value();\n // start the queue\n ajaxFns.shift()();\n\n return deferred;\n },\n\n // ........................................................................ sorting/filtering\n /** return a new collection of datasets whose attributes contain the substring matchesWhat */\n matches: function(matchesWhat) {\n return this.filter(dataset => dataset.matches(matchesWhat));\n },\n\n /** String representation. */\n toString: function() {\n return [\"DatasetAssociationCollection(\", this.length, \")\"].join(\"\");\n }\n }\n);\n\n//==============================================================================\nexport default {\n DatasetAssociation: DatasetAssociation,\n DatasetAssociationCollection: DatasetAssociationCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/dataset-model.js","import STATES from \"mvc/dataset/states\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/** @class Mixin for HistoryContents content (HDAs, HDCAs).\n */\nvar HistoryContentMixin = {\n /** default attributes for a model */\n defaults: {\n /** parent (containing) history */\n history_id: null,\n /** some content_type (HistoryContents can contain mixed model classes) */\n history_content_type: null,\n /** indicating when/what order the content was generated in the context of the history */\n hid: null,\n /** whether the user wants the content shown (visible) */\n visible: true\n },\n\n // ........................................................................ mixed content element\n // In order to be part of a MIXED bbone collection, we can't rely on the id\n // (which may collide btwn models of different classes)\n // Instead, use type_id which prefixes the history_content_type so the bbone collection can differentiate\n idAttribute: \"type_id\",\n\n // ........................................................................ common queries\n /** the more common alias of visible */\n hidden: function() {\n return !this.get(\"visible\");\n },\n\n //TODO: remove\n /** based on includeDeleted, includeHidden (gen. from the container control),\n * would this ds show in the list of ds's?\n * @param {Boolean} includeDeleted are we showing deleted hdas?\n * @param {Boolean} includeHidden are we showing hidden hdas?\n */\n isVisible: function(includeDeleted, includeHidden) {\n var isVisible = true;\n if (!includeDeleted && (this.get(\"deleted\") || this.get(\"purged\"))) {\n isVisible = false;\n }\n if (!includeHidden && !this.get(\"visible\")) {\n isVisible = false;\n }\n return isVisible;\n },\n\n // ........................................................................ ajax\n //TODO?: these are probably better done on the leaf classes\n /** history content goes through the 'api/histories' API */\n urlRoot: `${Galaxy.root}api/histories/`,\n\n /** full url spec. for this content */\n url: function() {\n var historyContentType = this.get(\"history_content_type\");\n var historyId = this.get(\"history_id\");\n var historyContentId = this.get(\"id\");\n var url = `${this.urlRoot}{this.get(\"historyId\")}/contents/${historyContentType}s/${historyContentId}`;\n return url;\n },\n\n /** save this content as not visible */\n hide: function(options) {\n if (!this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: false }, options);\n },\n /** save this content as visible */\n unhide: function(options) {\n if (this.get(\"visible\")) {\n return jQuery.when();\n }\n return this.save({ visible: true }, options);\n },\n\n // ........................................................................ misc\n toString: function() {\n return [this.get(\"type_id\"), this.get(\"hid\"), this.get(\"name\")].join(\":\");\n }\n};\n\n//==============================================================================\nexport default {\n HistoryContentMixin: HistoryContentMixin\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-content-model.js","/* For presentation-related functionality shared across collection creators.\n Particularily overlapping functionality related to name processing and help.\n*/\nvar CollectionCreatorMixin = {\n /** add (or clear if clear is truthy) a validation warning to the DOM element described in what */\n _validationWarning: function(what, clear) {\n var VALIDATION_CLASS = \"validation-warning\";\n if (what === \"name\") {\n what = this.$(\".collection-name\").add(this.$(\".collection-name-prompt\"));\n this.$(\".collection-name\")\n .focus()\n .select();\n }\n if (clear) {\n what = what || this.$(`.${VALIDATION_CLASS}`);\n what.removeClass(VALIDATION_CLASS);\n } else {\n what.addClass(VALIDATION_CLASS);\n }\n },\n\n _changeHideOriginals: function(ev) {\n this.hideOriginals = this.$(\".hide-originals\").prop(\"checked\");\n },\n\n // ........................................................................ footer\n /** handle a collection name change */\n _changeName: function(ev) {\n this._validationWarning(\"name\", !!this._getName());\n },\n\n /** check for enter key press when in the collection name and submit */\n _nameCheckForEnter: function(ev) {\n if (ev.keyCode === 13 && !this.blocking) {\n this._clickCreate();\n }\n },\n\n /** get the current collection name */\n _getName: function() {\n return _.escape(this.$(\".collection-name\").val());\n },\n\n // ........................................................................ header\n /** expand help */\n _clickMoreHelp: function(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").addClass(\"expanded\");\n this.$(\".more-help\").hide();\n },\n /** collapse help */\n _clickLessHelp: function(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").removeClass(\"expanded\");\n this.$(\".more-help\").show();\n },\n /** toggle help */\n _toggleHelp: function(ev) {\n ev.stopPropagation();\n this.$(\".main-help\").toggleClass(\"expanded\");\n this.$(\".more-help\").toggle();\n },\n\n /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */\n _showAlert: function(message, alertClass) {\n alertClass = alertClass || \"alert-danger\";\n this.$(\".main-help\").hide();\n this.$(\".header .alert\")\n .attr(\"class\", \"alert alert-dismissable\")\n .addClass(alertClass)\n .show()\n .find(\".alert-message\")\n .html(message);\n },\n /** hide the alerts at the top */\n _hideAlert: function(message) {\n this.$(\".main-help\").show();\n this.$(\".header .alert\").hide();\n },\n\n _cancelCreate: function(ev) {\n if (typeof this.oncancel === \"function\") {\n this.oncancel.call(this);\n }\n },\n\n /** attempt to create the current collection */\n _clickCreate: function(ev) {\n var name = this._getName();\n if (!name) {\n this._validationWarning(\"name\");\n } else if (!this.blocking) {\n this.createList(name);\n }\n },\n\n _setUpCommonSettings: function(attributes) {\n this.hideOriginals = attributes.defaultHideSourceItems || false;\n },\n\n /** render the footer, completion controls, and cancel controls */\n _renderFooter: function(speed, callback) {\n var self = this;\n var $footer = this.$(\".footer\")\n .empty()\n .html(this.templates.footer());\n _.each(this.footerSettings, (property, selector) => {\n self.$(selector).prop(\"checked\", self[property]);\n });\n if (typeof this.oncancel === \"function\") {\n this.$(\".cancel-create.btn\").show();\n }\n return $footer;\n },\n\n _creatorTemplates: {\n main: _.template(\n [\n '',\n '',\n ''\n ].join(\"\")\n )\n }\n};\n\n//==============================================================================\nexport default {\n CollectionCreatorMixin: CollectionCreatorMixin\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/base-creator.js","// Alphanumeric/natural sort fn\nfunction naturalSort(a, b) {\n // setup temp-scope variables for comparison evauluation\n var re = /(-?[0-9\\.]+)/g;\n\n var x = a.toString().toLowerCase() || \"\";\n var y = b.toString().toLowerCase() || \"\";\n var nC = String.fromCharCode(0);\n var xN = x.replace(re, `${nC}$1${nC}`).split(nC);\n var yN = y.replace(re, `${nC}$1${nC}`).split(nC);\n var xD = new Date(x).getTime();\n var yD = xD ? new Date(y).getTime() : null;\n // natural sorting of dates\n if (yD) {\n if (xD < yD) {\n return -1;\n } else if (xD > yD) {\n return 1;\n }\n }\n\n // natural sorting through split numeric strings and default strings\n var oFxNcL;\n\n var oFyNcL;\n for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {\n oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];\n oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];\n if (oFxNcL < oFyNcL) {\n return -1;\n } else if (oFxNcL > oFyNcL) {\n return 1;\n }\n }\n return 0;\n}\n\nexport default naturalSort;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/natural-sort.js","import jQuery from \"jquery\";\n(\"use_strict\");\n\nvar $ = jQuery;\n//=============================================================================\n\njQuery.fn.extend({\n hoverhighlight: function $hoverhighlight(scope, color) {\n scope = scope || \"body\";\n if (!this.length) {\n return this;\n }\n\n $(this).each(function() {\n var $this = $(this);\n var targetSelector = $this.data(\"target\");\n\n if (targetSelector) {\n $this\n .mouseover(ev => {\n $(targetSelector, scope).css({\n background: color\n });\n })\n .mouseout(ev => {\n $(targetSelector).css({\n background: \"\"\n });\n });\n }\n });\n return this;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/ui/hoverhighlight.js","/** This is the run workflow tool form view. */\nimport Utils from \"utils/utils\";\nimport Deferred from \"utils/deferred\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\nimport FormData from \"mvc/form/form-data\";\nimport ToolFormBase from \"mvc/tool/tool-form-base\";\nimport Modal from \"mvc/ui/ui-modal\";\nimport Webhooks from \"mvc/webhooks\";\nimport WorkflowIcons from \"mvc/workflow/workflow-icons\";\nvar View = Backbone.View.extend({\n initialize: function(options) {\n var self = this;\n this.modal = parent.Galaxy.modal || new Modal.View();\n this.model = (options && options.model) || new Backbone.Model(options);\n this.deferred = new Deferred();\n this.setElement(\n $(\"\")\n .addClass(\"ui-form-composite\")\n .append((this.$message = $(\"\")))\n .append((this.$header = $(\"\")))\n .append((this.$steps = $(\"\")))\n );\n $(\"body\").append(this.$el);\n this._configure();\n this.render();\n $(window).resize(() => {\n self._refresh();\n });\n },\n\n /** Refresh height of scrollable div below header, handle scrolling by lazy loading steps */\n _refresh: function(step_index) {\n var margin =\n _.reduce(this.$el.children(), (memo, child) => memo + $(child).outerHeight(), 0) -\n this.$steps.height() +\n 90;\n this.$steps.css(\"height\", $(window).height() - margin);\n },\n\n /** Configures form/step options for each workflow step */\n _configure: function() {\n var self = this;\n this.forms = [];\n this.steps = [];\n this.links = [];\n this.parms = [];\n _.each(this.model.get(\"steps\"), (step, i) => {\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", `${i} : Preparing workflow step.`);\n var icon = WorkflowIcons[step.step_type];\n var title = `${parseInt(i + 1)}: ${step.step_label || step.step_name}`;\n if (step.annotation) {\n title += ` - ${step.annotation}`;\n }\n if (step.step_version) {\n title += ` (Galaxy Version ${step.step_version})`;\n }\n step = Utils.merge(\n {\n index: i,\n fixed_title: _.escape(title),\n icon: icon || \"\",\n help: null,\n citations: null,\n collapsible: true,\n collapsed: i > 0 && !self._isDataStep(step),\n sustain_version: true,\n sustain_repeats: true,\n sustain_conditionals: true,\n narrow: true,\n text_enable: \"Edit\",\n text_disable: \"Undo\",\n cls_enable: \"fa fa-edit\",\n cls_disable: \"fa fa-undo\",\n errors: step.messages,\n initial_errors: true,\n cls: \"ui-portlet-narrow\",\n hide_operations: true,\n needs_refresh: false,\n always_refresh: step.step_type != \"tool\"\n },\n step\n );\n self.steps[i] = step;\n self.links[i] = [];\n self.parms[i] = {};\n });\n\n // build linear index of step input pairs\n _.each(this.steps, (step, i) => {\n FormData.visitInputs(step.inputs, (input, name) => {\n self.parms[i][name] = input;\n });\n });\n\n // iterate through data input modules and collect linked sub steps\n _.each(this.steps, (step, i) => {\n _.each(step.output_connections, output_connection => {\n _.each(self.steps, (sub_step, j) => {\n sub_step.step_index === output_connection.input_step_index && self.links[i].push(sub_step);\n });\n });\n });\n\n // convert all connected data inputs to hidden fields with proper labels,\n // and track the linked source step\n _.each(this.steps, (step, i) => {\n _.each(self.steps, (sub_step, j) => {\n var connections_by_name = {};\n _.each(step.output_connections, connection => {\n sub_step.step_index === connection.input_step_index &&\n (connections_by_name[connection.input_name] = connection);\n });\n _.each(self.parms[j], (input, name) => {\n var connection = connections_by_name[name];\n if (connection) {\n input.type = \"hidden\";\n input.help = input.step_linked ? `${input.help}, ` : \"\";\n input.help += `Output dataset '${connection.output_name}' from step ${parseInt(i) + 1}`;\n input.step_linked = input.step_linked || [];\n input.step_linked.push(step);\n }\n });\n });\n });\n\n // identify and configure workflow parameters\n var wp_count = 0;\n this.wp_inputs = {};\n function _handleWorkflowParameter(value, callback) {\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while ((match = re.exec(String(value)))) {\n var wp_name = match[1];\n callback(\n (self.wp_inputs[wp_name] = self.wp_inputs[wp_name] || {\n label: wp_name,\n name: wp_name,\n type: \"text\",\n color: `hsl( ${++wp_count * 100}, 70%, 30% )`,\n style: \"ui-form-wp-source\",\n links: []\n })\n );\n }\n }\n _.each(this.steps, (step, i) => {\n _.each(self.parms[i], (input, name) => {\n _handleWorkflowParameter(input.value, wp_input => {\n wp_input.links.push(step);\n input.wp_linked = true;\n input.type = \"text\";\n input.backdrop = true;\n input.style = \"ui-form-wp-target\";\n });\n });\n _.each(step.post_job_actions, pja => {\n _.each(pja.action_arguments, arg => {\n _handleWorkflowParameter(arg, () => {});\n });\n });\n });\n\n // select fields are shown for dynamic fields if all putative data inputs are available,\n // or if an explicit reference is specified as data_ref and available\n _.each(this.steps, (step, i) => {\n if (step.step_type == \"tool\") {\n var data_resolved = true;\n FormData.visitInputs(step.inputs, (input, name, context) => {\n var is_runtime_value = input.value && input.value.__class__ == \"RuntimeValue\";\n var is_data_input = [\"data\", \"data_collection\"].indexOf(input.type) != -1;\n var data_ref = context[input.data_ref];\n input.step_linked && !self._isDataStep(input.step_linked) && (data_resolved = false);\n input.options &&\n ((input.options.length == 0 && !data_resolved) || input.wp_linked) &&\n (input.is_workflow = true);\n data_ref &&\n (input.is_workflow =\n (data_ref.step_linked && !self._isDataStep(data_ref.step_linked)) || input.wp_linked);\n (is_data_input || (input.value && input.value.__class__ == \"RuntimeValue\" && !input.step_linked)) &&\n (step.collapsed = false);\n is_runtime_value && (input.value = input.default_value);\n input.flavor = \"workflow\";\n if (!is_runtime_value && !is_data_input && input.type !== \"hidden\" && !input.wp_linked) {\n if (input.optional || (!Utils.isEmpty(input.value) && input.value !== \"\")) {\n input.collapsible_value = input.value;\n input.collapsible_preview = true;\n }\n }\n });\n }\n });\n },\n\n render: function() {\n var self = this;\n this.deferred.reset();\n this._renderHeader();\n this._renderMessage();\n this._renderParameters();\n this._renderHistory();\n _.each(this.steps, step => {\n self._renderStep(step);\n });\n },\n\n /** Render header */\n _renderHeader: function() {\n var self = this;\n this.execute_btn = new Ui.Button({\n icon: \"fa-check\",\n title: \"Run workflow\",\n cls: \"btn btn-primary\",\n onclick: function() {\n self._execute();\n }\n });\n this.$header\n .addClass(\"ui-form-header\")\n .empty()\n .append(\n new Ui.Label({\n title: `Workflow: ${this.model.get(\"name\")}`\n }).$el\n )\n .append(this.execute_btn.$el);\n },\n\n /** Render message */\n _renderMessage: function() {\n this.$message.empty();\n if (this.model.get(\"has_upgrade_messages\")) {\n this.$message.append(\n new Ui.Message({\n message:\n \"Some tools in this workflow may have changed since it was last saved or some errors were found. The workflow may still run, but any new options will have default values. Please review the messages below to make a decision about whether the changes will affect your analysis.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el\n );\n }\n var step_version_changes = this.model.get(\"step_version_changes\");\n if (step_version_changes && step_version_changes.length > 0) {\n this.$message.append(\n new Ui.Message({\n message:\n \"Some tools are being executed with different versions compared to those available when this workflow was last saved because the other versions are not or no longer available on this Galaxy instance. To upgrade your workflow and dismiss this message simply edit the workflow and re-save it.\",\n status: \"warning\",\n persistent: true,\n fade: false\n }).$el\n );\n }\n },\n\n /** Render workflow parameters */\n _renderParameters: function() {\n var self = this;\n this.wp_form = null;\n if (!_.isEmpty(this.wp_inputs)) {\n this.wp_form = new Form({\n title: \"Workflow Parameters\",\n inputs: this.wp_inputs,\n cls: \"ui-portlet-narrow\",\n onchange: function() {\n _.each(self.wp_form.input_list, (input_def, i) => {\n _.each(input_def.links, step => {\n self._refreshStep(step);\n });\n });\n }\n });\n this._append(this.$steps.empty(), this.wp_form.$el);\n }\n },\n\n /** Render workflow parameters */\n _renderHistory: function() {\n this.history_form = new Form({\n cls: \"ui-portlet-narrow\",\n title: \"History Options\",\n inputs: [\n {\n type: \"conditional\",\n name: \"new_history\",\n test_param: {\n name: \"check\",\n label: \"Send results to a new history\",\n type: \"boolean\",\n value: \"false\",\n help: \"\"\n },\n cases: [\n {\n value: \"true\",\n inputs: [\n {\n name: \"name\",\n label: \"History name\",\n type: \"text\",\n value: this.model.get(\"name\")\n }\n ]\n }\n ]\n }\n ]\n });\n this._append(this.$steps, this.history_form.$el);\n },\n\n /** Render step */\n _renderStep: function(step) {\n var self = this;\n var form = null;\n this.deferred.execute(promise => {\n self.$steps.addClass(\"ui-steps\");\n if (step.step_type == \"tool\") {\n step.postchange = function(process, form) {\n var self = this;\n var current_state = {\n tool_id: step.id,\n tool_version: step.version,\n inputs: $.extend(true, {}, form.data.create())\n };\n form.wait(true);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Sending current state.\", current_state);\n Utils.request({\n type: \"POST\",\n url: `${Galaxy.root}api/tools/${step.id}/build`,\n data: current_state,\n success: function(data) {\n form.update(data);\n form.wait(false);\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Received new model.\", data);\n process.resolve();\n },\n error: function(response) {\n Galaxy.emit.debug(\"tool-form-composite::postchange()\", \"Refresh request failed.\", response);\n process.reject();\n }\n });\n };\n form = new ToolFormBase(step);\n if (step.post_job_actions && step.post_job_actions.length) {\n form.portlet.append(\n $(\"\")\n .addClass(\"ui-form-element-disabled\")\n .append(\n $(\"\")\n .addClass(\"ui-form-title\")\n .html(\"Job Post Actions\")\n )\n .append(\n $(\"\")\n .addClass(\"ui-form-preview\")\n .html(\n _.reduce(\n step.post_job_actions,\n (memo, value) => `${memo} ${value.short_str}`,\n \"\"\n )\n )\n )\n );\n }\n } else {\n var is_simple_input = [\"data_input\", \"data_collection_input\"].indexOf(step.step_type) != -1;\n _.each(step.inputs, input => {\n input.flavor = \"module\";\n input.hide_label = is_simple_input;\n });\n form = new Form(\n Utils.merge(\n {\n title: step.fixed_title,\n onchange: function() {\n _.each(self.links[step.index], link => {\n self._refreshStep(link);\n });\n },\n inputs:\n step.inputs && step.inputs.length > 0\n ? step.inputs\n : [\n {\n type: \"hidden\",\n name: \"No options available.\",\n ignore: null\n }\n ]\n },\n step\n )\n );\n }\n self.forms[step.index] = form;\n self._append(self.$steps, form.$el);\n self._refresh();\n step.needs_refresh && self._refreshStep(step);\n form.portlet[!self.show_progress ? \"enable\" : \"disable\"]();\n self.show_progress &&\n self.execute_btn.model.set({\n wait: true,\n wait_text: \"Preparing...\",\n percentage: (step.index + 1) * 100.0 / self.steps.length\n });\n Galaxy.emit.debug(\"tool-form-composite::initialize()\", `${step.index} : Workflow step state ready.`, step);\n setTimeout(() => {\n promise.resolve();\n }, 0);\n });\n },\n\n /** Refreshes step values from source step values */\n _refreshStep: function(step) {\n var self = this;\n var form = this.forms[step.index];\n if (form) {\n _.each(self.parms[step.index], (input, name) => {\n if (input.step_linked || input.wp_linked) {\n var field = form.field_list[form.data.match(name)];\n if (field) {\n var new_value = undefined;\n if (input.step_linked) {\n new_value = { values: [] };\n _.each(input.step_linked, source_step => {\n if (self._isDataStep(source_step)) {\n var value = self.forms[source_step.index].data.create().input;\n value &&\n _.each(value.values, v => {\n new_value.values.push(v);\n });\n }\n });\n if (!input.multiple && new_value.values.length > 0) {\n new_value = {\n values: [new_value.values[0]]\n };\n }\n } else if (input.wp_linked) {\n new_value = input.value;\n var re = /\\$\\{(.+?)\\}/g;\n var match;\n while ((match = re.exec(input.value))) {\n var wp_field = self.wp_form.field_list[self.wp_form.data.match(match[1])];\n var wp_value = wp_field && wp_field.value();\n if (wp_value) {\n new_value = new_value.split(match[0]).join(wp_value);\n }\n }\n }\n if (new_value !== undefined) {\n field.value(new_value);\n }\n }\n }\n });\n form.trigger(\"change\");\n } else {\n step.needs_refresh = true;\n }\n },\n\n /** Refresh the history after job submission while form is shown */\n _refreshHistory: function() {\n var self = this;\n var history = parent.Galaxy && parent.Galaxy.currHistoryPanel && parent.Galaxy.currHistoryPanel.model;\n this._refresh_history && clearTimeout(this._refresh_history);\n if (history) {\n history.refresh().success(() => {\n if (history.numOfUnfinishedShownContents() === 0) {\n self._refresh_history = setTimeout(() => {\n self._refreshHistory();\n }, history.UPDATE_DELAY);\n }\n });\n }\n },\n\n /** Build remaining steps */\n _execute: function() {\n var self = this;\n this.show_progress = true;\n this._enabled(false);\n this.deferred.execute(promise => {\n setTimeout(() => {\n promise.resolve();\n self._submit();\n }, 0);\n });\n },\n\n /** Validate and submit workflow */\n _submit: function() {\n var self = this;\n var history_form_data = this.history_form.data.create();\n var job_def = {\n new_history_name: history_form_data[\"new_history|name\"] ? history_form_data[\"new_history|name\"] : null,\n history_id: !history_form_data[\"new_history|name\"] ? this.model.get(\"history_id\") : null,\n replacement_params: this.wp_form ? this.wp_form.data.create() : {},\n parameters: {},\n // Tool form will submit flat maps for each parameter\n // (e.g. \"repeat_0|cond|param\": \"foo\" instead of nested\n // data structures).\n parameters_normalized: true,\n // Tool form always wants a list of invocations back\n // so that inputs can be batched.\n batch: true\n };\n var validated = true;\n for (var i in this.forms) {\n var form = this.forms[i];\n var job_inputs = form.data.create();\n var step = self.steps[i];\n var step_index = step.step_index;\n form.trigger(\"reset\");\n for (var job_input_id in job_inputs) {\n var input_value = job_inputs[job_input_id];\n var input_id = form.data.match(job_input_id);\n var input_field = form.field_list[input_id];\n var input_def = form.input_list[input_id];\n if (!input_def.step_linked) {\n if (this._isDataStep(step)) {\n validated = input_value && input_value.values && input_value.values.length > 0;\n } else {\n validated =\n input_def.optional ||\n (input_def.is_workflow && input_value !== \"\") ||\n (!input_def.is_workflow && input_value !== null);\n }\n if (!validated) {\n form.highlight(input_id);\n break;\n }\n job_def.parameters[step_index] = job_def.parameters[step_index] || {};\n job_def.parameters[step_index][job_input_id] = job_inputs[job_input_id];\n }\n }\n if (!validated) {\n break;\n }\n }\n if (!validated) {\n self._enabled(true);\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation failed.\", job_def);\n } else {\n Galaxy.emit.debug(\"tool-form-composite::submit()\", \"Validation complete.\", job_def);\n Utils.request({\n type: \"POST\",\n url: `${Galaxy.root}api/workflows/${this.model.id}/invocations`,\n data: job_def,\n success: function(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission successful.\", response);\n self.$el.children().hide();\n self.$el.append(self._templateSuccess(response));\n\n // Show Webhook if job is running\n if ($.isArray(response) && response.length > 0) {\n self.$el.append($(\"\", { id: \"webhook-view\" }));\n var WebhookApp = new Webhooks.WebhookView({\n urlRoot: `${Galaxy.root}api/webhooks/workflow`,\n toolId: job_def.tool_id,\n toolVersion: job_def.tool_version\n });\n }\n\n self._refreshHistory();\n },\n error: function(response) {\n Galaxy.emit.debug(\"tool-form-composite::submit\", \"Submission failed.\", response);\n var input_found = false;\n if (response && response.err_data) {\n for (var i in self.forms) {\n var form = self.forms[i];\n var step_related_errors = response.err_data[form.model.get(\"step_index\")];\n if (step_related_errors) {\n var error_messages = form.data.matchResponse(step_related_errors);\n for (var input_id in error_messages) {\n form.highlight(input_id, error_messages[input_id]);\n input_found = true;\n break;\n }\n }\n }\n }\n if (!input_found) {\n self.modal.show({\n title: \"Workflow submission failed\",\n body: self._templateError(job_def, response && response.err_msg),\n buttons: {\n Close: function() {\n self.modal.hide();\n }\n }\n });\n }\n },\n complete: function() {\n self._enabled(true);\n }\n });\n }\n },\n\n /** Append new dom to body */\n _append: function($container, $el) {\n $container.append(\"\").append($el);\n },\n\n /** Set enabled/disabled state */\n _enabled: function(enabled) {\n this.execute_btn.model.set({\n wait: !enabled,\n wait_text: \"Sending...\",\n percentage: -1\n });\n this.wp_form && this.wp_form.portlet[enabled ? \"enable\" : \"disable\"]();\n this.history_form && this.history_form.portlet[enabled ? \"enable\" : \"disable\"]();\n _.each(this.forms, form => {\n form && form.portlet[enabled ? \"enable\" : \"disable\"]();\n });\n },\n\n /** Is data input module/step */\n _isDataStep: function(steps) {\n var lst = $.isArray(steps) ? steps : [steps];\n for (var i = 0; i < lst.length; i++) {\n var step = lst[i];\n if (!step || !step.step_type || !step.step_type.startsWith(\"data\")) {\n return false;\n }\n }\n return true;\n },\n\n /** Templates */\n _templateSuccess: function(response) {\n if ($.isArray(response) && response.length > 0) {\n return $(\"\")\n .addClass(\"donemessagelarge\")\n .append(\n $(\"\").html(\n `Successfully invoked workflow ${Utils.sanitize(this.model.get(\"name\"))}${\n response.length > 1 ? ` ${response.length} times` : \"\"\n }.`\n )\n )\n .append(\n $(\"\")\n .append(\"\")\n .text(\n \"You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from 'running' to 'finished' if completed successfully or 'error' if problems were encountered.\"\n )\n );\n } else {\n return this._templateError(response, \"Invalid success response. No invocations found.\");\n }\n },\n\n _templateError: function(response, err_msg) {\n return $(\"\")\n .addClass(\"errormessagelarge\")\n .append(\n $(\"\").text(\n `The server could not complete the request. Please contact the Galaxy Team if this error persists. ${JSON.stringify(\n err_msg\n ) || \"\"}`\n )\n )\n .append($(\"\").text(JSON.stringify(response, null, 4)));\n }\n});\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/tool/tool-form-composite.js","import MODAL from \"mvc/ui/ui-modal\";\nimport ERROR_MODAL from \"mvc/ui/error-modal\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\n/**\n * A dialog/modal that allows copying a user history or 'importing' from user\n * another. Generally called via historyCopyDialog below.\n * @type {Object}\n */\nvar CopyDialog = {\n // language related strings/fns\n defaultName: _.template(\"Copy of '<%- name %>'\"),\n title: _.template(`${_l(\"Copying history\")} \"<%- name %>\"`),\n submitLabel: _l(\"Copy\"),\n errorMessage: _l(\"History could not be copied.\"),\n progressive: _l(\"Copying history\"),\n activeLabel: _l(\"Copy only the active, non-deleted datasets\"),\n allLabel: _l(\"Copy all datasets including deleted ones\"),\n anonWarning:\n _l(\"As an anonymous user, unless you login or register, you will lose your current history \") +\n _l(\"after copying this history. \"),\n\n // template for modal body\n _template: _.template(\n [\n //TODO: remove inline styles\n // show a warning message for losing current to anon users\n \"<% if( isAnon ){ %>\",\n '
\",\n \"<% } %>\",\n \"\"\n ].join(\"\")\n ),\n\n // empty modal body and let the user know the copy is happening\n _showAjaxIndicator: function _showAjaxIndicator() {\n var indicator = `
${this.progressive}...
`;\n this.modal\n .$(\".modal-body\")\n .empty()\n .append(indicator)\n .css({ \"margin-top\": \"8px\" });\n },\n\n // (sorta) public interface - display the modal, render the form, and potentially copy the history\n // returns a jQuery.Deferred done->history copied, fail->user cancelled\n dialog: function _dialog(modal, history, options) {\n options = options || {};\n\n var dialog = this;\n var deferred = jQuery.Deferred();\n\n var // TODO: getting a little byzantine here\n defaultCopyNameFn = options.nameFn || this.defaultName;\n\n var defaultCopyName = defaultCopyNameFn({\n name: history.get(\"name\")\n });\n\n var // TODO: these two might be simpler as one 3 state option (all,active,no-choice)\n defaultCopyWhat = options.allDatasets ? \"copy-all\" : \"copy-non-deleted\";\n\n var allowAll = !_.isUndefined(options.allowAll) ? options.allowAll : true;\n\n var autoClose = !_.isUndefined(options.autoClose) ? options.autoClose : true;\n\n this.modal = modal;\n\n // validate the name and copy if good\n function checkNameAndCopy() {\n var name = modal.$(\"#copy-modal-title\").val();\n if (!name) {\n modal.$(\".invalid-title\").show();\n return;\n }\n // get further settings, shut down and indicate the ajax call, then hide and resolve/reject\n var copyAllDatasets = modal.$('input[name=\"copy-what\"]:checked').val() === \"copy-all\";\n modal.$(\"button\").prop(\"disabled\", true);\n dialog._showAjaxIndicator();\n history\n .copy(true, name, copyAllDatasets)\n .done(response => {\n deferred.resolve(response);\n })\n .fail(function(xhr, status, message) {\n var options = {\n name: name,\n copyAllDatasets: copyAllDatasets\n };\n ERROR_MODAL.ajaxErrorModal(history, xhr, options, dialog.errorMessage);\n deferred.rejectWith(deferred, arguments);\n })\n .done(() => {\n if (autoClose) {\n modal.hide();\n }\n });\n }\n\n var originalClosingCallback = options.closing_callback;\n modal.show(\n _.extend(options, {\n title: this.title({ name: history.get(\"name\") }),\n body: $(\n dialog._template({\n name: defaultCopyName,\n isAnon: Galaxy.user.isAnonymous(),\n allowAll: allowAll,\n copyWhat: defaultCopyWhat,\n activeLabel: this.activeLabel,\n allLabel: this.allLabel,\n anonWarning: this.anonWarning\n })\n ),\n buttons: _.object([\n [\n _l(\"Cancel\"),\n () => {\n modal.hide();\n }\n ],\n [this.submitLabel, checkNameAndCopy]\n ]),\n height: \"auto\",\n closing_events: true,\n closing_callback: function _historyCopyClose(cancelled) {\n if (cancelled) {\n deferred.reject({ cancelled: true });\n }\n if (originalClosingCallback) {\n originalClosingCallback(cancelled);\n }\n }\n })\n );\n\n // set the default dataset copy, autofocus the title, and set up for a simple return\n modal\n .$(\"#copy-modal-title\")\n .focus()\n .select();\n modal.$(\"#copy-modal-title\").on(\"keydown\", ev => {\n if (ev.keyCode === 13) {\n ev.preventDefault();\n checkNameAndCopy();\n }\n });\n\n return deferred;\n }\n};\n\n//==============================================================================\n// maintain the (slight) distinction between copy and import\n/**\n * Subclass CopyDialog to use the import language.\n */\nvar ImportDialog = _.extend({}, CopyDialog, {\n defaultName: _.template(\"imported: <%- name %>\"),\n title: _.template(`${_l(\"Importing history\")} \"<%- name %>\"`),\n submitLabel: _l(\"Import\"),\n errorMessage: _l(\"History could not be imported.\"),\n progressive: _l(\"Importing history\"),\n activeLabel: _l(\"Import only the active, non-deleted datasets\"),\n allLabel: _l(\"Import all datasets including deleted ones\"),\n anonWarning:\n _l(\"As an anonymous user, unless you login or register, you will lose your current history \") +\n _l(\"after importing this history. \")\n});\n\n//==============================================================================\n/**\n * Main interface for both history import and history copy dialogs.\n * @param {Backbone.Model} history the history to copy\n * @param {Object} options a hash\n * @return {jQuery.Deferred} promise that fails on close and succeeds on copy\n *\n * options:\n * (this object is also passed to the modal used to display the dialog and accepts modal options)\n * {Function} nameFn if defined, use this to build the default name shown to the user\n * (the fn is passed: {name: })\n * {bool} useImport if true, use the 'import' language (instead of Copy)\n * {bool} allowAll if true, allow the user to choose between copying all datasets and\n * only non-deleted datasets\n * {String} allDatasets default initial checked radio button: 'copy-all' or 'copy-non-deleted',\n */\nvar historyCopyDialog = (history, options) => {\n options = options || {};\n // create our own modal if Galaxy doesn't have one (mako tab without use_panels)\n var modal = window.parent.Galaxy.modal || new MODAL.View({});\n return options.useImport\n ? ImportDialog.dialog(modal, history, options)\n : CopyDialog.dialog(modal, history, options);\n};\n\n//==============================================================================\nexport default historyCopyDialog;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/copy-dialog.js","import _l from \"utils/localization\";\n\n//TODO: toastr is another possibility - I didn't see where I might add details, tho\n\n/* ============================================================================\nError modals meant to replace the o-so-easy alerts.\n\nThese are currently styled as errormessages but use the Galaxy.modal\ninfrastructure to be shown/closed. They're capable of showing details in a\ntogglable dropdown and the details are formatted in a pre.\n\nExample:\n errorModal( 'Heres a message', 'A Title', { some_details: 'here' });\n errorModal( 'Heres a message' ); // no details, title is 'Error'\n\nThere are three specialized forms:\n offlineErrorModal a canned response for when there's no connection\n badGatewayErrorModal canned response for when Galaxy is restarting\n ajaxErrorModal plugable into any Backbone class as an\n error event handler by accepting the error args: model, xhr, options\n\nExamples:\n if( navigator.offLine ){ offlineErrorModal(); }\n if( xhr.status === 502 ){ badGatewayErrorModal(); }\n this.listenTo( this.model, 'error', ajaxErrorModal );\n\n============================================================================ */\n\nvar CONTACT_MSG = _l(\"Please contact a Galaxy administrator if the problem persists.\");\nvar DEFAULT_AJAX_ERR_MSG = _l(\"An error occurred while updating information with the server.\");\nvar DETAILS_MSG = _l(\"The following information can assist the developers in finding the source of the error:\");\n\n/** private helper that builds the modal and handles adding details */\nfunction _errorModal(message, title, details) {\n // create and return the modal, adding details button only if needed\n Galaxy.modal.show({\n title: title,\n body: message,\n closing_events: true,\n buttons: {\n Ok: function() {\n Galaxy.modal.hide();\n }\n }\n });\n Galaxy.modal.$el.addClass(\"error-modal\");\n\n if (details) {\n Galaxy.modal\n .$(\".error-details\")\n .add(Galaxy.modal.$('button:contains(\"Details\")'))\n .remove();\n $(\"\")\n .addClass(\"error-details\")\n .hide()\n .appendTo(Galaxy.modal.$(\".modal-content\"))\n .append([$(\"\").text(DETAILS_MSG), $(\"\").text(JSON.stringify(details, null, \" \"))]);\n\n $(``)\n .appendTo(Galaxy.modal.$(\".buttons\"))\n .click(() => {\n Galaxy.modal.$(\".error-details\").toggle();\n });\n }\n return Galaxy.modal;\n}\n\n/** Display a modal showing an error message but fallback to alert if there's no modal */\nfunction errorModal(message, title, details) {\n if (!message) {\n return;\n }\n\n message = _l(message);\n title = _l(title) || _l(\"Error:\");\n if (window.Galaxy && Galaxy.modal) {\n return _errorModal(message, title, details);\n }\n\n alert(`${title}\\n\\n${message}`);\n console.log(\"error details:\", JSON.stringify(details));\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal when the user may be offline */\nfunction offlineErrorModal() {\n return errorModal(_l(\"You appear to be offline. Please check your connection and try again.\"), _l(\"Offline?\"));\n}\n\n// ----------------------------------------------------------------------------\n/** 502 messages that should be displayed when galaxy is restarting */\nfunction badGatewayErrorModal() {\n return errorModal(\n `${_l(\"Galaxy is currently unreachable. Please try again in a few minutes.\")} ${CONTACT_MSG}`,\n _l(\"Cannot connect to Galaxy\")\n );\n}\n\n// ----------------------------------------------------------------------------\n/** display a modal (with details) about a failed Backbone ajax operation */\nfunction ajaxErrorModal(model, xhr, options, message, title) {\n message = message || DEFAULT_AJAX_ERR_MSG;\n message += ` ${CONTACT_MSG}`;\n title = title || _l(\"An error occurred\");\n var details = _ajaxDetails(model, xhr, options);\n return errorModal(message, title, details);\n}\n\n/** build details which may help debugging the ajax call */\nfunction _ajaxDetails(model, xhr, options) {\n return {\n //TODO: still can't manage Raven id\n raven: _.result(window.Raven, \"lastEventId\"),\n userAgent: navigator.userAgent,\n onLine: navigator.onLine,\n version: _.result(Galaxy.config, \"version_major\"),\n xhr: _.omit(xhr, _.functions(xhr)),\n options: _.omit(options, \"xhr\"),\n // add ajax data from Galaxy object cache\n url: _.result(Galaxy.lastAjax, \"url\"),\n data: _.result(Galaxy.lastAjax, \"data\"),\n // backbone stuff (auto-redacting email for user)\n model: _.result(model, \"toJSON\", `${model}`),\n user: _.omit(_.result(Galaxy.user, \"toJSON\"), \"email\")\n };\n}\n\n//=============================================================================\nexport default {\n errorModal: errorModal,\n offlineErrorModal: offlineErrorModal,\n badGatewayErrorModal: badGatewayErrorModal,\n ajaxErrorModal: ajaxErrorModal\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/ui/error-modal.js","import * as _ from \"libs/underscore\";\nimport * as Backbone from \"libs/backbone\";\nimport BASE_MVC from \"mvc/base-mvc\";\n\n//=============================================================================\n/**\n * A Collection that can be limited/offset/re-ordered/filtered.\n * @type {Backbone.Collection}\n */\nvar ControlledFetchCollection = Backbone.Collection.extend({\n /** call setOrder on initialization to build the comparator based on options */\n initialize: function(models, options) {\n Backbone.Collection.prototype.initialize.call(this, models, options);\n this.setOrder(options.order || this.order, { silent: true });\n },\n\n /** set up to track order changes and re-sort when changed */\n _setUpListeners: function() {\n return this.on({\n \"changed-order\": this.sort\n });\n },\n\n /** override to provide order and offsets based on instance vars, set limit if passed,\n * and set allFetched/fire 'all-fetched' when xhr returns\n */\n fetch: function(options) {\n options = this._buildFetchOptions(options);\n Galaxy.debug(\"fetch options:\", options);\n return Backbone.Collection.prototype.fetch.call(this, options);\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function(options) {\n // note: we normally want options passed in to override the defaults built here\n // so most of these fns will generate defaults\n options = _.clone(options) || {};\n var self = this;\n\n // jquery ajax option; allows multiple q/qv for filters (instead of 'q[]')\n options.traditional = true;\n\n // options.data\n // we keep limit, offset, etc. in options *as well as move it into data* because:\n // - it makes fetch calling convenient to add it to a single options map (instead of as mult. args)\n // - it allows the std. event handlers (for fetch, etc.) to have access\n // to the pagination options too\n // (i.e. this.on( 'sync', function( options ){ if( options.limit ){ ... } }))\n // however, when we send to xhr/jquery we copy them to data also so that they become API query params\n options.data = options.data || self._buildFetchData(options);\n Galaxy.debug(\"data:\", options.data);\n\n // options.data.filters --> options.data.q, options.data.qv\n var filters = this._buildFetchFilters(options);\n Galaxy.debug(\"filters:\", filters);\n if (!_.isEmpty(filters)) {\n _.extend(options.data, this._fetchFiltersToAjaxData(filters));\n }\n Galaxy.debug(\"data:\", options.data);\n return options;\n },\n\n /** Build the dictionary to send to fetch's XHR as data */\n _buildFetchData: function(options) {\n var defaults = {};\n if (this.order) {\n defaults.order = this.order;\n }\n return _.defaults(_.pick(options, this._fetchParams), defaults);\n },\n\n /** These attribute keys are valid params to fetch/API-index */\n _fetchParams: [\n /** model dependent string to control the order of models returned */\n \"order\",\n /** limit the number of models returned from a fetch */\n \"limit\",\n /** skip this number of models when fetching */\n \"offset\",\n /** what series of attributes to return (model dependent) */\n \"view\",\n /** individual keys to return for the models (see api/histories.index) */\n \"keys\"\n ],\n\n /** add any needed filters here based on collection state */\n _buildFetchFilters: function(options) {\n // override\n return _.clone(options.filters || {});\n },\n\n /** Convert dictionary filters to qqv style arrays */\n _fetchFiltersToAjaxData: function(filters) {\n // return as a map so ajax.data can extend from it\n var filterMap = {\n q: [],\n qv: []\n };\n _.each(filters, (v, k) => {\n // don't send if filter value is empty\n if (v === undefined || v === \"\") {\n return;\n }\n // json to python\n if (v === true) {\n v = \"True\";\n }\n if (v === false) {\n v = \"False\";\n }\n if (v === null) {\n v = \"None\";\n }\n // map to k/v arrays (q/qv)\n filterMap.q.push(k);\n filterMap.qv.push(v);\n });\n return filterMap;\n },\n\n /** override to reset allFetched flag to false */\n reset: function(models, options) {\n this.allFetched = false;\n return Backbone.Collection.prototype.reset.call(this, models, options);\n },\n\n // ........................................................................ order\n order: null,\n\n /** @type {Object} map of collection available sorting orders containing comparator fns */\n comparators: {\n update_time: BASE_MVC.buildComparator(\"update_time\", {\n ascending: false\n }),\n \"update_time-asc\": BASE_MVC.buildComparator(\"update_time\", {\n ascending: true\n }),\n create_time: BASE_MVC.buildComparator(\"create_time\", {\n ascending: false\n }),\n \"create_time-asc\": BASE_MVC.buildComparator(\"create_time\", {\n ascending: true\n })\n },\n\n /** set the order and comparator for this collection then sort with the new order\n * @event 'changed-order' passed the new order and the collection\n */\n setOrder: function(order, options) {\n options = options || {};\n var collection = this;\n var comparator = collection.comparators[order];\n if (_.isUndefined(comparator)) {\n throw new Error(`unknown order: ${order}`);\n }\n // if( _.isUndefined( comparator ) ){ return; }\n if (comparator === collection.comparator) {\n return;\n }\n\n collection.order = order;\n collection.comparator = comparator;\n\n if (!options.silent) {\n collection.trigger(\"changed-order\", options);\n }\n return collection;\n }\n});\n\n//=============================================================================\n/**\n *\n */\nvar PaginatedCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for each page's fetch */\n limitPerPage: 500,\n\n initialize: function(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n this.currentPage = options.currentPage || 0;\n },\n\n getTotalItemCount: function() {\n return this.length;\n },\n\n shouldPaginate: function() {\n return this.getTotalItemCount() >= this.limitPerPage;\n },\n\n getLastPage: function() {\n return Math.floor(this.getTotalItemCount() / this.limitPerPage);\n },\n\n getPageCount: function() {\n return this.getLastPage() + 1;\n },\n\n getPageLimitOffset: function(pageNum) {\n pageNum = this.constrainPageNum(pageNum);\n return {\n limit: this.limitPerPage,\n offset: pageNum * this.limitPerPage\n };\n },\n\n constrainPageNum: function(pageNum) {\n return Math.max(0, Math.min(pageNum, this.getLastPage()));\n },\n\n /** fetch the next page of data */\n fetchPage: function(pageNum, options) {\n var self = this;\n pageNum = self.constrainPageNum(pageNum);\n self.currentPage = pageNum;\n options = _.defaults(options || {}, self.getPageLimitOffset(pageNum));\n\n self.trigger(\"fetching-more\");\n return self.fetch(options).always(() => {\n self.trigger(\"fetching-more-done\");\n });\n },\n\n fetchCurrentPage: function(options) {\n return this.fetchPage(this.currentPage, options);\n },\n\n fetchPrevPage: function(options) {\n return this.fetchPage(this.currentPage - 1, options);\n },\n\n fetchNextPage: function(options) {\n return this.fetchPage(this.currentPage + 1, options);\n }\n});\n\n//=============================================================================\n/**\n * A Collection that will load more elements without reseting.\n */\nvar InfinitelyScrollingCollection = ControlledFetchCollection.extend({\n /** @type {Number} limit used for the first fetch (or a reset) */\n limitOnFirstFetch: null,\n /** @type {Number} limit used for each subsequent fetch */\n limitPerFetch: 100,\n\n initialize: function(models, options) {\n ControlledFetchCollection.prototype.initialize.call(this, models, options);\n /** @type {Integer} number of contents to return from the first fetch */\n this.limitOnFirstFetch = options.limitOnFirstFetch || this.limitOnFirstFetch;\n /** @type {Integer} limit for every fetch after the first */\n this.limitPerFetch = options.limitPerFetch || this.limitPerFetch;\n /** @type {Boolean} are all contents fetched? */\n this.allFetched = false;\n /** @type {Integer} what was the offset of the last content returned */\n this.lastFetched = options.lastFetched || 0;\n },\n\n /** build ajax data/parameters from options */\n _buildFetchOptions: function(options) {\n // options (options for backbone.fetch and jquery.ajax generally)\n // backbone option; false here to make fetching an addititive process\n options.remove = options.remove || false;\n return ControlledFetchCollection.prototype._buildFetchOptions.call(this, options);\n },\n\n /** fetch the first 'page' of data */\n fetchFirst: function(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchFirst:\", options);\n options = options ? _.clone(options) : {};\n this.allFetched = false;\n this.lastFetched = 0;\n return this.fetchMore(\n _.defaults(options, {\n reset: true,\n limit: this.limitOnFirstFetch\n })\n );\n },\n\n /** fetch the next page of data */\n fetchMore: function(options) {\n Galaxy.debug(\"ControlledFetchCollection.fetchMore:\", options);\n options = _.clone(options || {});\n var collection = this;\n\n Galaxy.debug(\"fetchMore, options.reset:\", options.reset);\n if (!options.reset && collection.allFetched) {\n return jQuery.when();\n }\n\n // TODO: this fails in the edge case where\n // the first fetch offset === limit (limit 4, offset 4, collection.length 4)\n if (options.reset) {\n options.offset = 0;\n } else if (options.offset === undefined) {\n options.offset = collection.lastFetched;\n }\n var limit = (options.limit = options.limit || collection.limitPerFetch || null);\n Galaxy.debug(\"fetchMore, limit:\", limit, \"offset:\", options.offset);\n\n collection.trigger(\"fetching-more\");\n return (\n collection\n .fetch(options)\n .always(() => {\n collection.trigger(\"fetching-more-done\");\n })\n // maintain allFetched flag and trigger if all were fetched this time\n .done(function _postFetchMore(fetchedData) {\n var numFetched = _.isArray(fetchedData) ? fetchedData.length : 0;\n collection.lastFetched += numFetched;\n Galaxy.debug(\"fetchMore, lastFetched:\", collection.lastFetched);\n // anything less than a full page means we got all there is to get\n if (!limit || numFetched < limit) {\n collection.allFetched = true;\n collection.trigger(\"all-fetched\", this);\n }\n })\n );\n },\n\n /** fetch all the collection */\n fetchAll: function(options) {\n // whitelist options to prevent allowing limit/offset/filters\n // (use vanilla fetch instead)\n options = options || {};\n var self = this;\n options = _.pick(options, \"silent\");\n options.filters = {};\n return self.fetch(options).done(() => {\n self.allFetched = true;\n self.trigger(\"all-fetched\", self);\n });\n }\n});\n\n//==============================================================================\nexport default {\n ControlledFetchCollection: ControlledFetchCollection,\n PaginatedCollection: PaginatedCollection,\n InfinitelyScrollingCollection: InfinitelyScrollingCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/base/controlled-fetch-collection.js","import DATASET from \"mvc/dataset/dataset-model\";\nimport HISTORY_CONTENT from \"mvc/history/history-content-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DATASET.DatasetAssociation;\n\nvar hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;\n/** @class (HDA) model for a Galaxy dataset contained in and related to a history.\n */\nvar HistoryDatasetAssociation = _super.extend(\n BASE_MVC.mixin(\n hcontentMixin,\n /** @lends HistoryDatasetAssociation.prototype */ {\n /** default attributes for a model */\n defaults: _.extend({}, _super.prototype.defaults, hcontentMixin.defaults, {\n history_content_type: \"dataset\",\n model_class: \"HistoryDatasetAssociation\"\n })\n }\n )\n);\n\n//==============================================================================\nexport default {\n HistoryDatasetAssociation: HistoryDatasetAssociation\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hda-model.js","import LIST_ITEM from \"mvc/list/list-item\";\nimport LoadingIndicator from \"ui/loading-indicator\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/search-input\";\n\nvar logNamespace = \"list\";\n/* ============================================================================\nTODO:\n\n============================================================================ */\n/** @class View for a list/collection of models and the sub-views of those models.\n * Sub-views must (at least have the interface if not) inherit from ListItemView.\n * (For a list panel that also includes some 'container' model (History->HistoryContents)\n * use ModelWithListPanel)\n *\n * Allows for:\n * searching collection/sub-views\n * selecting/multi-selecting sub-views\n *\n * Currently used:\n * for dataset/dataset-choice\n * as superclass of ModelListPanel\n */\nvar ListPanel = Backbone.View.extend(BASE_MVC.LoggableMixin).extend(\n /** @lends ListPanel.prototype */ {\n _logNamespace: logNamespace,\n\n /** class to use for constructing the sub-views */\n viewClass: LIST_ITEM.ListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: Backbone.Collection,\n\n tagName: \"div\",\n className: \"list-panel\",\n\n /** (in ms) that jquery effects will use */\n fxSpeed: \"fast\",\n\n /** string to display when the collection has no contents */\n emptyMsg: _l(\"This list is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: _l(\"No matching items found\"),\n /** string used for search placeholder */\n searchPlaceholder: _l(\"search\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the list\n */\n initialize: function(attributes, options) {\n attributes = attributes || {};\n // set the logger if requested\n if (attributes.logger) {\n this.logger = attributes.logger;\n }\n this.log(`${this}.initialize:`, attributes);\n\n // ---- instance vars\n /** how quickly should jquery fx run? */\n this.fxSpeed = _.has(attributes, \"fxSpeed\") ? attributes.fxSpeed : this.fxSpeed;\n\n /** filters for displaying subviews */\n this.filters = [];\n /** current search terms */\n this.searchFor = attributes.searchFor || \"\";\n\n /** loading indicator */\n // this.indicator = new LoadingIndicator( this.$el );\n\n /** currently showing selectors on items? */\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : true;\n //this.selecting = false;\n\n /** cached selected item.model.ids to persist btwn renders */\n this.selected = attributes.selected || [];\n /** the last selected item.model.id */\n this.lastSelected = null;\n\n /** are sub-views draggable */\n this.dragItems = attributes.dragItems || false;\n\n /** list item view class (when passed models) */\n this.viewClass = attributes.viewClass || this.viewClass;\n\n /** list item views */\n this.views = [];\n /** list item models */\n this.collection = attributes.collection || this._createDefaultCollection();\n\n /** filter fns run over collection items to see if they should show in the list */\n this.filters = attributes.filters || [];\n\n /** override $scrollContainer fn via attributes - fn should return jq for elem to call scrollTo on */\n this.$scrollContainer = attributes.$scrollContainer || this.$scrollContainer;\n\n /** @type {String} generic title */\n this.title = attributes.title || \"\";\n /** @type {String} generic subtitle */\n this.subtitle = attributes.subtitle || \"\";\n\n this._setUpListeners();\n },\n\n // ------------------------------------------------------------------------ listeners\n /** create any event listeners for the list */\n _setUpListeners: function() {\n this.off();\n\n //TODO: move errorHandler down into list-view from history-view or\n // pass to global error handler (Galaxy)\n this.on({\n error: function(model, xhr, options, msg, details) {\n //this.errorHandler( model, xhr, options, msg, details );\n console.error(model, xhr, options, msg, details);\n },\n // show hide the loading indicator\n loading: function() {\n this._showLoadingIndicator(\"loading...\", 40);\n },\n \"loading-done\": function() {\n this._hideLoadingIndicator(40);\n }\n });\n\n // throw the first render up as a diff namespace using once (for outside consumption)\n this.once(\"rendered\", function() {\n this.trigger(\"rendered:initial\", this);\n });\n\n this._setUpCollectionListeners();\n this._setUpViewListeners();\n return this;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function() {\n // override\n return new this.collectionClass([]);\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function() {\n this.log(`${this}._setUpCollectionListeners`, this.collection);\n this.stopListening(this.collection);\n\n // bubble up error events\n this.listenTo(this.collection, {\n error: function(model, xhr, options, msg, details) {\n this.trigger(\"error\", model, xhr, options, msg, details);\n },\n update: function(collection, options) {\n var changes = options.changes;\n // console.info( collection + ', update:', changes, '\\noptions:', options );\n // more than one: render everything\n if (options.renderAll || changes.added.length + changes.removed.length > 1) {\n return this.renderItems();\n }\n // otherwise, let the single add/remove handlers do it\n if (changes.added.length === 1) {\n return this.addItemView(_.first(changes.added), collection, options);\n }\n if (changes.removed.length === 1) {\n return this.removeItemView(_.first(changes.removed), collection, options);\n }\n }\n });\n return this;\n },\n\n /** listening for sub-view events that bubble up with the 'view:' prefix */\n _setUpViewListeners: function() {\n this.log(`${this}._setUpViewListeners`);\n\n // shift to select a range\n this.on({\n \"view:selected\": function(view, ev) {\n if (ev && ev.shiftKey && this.lastSelected) {\n var lastSelectedView = this.viewFromModelId(this.lastSelected);\n if (lastSelectedView) {\n this.selectRange(view, lastSelectedView);\n }\n } else if (ev && ev.altKey && !this.selecting) {\n this.showSelectors();\n }\n this.selected.push(view.model.id);\n this.lastSelected = view.model.id;\n },\n\n \"view:de-selected\": function(view, ev) {\n this.selected = _.without(this.selected, view.model.id);\n }\n });\n },\n\n // ------------------------------------------------------------------------ rendering\n /** Render this content, set up ui.\n * @param {Number or String} speed the speed of the render\n */\n render: function(speed) {\n this.log(`${this}.render`, speed);\n var $newRender = this._buildNewRender();\n this._setUpBehaviors($newRender);\n this._queueNewRender($newRender, speed);\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _buildNewRender: function() {\n this.debug(`${this}(ListPanel)._buildNewRender`);\n var $newRender = $(this.templates.el({}, this));\n this._renderControls($newRender);\n this._renderTitle($newRender);\n this._renderSubtitle($newRender);\n this._renderSearch($newRender);\n this.renderItems($newRender);\n return $newRender;\n },\n\n /** Build a temp div containing the new children for the view's $el. */\n _renderControls: function($newRender) {\n this.debug(`${this}(ListPanel)._renderControls`);\n var $controls = $(this.templates.controls({}, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n /** return a jQuery object containing the title DOM */\n _renderTitle: function($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** return a jQuery object containing the subtitle DOM (if any) */\n _renderSubtitle: function($where) {\n //$where = $where || this.$el;\n //$where.find( '.title' ).replaceWith( ... )\n },\n\n /** Fade out the old el, swap in the new contents, then fade in.\n * @param {Number or String} speed jq speed to use for rendering effects\n * @fires rendered when rendered\n */\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n $(panel).queue(\"fx\", [\n next => {\n panel.$el.fadeOut(speed, next);\n },\n next => {\n panel._swapNewRender($newRender);\n next();\n },\n next => {\n panel.$el.fadeIn(speed, next);\n },\n next => {\n panel.trigger(\"rendered\", panel);\n next();\n }\n ]);\n },\n\n /** empty out the current el, move the $newRender's children in */\n _swapNewRender: function($newRender) {\n this.$el\n .empty()\n .attr(\"class\", this.className)\n .append($newRender.children());\n if (this.selecting) {\n this.showSelectors(0);\n }\n return this;\n },\n\n /** Set up any behaviors, handlers (ep. plugins) that need to be called when the entire view has been built but\n * not attached to the page yet.\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n this.$controls($where)\n .find(\"[title]\")\n .tooltip();\n // set up the pupup for actions available when multi selecting\n this._renderMultiselectActionMenu($where);\n return this;\n },\n\n /** render a menu containing the actions available to sets of selected items */\n _renderMultiselectActionMenu: function($where) {\n $where = $where || this.$el;\n var $menu = $where.find(\".list-action-menu\");\n var actions = this.multiselectActions();\n if (!actions.length) {\n return $menu.empty();\n }\n\n var $newMenu = $(\n [\n '
',\n '\",\n '
',\n \"
\",\n \"
\"\n ].join(\"\")\n );\n var $actions = actions.map(action => {\n var html = ['
\"].join(\"\");\n return $(html).click(ev => {\n ev.preventDefault();\n return action.func(ev);\n });\n });\n $newMenu.find(\"ul\").append($actions);\n $menu.replaceWith($newMenu);\n return $newMenu;\n },\n\n /** return a list of plain objects used to render multiselect actions menu. Each object should have:\n * html: an html string used as the anchor contents\n * func: a function called when the anchor is clicked (passed the click event)\n */\n multiselectActions: function() {\n return [];\n },\n\n // ------------------------------------------------------------------------ sub-$element shortcuts\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function($where) {\n // override or set via attributes.$scrollContainer\n return ($where || this.$el).parent().parent();\n },\n /** convenience selector for the section that displays the list controls */\n $controls: function($where) {\n return ($where || this.$el).find(\"> .controls\");\n },\n /** list-items: where the subviews are contained in the view's dom */\n $list: function($where) {\n return ($where || this.$el).find(\"> .list-items\");\n },\n /** container where list messages are attached */\n $messages: function($where) {\n //TODO: controls isn't really correct here (only for ModelListPanel)\n return ($where || this.$el).find(\"> .controls .messages\");\n },\n /** the message displayed when no views can be shown (no views, none matching search) */\n $emptyMessage: function($where) {\n return ($where || this.$el).find(\"> .empty-message\");\n },\n\n // ------------------------------------------------------------------------ hda sub-views\n /** render the subviews for the list's collection */\n renderItems: function($whereTo) {\n $whereTo = $whereTo || this.$el;\n var panel = this;\n panel.log(`${this}.renderItems`, $whereTo);\n\n var $list = panel.$list($whereTo);\n panel.freeViews();\n // console.log( 'views freed' );\n //TODO:? cache and re-use views?\n var shownModels = panel._filterCollection();\n // console.log( 'models filtered:', shownModels );\n\n panel.views = shownModels.map(itemModel => {\n var view = panel._createItemView(itemModel);\n return view;\n });\n\n $list.empty();\n // console.log( 'list emptied' );\n if (panel.views.length) {\n panel._attachItems($whereTo);\n // console.log( 'items attached' );\n }\n panel._renderEmptyMessage($whereTo).toggle(!panel.views.length);\n panel.trigger(\"views:ready\", panel.views);\n\n // console.log( '------------------------------------------- rendering items' );\n return panel.views;\n },\n\n /** Filter the collection to only those models that should be currently viewed */\n _filterCollection: function() {\n // override this\n var panel = this;\n return panel.collection.filter(_.bind(panel._filterItem, panel));\n },\n\n /** Should the model be viewable in the current state?\n * Checks against this.filters and this.searchFor\n */\n _filterItem: function(model) {\n // override this\n var panel = this;\n return (\n _.every(panel.filters.map(fn => fn.call(model))) &&\n (!panel.searchFor || model.matchesAll(panel.searchFor))\n );\n },\n\n /** Create a view for a model and set up it's listeners */\n _createItemView: function(model) {\n var ViewClass = this._getItemViewClass(model);\n var options = _.extend(this._getItemViewOptions(model), {\n model: model\n });\n var view = new ViewClass(options);\n this._setUpItemViewListeners(view);\n return view;\n },\n\n /** Free a view for a model. Note: does not remove it from the DOM */\n _destroyItemView: function(view) {\n this.stopListening(view);\n this.views = _.without(this.views, view);\n },\n\n _destroyItemViews: function(view) {\n var self = this;\n self.views.forEach(v => {\n self.stopListening(v);\n });\n self.views = [];\n return self;\n },\n\n /** free any sub-views the list has */\n freeViews: function() {\n return this._destroyItemViews();\n },\n\n /** Get the bbone view class based on the model */\n _getItemViewClass: function(model) {\n // override this\n return this.viewClass;\n },\n\n /** Get the options passed to the new view based on the model */\n _getItemViewOptions: function(model) {\n // override this\n return {\n //logger : this.logger,\n fxSpeed: this.fxSpeed,\n expanded: false,\n selectable: this.selecting,\n selected: _.contains(this.selected, model.id),\n draggable: this.dragItems\n };\n },\n\n /** Set up listeners for new models */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n // send all events to the panel, re-namspaceing them with the view prefix\n this.listenTo(view, \"all\", function() {\n var args = Array.prototype.slice.call(arguments, 0);\n args[0] = `view:${args[0]}`;\n panel.trigger.apply(panel, args);\n });\n\n // drag multiple - hijack ev.setData to add all selected items\n this.listenTo(\n view,\n \"draggable:dragstart\",\n function(ev, v) {\n //TODO: set multiple drag data here\n var json = {};\n\n var selected = this.getSelectedModels();\n if (selected.length) {\n json = selected.toJSON();\n } else {\n json = [v.model.toJSON()];\n }\n ev.dataTransfer.setData(\"text\", JSON.stringify(json));\n //ev.dataTransfer.setDragImage( v.el, 60, 60 );\n },\n this\n );\n\n return panel;\n },\n\n /** Attach views in this.views to the model based on $whereTo */\n _attachItems: function($whereTo) {\n var self = this;\n // console.log( '_attachItems:', $whereTo, this.$list( $whereTo ) );\n //ASSUMES: $list has been emptied\n this.$list($whereTo).append(this.views.map(view => self._renderItemView$el(view)));\n return this;\n },\n\n /** get a given subview's $el (or whatever may wrap it) and return it */\n _renderItemView$el: function(view) {\n // useful to wrap and override\n return view.render(0).$el;\n },\n\n /** render the empty/none-found message */\n _renderEmptyMessage: function($whereTo) {\n this.debug(\"_renderEmptyMessage\", $whereTo, this.searchFor);\n var text = this.searchFor ? this.noneFoundMsg : this.emptyMsg;\n return this.$emptyMessage($whereTo).text(text);\n },\n\n /** expand all item views */\n expandAll: function() {\n _.each(this.views, view => {\n view.expand();\n });\n },\n\n /** collapse all item views */\n collapseAll: function() {\n _.each(this.views, view => {\n view.collapse();\n });\n },\n\n // ------------------------------------------------------------------------ collection/views syncing\n /** Add a view (if the model should be viewable) to the panel */\n addItemView: function(model, collection, options) {\n // console.log( this + '.addItemView:', model );\n var panel = this;\n // get the index of the model in the list of filtered models shown by this list\n // in order to insert the view in the proper place\n //TODO:? potentially expensive\n var modelIndex = panel._filterCollection().indexOf(model);\n if (modelIndex === -1) {\n return undefined;\n }\n var view = panel._createItemView(model);\n // console.log( 'adding and rendering:', modelIndex, view.toString() );\n\n $(view).queue(\"fx\", [\n next => {\n // hide the empty message first if only view\n if (panel.$emptyMessage().is(\":visible\")) {\n panel.$emptyMessage().fadeOut(panel.fxSpeed, next);\n } else {\n next();\n }\n },\n next => {\n panel._attachView(view, modelIndex);\n next();\n }\n ]);\n return view;\n },\n\n /** internal fn to add view (to both panel.views and panel.$list) */\n _attachView: function(view, modelIndex, useFx) {\n // console.log( this + '._attachView:', view, modelIndex, useFx );\n useFx = _.isUndefined(useFx) ? true : useFx;\n modelIndex = modelIndex || 0;\n var panel = this;\n\n // use the modelIndex to splice into views and insert at the proper index in the DOM\n panel.views.splice(modelIndex, 0, view);\n panel._insertIntoListAt(modelIndex, panel._renderItemView$el(view).hide());\n\n panel.trigger(\"view:attached\", view);\n if (useFx) {\n view.$el.slideDown(panel.fxSpeed, () => {\n panel.trigger(\"view:attached:rendered\");\n });\n } else {\n view.$el.show();\n panel.trigger(\"view:attached:rendered\");\n }\n return view;\n },\n\n /** insert a jq object as a child of list-items at the specified *DOM index* */\n _insertIntoListAt: function(index, $what) {\n // console.log( this + '._insertIntoListAt:', index, $what );\n var $list = this.$list();\n if (index === 0) {\n $list.prepend($what);\n } else {\n $list\n .children()\n .eq(index - 1)\n .after($what);\n }\n return $what;\n },\n\n /** Remove a view from the panel (if found) */\n removeItemView: function(model, collection, options) {\n var panel = this;\n var view = _.find(panel.views, v => v.model === model);\n if (!view) {\n return undefined;\n }\n panel.views = _.without(panel.views, view);\n panel.trigger(\"view:removed\", view);\n\n // potentially show the empty message if no views left\n // use anonymous queue here - since remove can happen multiple times\n $({}).queue(\"fx\", [\n next => {\n view.$el.fadeOut(panel.fxSpeed, next);\n },\n next => {\n view.remove();\n panel.trigger(\"view:removed:rendered\");\n if (!panel.views.length) {\n panel._renderEmptyMessage().fadeIn(panel.fxSpeed, next);\n } else {\n next();\n }\n }\n ]);\n return view;\n },\n\n /** get views based on model.id */\n viewFromModelId: function(id) {\n return _.find(this.views, v => v.model.id === id);\n },\n\n /** get views based on model */\n viewFromModel: function(model) {\n return model ? this.viewFromModelId(model.id) : undefined;\n },\n\n /** get views based on model properties */\n viewsWhereModel: function(properties) {\n return this.views.filter(view => _.isMatch(view.model.attributes, properties));\n },\n\n /** A range of views between (and including) viewA and viewB */\n viewRange: function(viewA, viewB) {\n if (viewA === viewB) {\n return viewA ? [viewA] : [];\n }\n\n var indexA = this.views.indexOf(viewA);\n var indexB = this.views.indexOf(viewB);\n\n // handle not found\n if (indexA === -1 || indexB === -1) {\n if (indexA === indexB) {\n return [];\n }\n return indexA === -1 ? [viewB] : [viewA];\n }\n // reverse if indeces are\n //note: end inclusive\n return indexA < indexB ? this.views.slice(indexA, indexB + 1) : this.views.slice(indexB, indexA + 1);\n },\n\n // ------------------------------------------------------------------------ searching\n /** render a search input for filtering datasets shown\n * (see SearchableMixin in base-mvc for implementation of the actual searching)\n * return will start the search\n * esc will clear the search\n * clicking the clear button will clear the search\n * uses searchInput in ui.js\n */\n _renderSearch: function($where) {\n $where.find(\".controls .search-input\").searchInput({\n placeholder: this.searchPlaceholder,\n initialVal: this.searchFor,\n onfirstsearch: _.bind(this._firstSearch, this),\n onsearch: _.bind(this.searchItems, this),\n onclear: _.bind(this.clearSearch, this)\n });\n return $where;\n },\n\n /** What to do on the first search entered */\n _firstSearch: function(searchFor) {\n // override to load model details if necc.\n this.log(\"onFirstSearch\", searchFor);\n return this.searchItems(searchFor);\n },\n\n /** filter view list to those that contain the searchFor terms */\n searchItems: function(searchFor, force) {\n this.log(\"searchItems\", searchFor, this.searchFor, force);\n if (!force && this.searchFor === searchFor) {\n return this;\n }\n this.searchFor = searchFor;\n this.renderItems();\n this.trigger(\"search:searching\", searchFor, this);\n var $search = this.$(\"> .controls .search-query\");\n if ($search.val() !== searchFor) {\n $search.val(searchFor);\n }\n return this;\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function(searchFor) {\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n this.renderItems();\n return this;\n },\n\n // ------------------------------------------------------------------------ selection\n /** @type Integer when the number of list item views is >= to this, don't animate selectors */\n THROTTLE_SELECTOR_FX_AT: 20,\n\n /** show selectors on all visible itemViews and associated controls */\n showSelectors: function(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = true;\n this.$(\".list-actions\").slideDown(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, view => {\n view.showSelector(speed);\n });\n //this.selected = [];\n //this.lastSelected = null;\n },\n\n /** hide selectors on all visible itemViews and associated controls */\n hideSelectors: function(speed) {\n speed = speed !== undefined ? speed : this.fxSpeed;\n this.selecting = false;\n this.$(\".list-actions\").slideUp(speed);\n speed = this.views.length >= this.THROTTLE_SELECTOR_FX_AT ? 0 : speed;\n _.each(this.views, view => {\n view.hideSelector(speed);\n });\n this.selected = [];\n this.lastSelected = null;\n },\n\n /** show or hide selectors on all visible itemViews and associated controls */\n toggleSelectors: function() {\n if (!this.selecting) {\n this.showSelectors();\n } else {\n this.hideSelectors();\n }\n },\n\n /** select all visible items */\n selectAll: function(event) {\n _.each(this.views, view => {\n view.select(event);\n });\n },\n\n /** deselect all visible items */\n deselectAll: function(event) {\n this.lastSelected = null;\n _.each(this.views, view => {\n view.deselect(event);\n });\n },\n\n /** select a range of datasets between A and B */\n selectRange: function(viewA, viewB) {\n var range = this.viewRange(viewA, viewB);\n _.each(range, view => {\n view.select();\n });\n return range;\n },\n\n /** return an array of all currently selected itemViews */\n getSelectedViews: function() {\n return _.filter(this.views, v => v.selected);\n },\n\n /** return a collection of the models of all currenly selected items */\n getSelectedModels: function() {\n // console.log( '(getSelectedModels)' );\n return new this.collection.constructor(_.map(this.getSelectedViews(), view => view.model));\n },\n\n // ------------------------------------------------------------------------ loading indicator\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function(msg, speed, callback) {\n this.debug(\"_showLoadingIndicator\", this.indicator, msg, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (!this.indicator) {\n this.indicator = new LoadingIndicator(this.$el);\n this.debug(\"\\t created\", this.indicator);\n }\n if (!this.$el.is(\":visible\")) {\n this.indicator.show(0, callback);\n } else {\n this.$el.fadeOut(speed);\n this.indicator.show(msg, speed, callback);\n }\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function(speed, callback) {\n this.debug(\"_hideLoadingIndicator\", this.indicator, speed, callback);\n speed = speed !== undefined ? speed : this.fxSpeed;\n if (this.indicator) {\n this.indicator.hide(speed, callback);\n }\n },\n\n // ------------------------------------------------------------------------ scrolling\n /** get the current scroll position of the panel in its parent */\n scrollPosition: function() {\n return this.$scrollContainer().scrollTop();\n },\n\n /** set the current scroll position of the panel in its parent */\n scrollTo: function(pos, speed) {\n speed = speed || 0;\n this.$scrollContainer().animate({ scrollTop: pos }, speed);\n return this;\n },\n\n /** Scrolls the panel to the top. */\n scrollToTop: function(speed) {\n return this.scrollTo(0, speed);\n },\n\n /** scroll to the given view in list-items */\n scrollToItem: function(view, speed) {\n if (!view) {\n return this;\n }\n return this;\n },\n\n /** Scrolls the panel to show the content with the given id. */\n scrollToId: function(id, speed) {\n return this.scrollToItem(this.viewFromModelId(id), speed);\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .select-all\": \"selectAll\",\n \"click .deselect-all\": \"deselectAll\"\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function() {\n return `ListPanel(${this.collection})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nListPanel.prototype.templates = (() => {\n var elTemplate = BASE_MVC.wrapTemplate([\n // temp container\n \"
\",\n '',\n '',\n '',\n \"
\"\n ]);\n\n var controlsTemplate = BASE_MVC.wrapTemplate([\n '
\"\n ]);\n\n return {\n el: elTemplate,\n controls: controlsTemplate\n };\n})();\n\n//=============================================================================\n/** View for a model that has a sub-collection (e.g. History, DatasetCollection)\n * Allows:\n * the model to be reset\n * auto assign panel.collection to panel.model[ panel.modelCollectionKey ]\n *\n */\nvar ModelListPanel = ListPanel.extend({\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n initialize: function(attributes) {\n ListPanel.prototype.initialize.call(this, attributes);\n this.selecting = attributes.selecting !== undefined ? attributes.selecting : false;\n\n this.setModel(this.model, attributes);\n },\n\n /** release/free/shutdown old models and set up panel for new models\n * @fires new-model with the panel as parameter\n */\n setModel: function(model, attributes) {\n attributes = attributes || {};\n this.debug(`${this}.setModel:`, model, attributes);\n\n this.freeModel();\n this.freeViews();\n\n if (model) {\n var oldModelId = this.model ? this.model.get(\"id\") : null;\n\n // set up the new model with user, logger, storage, events\n this.model = model;\n if (this.logger) {\n this.model.logger = this.logger;\n }\n this._setUpModelListeners();\n\n //TODO: relation btwn model, collection becoming tangled here\n // free the collection, and assign the new collection to either\n // the model[ modelCollectionKey ], attributes.collection, or an empty vanilla collection\n this.stopListening(this.collection);\n this.collection =\n this.model[this.modelCollectionKey] || attributes.collection || this._createDefaultCollection();\n this._setUpCollectionListeners();\n\n if (oldModelId && model.get(\"id\") !== oldModelId) {\n this.trigger(\"new-model\", this);\n }\n }\n return this;\n },\n\n /** free the current model and all listeners for it, free any views for the model */\n freeModel: function() {\n // stop/release the previous model, and clear cache to sub-views\n if (this.model) {\n this.stopListening(this.model);\n //TODO: see base-mvc\n //this.model.free();\n //this.model = null;\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ listening\n /** listening for model events */\n _setUpModelListeners: function() {\n // override\n this.log(`${this}._setUpModelListeners`, this.model);\n // bounce model errors up to the panel\n this.listenTo(\n this.model,\n \"error\",\n function() {\n var args = Array.prototype.slice.call(arguments, 0);\n //args.unshift( 'model:error' );\n args.unshift(\"error\");\n this.trigger.apply(this, args);\n },\n this\n );\n\n // debugging\n if (this.logger) {\n this.listenTo(this.model, \"all\", function(event) {\n this.info(`${this}(model)`, event, arguments);\n });\n }\n return this;\n },\n\n /** Build a temp div containing the new children for the view's $el.\n */\n _renderControls: function($newRender) {\n this.debug(`${this}(ModelListPanel)._renderControls`);\n var json = this.model ? this.model.toJSON() : {};\n var $controls = $(this.templates.controls(json, this));\n $newRender.find(\".controls\").replaceWith($controls);\n return $controls;\n },\n\n // ------------------------------------------------------------------------ misc\n /** Return a string rep of the panel */\n toString: function() {\n return `ModelListPanel(${this.model})`;\n }\n});\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nModelListPanel.prototype.templates = (() => {\n var controlsTemplate = BASE_MVC.wrapTemplate([\n '
',\n '
',\n //TODO: this is really the only difference - consider factoring titlebar out\n '
<%- model.name %>
',\n \"
\",\n '
<%- view.subtitle %>
',\n '',\n '',\n\n '
',\n '',\n \"
\",\n\n '
',\n '
',\n '\",\n '\",\n \"
\",\n '
',\n \"
\",\n \"
\",\n \"
\"\n ]);\n\n return _.extend(_.clone(ListPanel.prototype.templates), {\n controls: controlsTemplate\n });\n})();\n\n//=============================================================================\nexport default {\n ListPanel: ListPanel,\n ModelListPanel: ModelListPanel\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/list/list-view.js","import jQuery from \"jquery\";\n(\"use_strict\");\n\nvar $ = jQuery;\nvar _l = window._l || (s => s);\n\n//TODO: consolidate with tool menu functionality, use there\n\n/** searchInput: (jQuery plugin)\n * Creates a search input, a clear button, and loading indicator\n * within the selected node.\n *\n * When the user either presses return or enters some minimal number\n * of characters, a callback is called. Pressing ESC when the input\n * is focused will clear the input and call a separate callback.\n */\nfunction searchInput(parentNode, options) {\n var KEYCODE_ESC = 27;\n var KEYCODE_RETURN = 13;\n var $parentNode = $(parentNode);\n var firstSearch = true;\n\n var defaults = {\n initialVal: \"\",\n name: \"search\",\n placeholder: \"search\",\n classes: \"\",\n onclear: function() {},\n onfirstsearch: null,\n onsearch: function(inputVal) {},\n minSearchLen: 0,\n escWillClear: true,\n oninit: function() {}\n };\n\n // .................................................................... input rendering and events\n // visually clear the search, trigger an event, and call the callback\n function clearSearchInput(event) {\n var $input = $(this)\n .parent()\n .children(\"input\");\n $input\n .val(\"\")\n .trigger(\"searchInput.clear\")\n .blur();\n options.onclear();\n }\n\n // search for searchTerms, trigger an event, call the appropo callback (based on whether this is the first)\n function search(event, searchTerms) {\n if (!searchTerms) {\n return clearSearchInput();\n }\n $(this).trigger(\"search.search\", searchTerms);\n if (typeof options.onfirstsearch === \"function\" && firstSearch) {\n firstSearch = false;\n options.onfirstsearch(searchTerms);\n } else {\n options.onsearch(searchTerms);\n }\n }\n\n // .................................................................... input rendering and events\n function inputTemplate() {\n // class search-query is bootstrap 2.3 style that now lives in base.less\n return [\n '\"\n ].join(\"\");\n }\n\n // the search input that responds to keyboard events and displays the search value\n function $input() {\n return (\n $(inputTemplate())\n // select all text on a focus\n .focus(function(event) {\n $(this).select();\n })\n // attach behaviors to esc, return if desired, search on some min len string\n .keyup(function(event) {\n event.preventDefault();\n event.stopPropagation();\n\n // esc key will clear if desired\n if (event.which === KEYCODE_ESC && options.escWillClear) {\n clearSearchInput.call(this, event);\n } else {\n var searchTerms = $(this).val();\n // return key or the search string len > minSearchLen (if not 0) triggers search\n if (\n event.which === KEYCODE_RETURN ||\n (options.minSearchLen && searchTerms.length >= options.minSearchLen)\n ) {\n search.call(this, event, searchTerms);\n }\n }\n })\n .val(options.initialVal)\n );\n }\n\n // .................................................................... clear button rendering and events\n // a button for clearing the search bar, placed on the right hand side\n function $clearBtn() {\n return $(\n [''].join(\n \"\"\n )\n )\n .tooltip({ placement: \"bottom\" })\n .click(function(event) {\n clearSearchInput.call(this, event);\n });\n }\n\n // .................................................................... loadingIndicator rendering\n // a button for clearing the search bar, placed on the right hand side\n function $loadingIndicator() {\n return $(\n [''].join(\"\")\n )\n .hide()\n .tooltip({ placement: \"bottom\" });\n }\n\n // .................................................................... commands\n // visually swap the load, clear buttons\n function toggleLoadingIndicator() {\n $parentNode.find(\".search-loading\").toggle();\n $parentNode.find(\".search-clear\").toggle();\n }\n\n // .................................................................... init\n // string command (not constructor)\n if (jQuery.type(options) === \"string\") {\n if (options === \"toggle-loading\") {\n toggleLoadingIndicator();\n }\n return $parentNode;\n }\n\n // initial render\n if (jQuery.type(options) === \"object\") {\n options = jQuery.extend(true, {}, defaults, options);\n }\n //NOTE: prepended\n return $parentNode.addClass(\"search-input\").prepend([$input(), $clearBtn(), $loadingIndicator()]);\n}\n\n// as jq plugin\njQuery.fn.extend({\n searchInput: function $searchInput(options) {\n return this.each(function() {\n return searchInput(this, options);\n });\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/ui/search-input.js","import DATASET_LI from \"mvc/dataset/dataset-li\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport HISTORY_ITEM_LI from \"mvc/history/history-item-li\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DATASET_LI.DatasetListItemView;\n/** @class Read only view for HistoryDatasetAssociation.\n * Since there are no controls on the HDAView to hide the dataset,\n * the primary thing this class does (currently) is override templates\n * to render the HID.\n */\nvar HDAListItemView = _super.extend(\n /** @lends HDAListItemView.prototype */ {\n className: `${_super.prototype.className} history-content`,\n\n initialize: function(attributes, options) {\n _super.prototype.initialize.call(this, attributes, options);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDAListItemView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nHDAListItemView.prototype.templates = (() => {\n var titleBarTemplate = dataset => `\n
\n `;\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n titleBar: titleBarTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n HDCAListItemView: HDCAListItemView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hdca-li.js","import LIST_VIEW from \"mvc/list/list-view\";\nimport DC_MODEL from \"mvc/collection/collection-model\";\nimport DC_LI from \"mvc/collection/collection-li\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"collections\";\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a dataset collection.\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar CollectionView = _super.extend(\n /** @lends CollectionView.prototype */ {\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n _logNamespace: logNamespace,\n\n className: `${_super.prototype.className} dataset-collection-panel`,\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"elements\",\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n this.hasUser = attributes.hasUser;\n /** A stack of panels that currently cover or hide this panel */\n this.panelStack = [];\n /** The text of the link to go back to the panel containing this one */\n this.parentName = attributes.parentName;\n /** foldout or drilldown */\n this.foldoutStyle = attributes.foldoutStyle || \"foldout\";\n this.downloadUrl = `${Galaxy.root}api/dataset_collections/${this.model.attributes.id}/download`;\n },\n\n _queueNewRender: function($newRender, speed) {\n speed = speed === undefined ? this.fxSpeed : speed;\n var panel = this;\n panel.log(\"_queueNewRender:\", $newRender, speed);\n\n // TODO: jquery@1.12 doesn't change display when the elem has display: flex\n // this causes display: block for those elems after the use of show/hide animations\n // animations are removed from this view for now until fixed\n panel._swapNewRender($newRender);\n panel.trigger(\"rendered\", panel);\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, use model.getVisibleContents */\n _filterCollection: function() {\n //TODO: should *not* be model.getVisibleContents - visibility is not model related\n return this.model.getVisibleContents();\n },\n\n /** override to return proper view class based on element_type */\n _getItemViewClass: function(model) {\n //this.debug( this + '._getItemViewClass:', model );\n //TODO: subclasses use DCEViewClass - but are currently unused - decide\n switch (model.get(\"element_type\")) {\n case \"hda\":\n return this.DatasetDCEViewClass;\n case \"dataset_collection\":\n return this.NestedDCDCEViewClass;\n }\n throw new TypeError(\"Unknown element type:\", model.get(\"element_type\"));\n },\n\n /** override to add link target and anon */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n hasUser: this.hasUser,\n //TODO: could move to only nested: list:paired\n foldoutStyle: this.foldoutStyle\n });\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n\n // use pub-sub to: handle drilldown expansion and collapse\n panel.listenTo(view, {\n \"expanded:drilldown\": function(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n return this;\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$(\"> .controls\")\n .add(this.$list())\n .hide();\n drilldown.parentName = this.model.get(\"name\");\n this.$el.append(drilldown.render().$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function(drilldown) {\n this.panelStack.pop();\n this.render();\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: {\n \"click .navigation .back\": \"close\"\n },\n\n /** close/remove this collection panel */\n close: function(event) {\n this.remove();\n this.trigger(\"close\");\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `CollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nCollectionView.prototype.templates = (() => {\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\"\n ],\n \"collection\"\n );\n\n return _.extend(_.clone(_super.prototype.templates), {\n controls: controlsTemplate\n });\n})();\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionView = CollectionView.extend(\n /** @lends ListCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionView = ListCollectionView.extend(\n /** @lends PairCollectionView.prototype */ {\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `PairCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListOfPairsCollectionView = CollectionView.extend(\n /** @lends ListOfPairsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfPairsCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionView = CollectionView.extend({\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView.extend({\n foldoutPanelClass: PairCollectionView\n }),\n\n /** string rep */\n toString: function() {\n return `ListOfListsCollectionView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n});\n\n//==============================================================================\nexport default {\n CollectionView: CollectionView,\n ListCollectionView: ListCollectionView,\n PairCollectionView: PairCollectionView,\n ListOfPairsCollectionView: ListOfPairsCollectionView,\n ListOfListsCollectionView: ListOfListsCollectionView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-view.js","import STATES from \"mvc/dataset/states\";\nimport DATASET_LI from \"mvc/dataset/dataset-li\";\nimport TAGS from \"mvc/tag\";\nimport ANNOTATIONS from \"mvc/annotation\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = DATASET_LI.DatasetListItemView;\n/** @class Editing view for DatasetAssociation.\n */\nvar DatasetListItemEdit = _super.extend(\n /** @lends DatasetListItemEdit.prototype */ {\n /** set up: options */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n this.hasUser = attributes.hasUser;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n //TODO: move to HiddenUntilActivatedViewMixin\n /** should the tags editor be shown or hidden initially? */\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n /** should the tags editor be shown or hidden initially? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n },\n\n // ......................................................................... titlebar actions\n /** In this override, add the other two primary actions: edit and delete */\n _renderPrimaryActions: function() {\n var actions = _super.prototype._renderPrimaryActions.call(this);\n if (this.model.get(\"state\") === STATES.NOT_VIEWABLE) {\n return actions;\n }\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions\n .call(this)\n .concat([this._renderEditButton(), this._renderDeleteButton()]);\n },\n\n //TODO: move titleButtons into state renderers, remove state checks in the buttons\n\n /** Render icon-button to edit the attributes (format, permissions, etc.) this dataset. */\n _renderEditButton: function() {\n var self = this;\n // don't show edit while uploading, in-accessible\n // DO show if in error (ala previous history panel)\n if (this.model.get(\"state\") === STATES.DISCARDED || !this.model.get(\"accessible\")) {\n return null;\n }\n var purged = this.model.get(\"purged\");\n var deleted = this.model.get(\"deleted\");\n\n var editBtnData = {\n title: _l(\"Edit attributes\"),\n href: `${Galaxy.root}datasets/edit?dataset_id=${this.model.attributes.id}`,\n faIcon: \"fa-pencil\",\n classes: \"edit-btn\",\n onclick: function(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/edit\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n };\n\n // disable if purged or deleted and explain why in the tooltip\n if (deleted || purged) {\n editBtnData.disabled = true;\n if (purged) {\n editBtnData.title = _l(\"Cannot edit attributes of datasets removed from disk\");\n } else if (deleted) {\n editBtnData.title = _l(\"Undelete dataset to edit attributes\");\n }\n\n // disable if still uploading or new\n } else if (_.contains([STATES.UPLOAD, STATES.NEW], this.model.get(\"state\"))) {\n editBtnData.disabled = true;\n editBtnData.title = _l(\"This dataset is not yet editable\");\n }\n return faIconButton(editBtnData);\n },\n\n /** Render icon-button to delete this hda. */\n _renderDeleteButton: function() {\n // don't show delete if...\n if (!this.model.get(\"accessible\")) {\n return null;\n }\n\n var self = this;\n var deletedAlready = this.model.isDeletedOrPurged();\n return faIconButton({\n title: !deletedAlready ? _l(\"Delete\") : _l(\"Dataset is already deleted\"),\n disabled: deletedAlready,\n faIcon: \"fa-times\",\n classes: \"delete-btn\",\n onclick: function() {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n self.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n self.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... details\n /** In this override, add tags and annotations controls, make the ? dbkey a link to editing page */\n _renderDetails: function() {\n //TODO: generalize to be allow different details for each state\n var $details = _super.prototype._renderDetails.call(this);\n\n var state = this.model.get(\"state\");\n\n if (!this.model.isDeletedOrPurged() && _.contains([STATES.OK, STATES.FAILED_METADATA], state)) {\n this._renderTags($details);\n this._renderAnnotation($details);\n this._makeDbkeyEditLink($details);\n }\n\n this._setUpBehaviors($details);\n return $details;\n },\n\n /**************************************************************************\n * Render help button to show tool help text without rerunning the tool.\n * Issue #2100\n */\n _renderToolHelpButton: function() {\n var datasetID = this.model.attributes.dataset_id;\n var jobID = this.model.attributes.creating_job;\n var self = this;\n\n var parseToolBuild = data => {\n var helpString = `
`;\n if (data.name && data.help) {\n helpString += `Tool help for ${data.name}`;\n helpString += data.help;\n } else {\n helpString += \"Tool help is unavailable for this dataset.\";\n }\n helpString += \"
\";\n self.$el.find(\".details\").append($.parseHTML(helpString));\n };\n var parseToolID = data => {\n $.ajax({\n url: `${Galaxy.root}api/tools/${data.tool_id}/build`\n })\n .done(data => {\n parseToolBuild(data);\n })\n .fail(() => {\n parseToolBuild({});\n });\n };\n if (Galaxy.user.id === null) {\n return null;\n }\n return faIconButton({\n title: _l(\"Tool Help\"),\n classes: \"icon-btn\",\n href: \"#\",\n faIcon: \"fa-question\",\n onclick: function() {\n var divString = `thdiv-${datasetID}`;\n if (self.$el.find(\".toolhelp\").length > 0) {\n self.$el.find(\".toolhelp\").toggle();\n } else {\n $.ajax({\n url: `${Galaxy.root}api/jobs/${jobID}`\n })\n .done(data => {\n parseToolID(data);\n })\n .fail(() => {\n console.log(\n `Failed at recovering job information from the Galaxy API for job id \"${jobID}\".`\n );\n });\n }\n }\n });\n },\n //*************************************************************************\n\n /** Add less commonly used actions in the details section based on state */\n _renderSecondaryActions: function() {\n var actions = _super.prototype._renderSecondaryActions.call(this);\n switch (this.model.get(\"state\")) {\n case STATES.UPLOAD:\n case STATES.NOT_VIEWABLE:\n return actions;\n case STATES.ERROR:\n // error button comes first\n actions.unshift(this._renderErrButton());\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n case STATES.OK:\n case STATES.FAILED_METADATA:\n return actions.concat([\n this._renderRerunButton(),\n this._renderVisualizationsButton(),\n this._renderToolHelpButton()\n ]);\n }\n return actions.concat([this._renderRerunButton(), this._renderToolHelpButton()]);\n },\n\n /** Render icon-button to report an error on this dataset to the galaxy admin. */\n _renderErrButton: function() {\n var self = this;\n return faIconButton({\n title: _l(\"View or report this error\"),\n href: `${Galaxy.root}datasets/error?dataset_id=${this.model.attributes.id}`,\n classes: \"report-error-btn\",\n faIcon: \"fa-bug\",\n onclick: function(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"datasets/error\", {\n dataset_id: self.model.attributes.id\n });\n }\n }\n });\n },\n\n /** Render icon-button to re-run the job that created this dataset. */\n _renderRerunButton: function() {\n var creating_job = this.model.get(\"creating_job\");\n if (this.model.get(\"rerunnable\")) {\n return faIconButton({\n title: _l(\"Run this job again\"),\n href: this.model.urls.rerun,\n classes: \"rerun-btn\",\n target: this.linkTarget,\n faIcon: \"fa-refresh\",\n onclick: function(ev) {\n if (Galaxy.router) {\n ev.preventDefault();\n Galaxy.router.push(\"/\", {\n job_id: creating_job\n });\n }\n }\n });\n }\n },\n\n /** Render an icon-button or popupmenu of links based on the applicable visualizations */\n _renderVisualizationsButton: function() {\n //TODO: someday - lazyload visualizations\n var visualizations = this.model.get(\"visualizations\");\n if (this.model.isDeletedOrPurged() || !this.hasUser || !this.model.hasData() || _.isEmpty(visualizations)) {\n return null;\n }\n if (!_.isObject(visualizations[0])) {\n this.warn(\"Visualizations have been switched off\");\n return null;\n }\n\n var $visualizations = $(this.templates.visualizations(visualizations, this));\n //HACK: need to re-write those directed at galaxy_main with linkTarget\n $visualizations.find('[target=\"galaxy_main\"]').attr(\"target\", this.linkTarget);\n // use addBack here to include the root $visualizations elem (for the case of 1 visualization)\n this._addScratchBookFn($visualizations.find(\".visualization-link\").addBack(\".visualization-link\"));\n return $visualizations;\n },\n\n /** add scratchbook functionality to visualization links */\n _addScratchBookFn: function($links) {\n var li = this;\n $links.click(function(ev) {\n if (Galaxy.frame && Galaxy.frame.active) {\n Galaxy.frame.add({\n title: \"Visualization\",\n url: $(this).attr(\"href\")\n });\n ev.preventDefault();\n ev.stopPropagation();\n }\n });\n },\n\n //TODO: if possible move these to readonly view - but display the owner's tags/annotation (no edit)\n /** Render the tags list/control */\n _renderTags: function($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.tagsEditor = new TAGS.TagsEditor({\n model: this.model,\n el: $where.find(\".tags-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function() {\n view.tagsEditorShown = true;\n },\n onhide: function() {\n view.tagsEditorShown = false;\n },\n $activator: faIconButton({\n title: _l(\"Edit dataset tags\"),\n classes: \"tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.tagsEditorShown) {\n this.tagsEditor.toggle(true);\n }\n },\n\n /** Render the annotation display/control */\n _renderAnnotation: function($where) {\n if (!this.hasUser) {\n return;\n }\n var view = this;\n this.annotationEditor = new ANNOTATIONS.AnnotationEditor({\n model: this.model,\n el: $where.find(\".annotation-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // persist state on the hda view (and not the editor) since these are currently re-created each time\n onshow: function() {\n view.annotationEditorShown = true;\n },\n onhide: function() {\n view.annotationEditorShown = false;\n },\n $activator: faIconButton({\n title: _l(\"Edit dataset annotation\"),\n classes: \"annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".actions .right\"))\n });\n if (this.annotationEditorShown) {\n this.annotationEditor.toggle(true);\n }\n },\n\n /** If the format/dbkey/genome_build isn't set, make the display a link to the edit page */\n _makeDbkeyEditLink: function($details) {\n // make the dbkey a link to editing\n if (this.model.get(\"metadata_dbkey\") === \"?\" && !this.model.isDeletedOrPurged()) {\n var editableDbkey = $('?')\n .attr(\"href\", this.model.urls.edit)\n .attr(\"target\", \"_top\");\n $details.find(\".dbkey .value\").replaceWith(editableDbkey);\n }\n },\n\n // ......................................................................... events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .undelete-link\": \"_clickUndeleteLink\",\n \"click .purge-link\": \"_clickPurgeLink\",\n\n \"click .edit-btn\": function(ev) {\n this.trigger(\"edit\", this, ev);\n },\n \"click .delete-btn\": function(ev) {\n this.trigger(\"delete\", this, ev);\n },\n \"click .rerun-btn\": function(ev) {\n this.trigger(\"rerun\", this, ev);\n },\n \"click .report-err-btn\": function(ev) {\n this.trigger(\"report-err\", this, ev);\n },\n \"click .visualization-btn\": function(ev) {\n this.trigger(\"visualize\", this, ev);\n },\n \"click .dbkey a\": function(ev) {\n this.trigger(\"edit\", this, ev);\n }\n }),\n\n /** listener for item undelete (in the messages section) */\n _clickUndeleteLink: function(ev) {\n this.model.undelete();\n return false;\n },\n\n /** listener for item purge (in the messages section) */\n _clickPurgeLink: function(ev) {\n if (confirm(_l(\"This will permanently remove the data in your dataset. Are you sure?\"))) {\n this.model.purge();\n }\n return false;\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDAEditView(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetListItemEdit.prototype.templates = (() => {\n var warnings = _.extend({}, _super.prototype.templates.warnings, {\n failed_metadata: BASE_MVC.wrapTemplate(\n [\n // in this override, provide a link to the edit page\n '<% if( dataset.state === \"failed_metadata\" ){ %>',\n '
\",\n \"<% } %>\"\n ],\n \"dataset\"\n ),\n\n deleted: BASE_MVC.wrapTemplate(\n [\n // in this override, provide links to undelete or purge the dataset\n \"<% if( dataset.deleted && !dataset.purged ){ %>\",\n // deleted not purged\n '
\",\n \"<% } %>\"\n ],\n \"visualizations\"\n );\n\n return _.extend({}, _super.prototype.templates, {\n warnings: warnings,\n visualizations: visualizationsTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n DatasetListItemEdit: DatasetListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/dataset/dataset-li-edit.js","import baseMVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/editable-text\";\n// =============================================================================\n/** A view on any model that has a 'annotation' attribute\n */\nvar AnnotationEditor = Backbone.View.extend(baseMVC.LoggableMixin)\n .extend(baseMVC.HiddenUntilActivatedViewMixin)\n .extend({\n tagName: \"div\",\n className: \"annotation-display\",\n\n /** Set up listeners, parse options */\n initialize: function(options) {\n options = options || {};\n this.tooltipConfig = options.tooltipConfig || {\n placement: \"bottom\"\n };\n //console.debug( this, options );\n // only listen to the model only for changes to annotations\n this.listenTo(this.model, \"change:annotation\", function() {\n this.render();\n });\n this.hiddenUntilActivated(options.$activator, options);\n },\n\n /** Build the DOM elements, call select to on the created input, and set up behaviors */\n render: function() {\n var view = this;\n this.$el.html(this._template());\n\n //TODO: handle empties better\n this.$annotation().make_text_editable({\n use_textarea: true,\n on_finish: function(newAnnotation) {\n view.$annotation().text(newAnnotation);\n view.model.save({ annotation: newAnnotation }, { silent: true }).fail(() => {\n view.$annotation().text(view.model.previous(\"annotation\"));\n });\n }\n });\n return this;\n },\n\n /** @returns {String} the html text used to build the view's DOM */\n _template: function() {\n var annotation = this.model.get(\"annotation\");\n return [\n //TODO: make prompt optional\n '\",\n // set up initial tags by adding as CSV to input vals (necc. to init select2)\n '
',\n _.escape(annotation),\n \"
\"\n ].join(\"\");\n },\n\n /** @returns {jQuery} the main element for this view */\n $annotation: function() {\n return this.$el.find(\".annotation\");\n },\n\n /** shut down event listeners and remove this view's DOM */\n remove: function() {\n this.$annotation.off();\n this.stopListening(this.model);\n Backbone.View.prototype.remove.call(this);\n },\n\n /** string rep */\n toString: function() {\n return [\"AnnotationEditor(\", `${this.model}`, \")\"].join(\"\");\n }\n });\n// =============================================================================\nexport default {\n AnnotationEditor: AnnotationEditor\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/annotation.js","import jQuery from \"jquery\";\nvar $ = jQuery;\nimport GalaxyApp from \"galaxy\";\nimport Router from \"layout/router\";\nimport ToolPanel from \"./panels/tool-panel\";\nimport HistoryPanel from \"./panels/history-panel\";\nimport Page from \"layout/page\";\nimport ToolForm from \"mvc/tool/tool-form\";\nimport FormWrapper from \"mvc/form/form-wrapper\";\nimport UserPreferences from \"mvc/user/user-preferences\";\nimport CustomBuilds from \"mvc/user/user-custom-builds\";\nimport Tours from \"mvc/tours\";\nimport GridView from \"mvc/grid/grid-view\";\nimport GridShared from \"mvc/grid/grid-shared\";\nimport Workflows from \"mvc/workflow/workflow\";\nimport HistoryList from \"mvc/history/history-list\";\nimport ToolFormComposite from \"mvc/tool/tool-form-composite\";\nimport QueryStringParsing from \"utils/query-string-parsing\";\nimport Utils from \"utils/utils\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport DatasetError from \"mvc/dataset/dataset-error\";\nimport DatasetEditAttributes from \"mvc/dataset/dataset-edit-attributes\";\n\n/** define the 'Analyze Data'/analysis/main/home page for Galaxy\n * * has a masthead\n * * a left tool menu to allow the user to load tools in the center panel\n * * a right history menu that shows the user's current data\n * * a center panel\n * Both panels (generally) persist while the center panel shows any\n * UI needed for the current step of an analysis, like:\n * * tool forms to set tool parameters,\n * * tables showing the contents of datasets\n * * etc.\n */\nwindow.app = function app(options, bootstrapped) {\n window.Galaxy = new GalaxyApp.GalaxyApp(options, bootstrapped);\n Galaxy.debug(\"analysis app\");\n\n /** Routes */\n var AnalysisRouter = Router.extend({\n routes: {\n \"(/)\": \"home\",\n \"(/)root*\": \"home\",\n \"(/)tours(/)(:tour_id)\": \"show_tours\",\n \"(/)user(/)\": \"show_user\",\n \"(/)user(/)(:form_id)\": \"show_user_form\",\n \"(/)workflow(/)\": \"show_workflows\",\n \"(/)workflow/run(/)\": \"show_run\",\n \"(/)pages(/)create(/)\": \"show_pages_create\",\n \"(/)pages(/)edit(/)\": \"show_pages_edit\",\n \"(/)pages(/)(:action_id)\": \"show_pages\",\n \"(/)visualizations(/)edit(/)\": \"show_visualizations_edit\",\n \"(/)visualizations/(:action_id)\": \"show_visualizations\",\n \"(/)workflows/list_published(/)\": \"show_workflows_published\",\n \"(/)histories(/)rename(/)\": \"show_histories_rename\",\n \"(/)histories(/)permissions(/)\": \"show_histories_permissions\",\n \"(/)histories(/)(:action_id)\": \"show_histories\",\n \"(/)datasets(/)list(/)\": \"show_datasets\",\n \"(/)workflow/import_workflow\": \"show_import_workflow\",\n \"(/)custom_builds\": \"show_custom_builds\",\n \"(/)datasets/edit\": \"show_dataset_edit_attributes\",\n \"(/)datasets/error\": \"show_dataset_error\"\n },\n\n require_login: [\"show_user\", \"show_user_form\", \"show_workflows\"],\n\n authenticate: function(args, name) {\n return (Galaxy.user && Galaxy.user.id) || this.require_login.indexOf(name) == -1;\n },\n\n show_tours: function(tour_id) {\n if (tour_id) {\n Tours.giveTour(tour_id);\n } else {\n this.page.display(new Tours.ToursView());\n }\n },\n\n show_user: function() {\n this.page.display(new UserPreferences.View());\n },\n\n show_user_form: function(form_id) {\n var model = new UserPreferences.Model({\n user_id: Galaxy.params.id\n });\n this.page.display(new FormWrapper.View(model.get(form_id)));\n },\n\n show_visualizations: function(action_id) {\n this.page.display(\n new GridShared.View({\n action_id: action_id,\n plural: \"Visualizations\",\n item: \"visualization\"\n })\n );\n },\n\n show_visualizations_edit: function() {\n this.page.display(\n new FormWrapper.View({\n url: `visualization/edit?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"visualizations/list\"\n })\n );\n },\n\n show_workflows_published: function() {\n this.page.display(\n new GridView({\n url_base: `${Galaxy.root}workflow/list_published`,\n dict_format: true\n })\n );\n },\n\n show_histories: function(action_id) {\n this.page.display(new HistoryList.View({ action_id: action_id }));\n },\n\n show_histories_rename: function() {\n this.page.display(\n new FormWrapper.View({\n url: `history/rename?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"histories/list\"\n })\n );\n },\n\n show_histories_permissions: function() {\n this.page.display(\n new FormWrapper.View({\n url: `history/permissions?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"histories/list\"\n })\n );\n },\n\n show_datasets: function() {\n this.page.display(\n new GridView({\n url_base: `${Galaxy.root}dataset/list`,\n dict_format: true\n })\n );\n },\n\n show_pages: function(action_id) {\n this.page.display(\n new GridShared.View({\n action_id: action_id,\n plural: \"Pages\",\n item: \"page\"\n })\n );\n },\n\n show_pages_create: function() {\n this.page.display(\n new FormWrapper.View({\n url: \"page/create\",\n redirect: \"pages/list\"\n })\n );\n },\n\n show_pages_edit: function() {\n this.page.display(\n new FormWrapper.View({\n url: `page/edit?id=${QueryStringParsing.get(\"id\")}`,\n redirect: \"pages/list\"\n })\n );\n },\n\n show_workflows: function() {\n this.page.display(new Workflows.View());\n },\n\n show_run: function() {\n this._loadWorkflow();\n },\n\n show_import_workflow: function() {\n this.page.display(new Workflows.ImportWorkflowView());\n },\n\n show_custom_builds: function() {\n var self = this;\n var historyPanel = this.page.historyPanel.historyView;\n if (!historyPanel || !historyPanel.model || !historyPanel.model.id) {\n window.setTimeout(() => {\n self.show_custom_builds();\n }, 500);\n return;\n }\n this.page.display(new CustomBuilds.View());\n },\n\n show_dataset_edit_attributes: function() {\n this.page.display(new DatasetEditAttributes.View());\n },\n\n show_dataset_error: function() {\n this.page.display(new DatasetError.View());\n },\n\n /** */\n home: function(params) {\n // TODO: to router, remove Globals\n // load a tool by id (tool_id) or rerun a previous tool execution (job_id)\n if (params.tool_id || params.job_id) {\n if (params.tool_id === \"upload1\") {\n this.page.toolPanel.upload.show();\n this._loadCenterIframe(\"welcome\");\n } else {\n this._loadToolForm(params);\n }\n } else {\n // show the workflow run form\n if (params.workflow_id) {\n this._loadWorkflow();\n // load the center iframe with controller.action: galaxy.org/?m_c=history&m_a=list -> history/list\n } else if (params.m_c) {\n this._loadCenterIframe(`${params.m_c}/${params.m_a}`);\n // show the workflow run form\n } else {\n this._loadCenterIframe(\"welcome\");\n }\n }\n },\n\n /** load the center panel with a tool form described by the given params obj */\n _loadToolForm: function(params) {\n //TODO: load tool form code async\n params.id = decodeURIComponent(params.tool_id);\n this.page.display(new ToolForm.View(params));\n },\n\n /** load the center panel iframe using the given url */\n _loadCenterIframe: function(url, root) {\n root = root || Galaxy.root;\n url = root + url;\n this.page.$(\"#galaxy_main\").prop(\"src\", url);\n },\n\n /** load workflow by its url in run mode */\n _loadWorkflow: function() {\n var self = this;\n Utils.get({\n url: `${Galaxy.root}api/workflows/${Utils.getQueryString(\"id\")}/download?style=run`,\n success: function(response) {\n self.page.display(new ToolFormComposite.View(response));\n },\n error: function(response) {\n var error_msg = response.err_msg || \"Error occurred while loading the resource.\";\n var options = {\n message: error_msg,\n status: \"danger\",\n persistent: true\n };\n self.page.display(new Ui.Message(options));\n }\n });\n }\n });\n\n // render and start the router\n $(() => {\n Galaxy.page = new Page.View(\n _.extend(options, {\n Left: ToolPanel,\n Right: HistoryPanel,\n Router: AnalysisRouter\n })\n );\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/apps/analysis.js","import Tools from \"mvc/tool/tools\";\nimport Upload from \"mvc/upload/upload-view\";\nimport _l from \"utils/localization\";\nimport ToolForm from \"mvc/tool/tool-form-composite\";\n\nvar ToolPanel = Backbone.View.extend({\n initialize: function(page, options) {\n // access configuration options\n var config = options.config;\n this.root = options.root;\n\n /** @type {Object[]} descriptions of user's workflows to be shown in the tool menu */\n this.stored_workflow_menu_entries = config.stored_workflow_menu_entries || [];\n\n // create tool search, tool panel, and tool panel view.\n var tool_search = new Tools.ToolSearch({\n hidden: false\n });\n var tools = new Tools.ToolCollection(config.toolbox);\n this.tool_panel = new Tools.ToolPanel({\n tool_search: tool_search,\n tools: tools,\n layout: config.toolbox_in_panel\n });\n this.tool_panel_view = new Tools.ToolPanelView({\n model: this.tool_panel\n });\n\n // add upload modal\n this.upload_button = new Upload({\n nginx_upload_path: config.nginx_upload_path,\n ftp_upload_site: config.ftp_upload_site,\n default_genome: config.default_genome,\n default_extension: config.default_extension\n });\n\n // add uploader button to Galaxy object\n Galaxy.upload = this.upload_button;\n\n // components for panel definition\n this.model = new Backbone.Model({\n title: _l(\"Tools\"),\n buttons: [this.upload_button]\n });\n\n // build body template\n this.setElement(this._template());\n },\n\n render: function() {\n // if there are tools, render panel and display everything\n var self = this;\n if (this.tool_panel.get(\"layout\").size() > 0) {\n this.$el.prepend(this.tool_panel_view.$el);\n this.tool_panel_view.render();\n }\n // build the dom for the workflow portion of the tool menu\n // add internal workflow list\n self.$(\"#internal-workflows\").append(\n self._templateAllWorkflow({\n title: _l(\"All workflows\"),\n href: \"workflow\"\n })\n );\n _.each(this.stored_workflow_menu_entries, menu_entry => {\n self.$(\"#internal-workflows\").append(\n self._templateWorkflowLink({\n title: menu_entry.stored_workflow.name,\n href: `workflow/run?id=${menu_entry.encoded_stored_workflow_id}`\n })\n );\n });\n },\n\n /** build a link to one tool */\n _templateTool: function(tool) {\n return [\n '
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
' +\n '' +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n '
' +\n \"
\" +\n \"
\" +\n '' +\n \"
\" +\n \"
\" +\n '' +\n \"
\" +\n \"
\" +\n '' +\n \"
\" +\n '
' +\n \"
\" +\n '
' +\n '
' +\n '
' +\n '' +\n '
0%
' +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\"\n );\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/composite/composite-row.js","/** Renders contents of the collection uploader */\nimport Utils from \"utils/utils\";\nimport UploadModel from \"mvc/upload/upload-model\";\nimport UploadRow from \"mvc/upload/collection/collection-row\";\nimport UploadFtp from \"mvc/upload/upload-ftp\";\nimport UploadExtension from \"mvc/upload/upload-extension\";\nimport Popover from \"mvc/ui/ui-popover\";\nimport Select from \"mvc/ui/ui-select\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport LIST_COLLECTION_CREATOR from \"mvc/collection/list-collection-creator\";\nimport \"utils/uploadbox\";\nexport default Backbone.View.extend({\n // current upload size in bytes\n upload_size: 0,\n\n // contains upload row models\n collection: new UploadModel.Collection(),\n\n // keeps track of the current uploader state\n counter: {\n announce: 0,\n success: 0,\n error: 0,\n running: 0,\n reset: function() {\n this.announce = this.success = this.error = this.running = 0;\n }\n },\n\n initialize: function(app) {\n var self = this;\n this.app = app;\n this.options = app.options;\n this.list_extensions = app.list_extensions;\n this.list_genomes = app.list_genomes;\n this.ui_button = app.ui_button;\n this.ftp_upload_site = app.currentFtp();\n this.setElement(this._template());\n\n // append buttons to dom\n this.btnLocal = new Ui.Button({\n id: \"btn-local\",\n title: \"Choose local files\",\n onclick: function() {\n self.uploadbox.select();\n },\n icon: \"fa fa-laptop\"\n });\n this.btnFtp = new Ui.Button({\n id: \"btn-ftp\",\n title: \"Choose FTP files\",\n onclick: function() {\n self._eventFtp();\n },\n icon: \"fa fa-folder-open-o\"\n });\n this.btnCreate = new Ui.Button({\n id: \"btn-new\",\n title: \"Paste/Fetch data\",\n onclick: function() {\n self._eventCreate();\n },\n icon: \"fa fa-edit\"\n });\n this.btnStart = new Ui.Button({\n id: \"btn-start\",\n title: \"Start\",\n onclick: function() {\n self._eventStart();\n }\n });\n this.btnBuild = new Ui.Button({\n id: \"btn-build\",\n title: \"Build\",\n onclick: function() {\n self._eventBuild();\n }\n });\n this.btnStop = new Ui.Button({\n id: \"btn-stop\",\n title: \"Pause\",\n onclick: function() {\n self._eventStop();\n }\n });\n this.btnReset = new Ui.Button({\n id: \"btn-reset\",\n title: \"Reset\",\n onclick: function() {\n self._eventReset();\n }\n });\n this.btnClose = new Ui.Button({\n id: \"btn-close\",\n title: \"Close\",\n onclick: function() {\n self.app.modal.hide();\n }\n });\n _.each(\n [\n this.btnLocal,\n this.btnFtp,\n this.btnCreate,\n this.btnStop,\n this.btnReset,\n this.btnStart,\n this.btnBuild,\n this.btnClose\n ],\n button => {\n self.$(\".upload-buttons\").prepend(button.$el);\n }\n );\n\n // file upload\n this.uploadbox = this.$(\".upload-box\").uploadbox({\n url: this.app.options.nginx_upload_path,\n announce: function(index, file) {\n self._eventAnnounce(index, file);\n },\n initialize: function(index) {\n return self.app.toData([self.collection.get(index)], self.history_id);\n },\n progress: function(index, percentage) {\n self._eventProgress(index, percentage);\n },\n success: function(index, message) {\n self._eventSuccess(index, message);\n },\n error: function(index, message) {\n self._eventError(index, message);\n },\n complete: function() {\n self._eventComplete();\n },\n ondragover: function() {\n self.$(\".upload-box\").addClass(\"highlight\");\n },\n ondragleave: function() {\n self.$(\".upload-box\").removeClass(\"highlight\");\n }\n });\n\n // add ftp file viewer\n this.ftp = new Popover.View({\n title: \"FTP files\",\n container: this.btnFtp.$el\n });\n\n // select extension\n this.select_extension = new Select.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-extension\"),\n data: _.filter(this.list_extensions, ext => !ext.composite_files),\n value: this.options.default_extension,\n onchange: function(extension) {\n self.updateExtension(extension);\n }\n });\n\n this.collectionType = \"list\";\n this.select_collection = new Select.View({\n css: \"upload-footer-selection-compressed\",\n container: this.$(\".upload-footer-collection-type\"),\n data: [\n { id: \"list\", text: \"List\" },\n { id: \"paired\", text: \"Paired\" },\n { id: \"list:paired\", text: \"List of Pairs\" }\n ],\n value: \"list\",\n onchange: function(collectionType) {\n self.updateCollectionType(collectionType);\n }\n });\n\n // handle extension info popover\n this.$(\".upload-footer-extension-info\")\n .on(\"click\", e => {\n new UploadExtension({\n $el: $(e.target),\n title: self.select_extension.text(),\n extension: self.select_extension.value(),\n list: self.list_extensions,\n placement: \"top\"\n });\n })\n .on(\"mousedown\", e => {\n e.preventDefault();\n });\n\n // genome extension\n this.select_genome = new Select.View({\n css: \"upload-footer-selection\",\n container: this.$(\".upload-footer-genome\"),\n data: this.list_genomes,\n value: this.options.default_genome,\n onchange: function(genome) {\n self.updateGenome(genome);\n }\n });\n\n // events\n this.collection.on(\"remove\", model => {\n self._eventRemove(model);\n });\n this._updateScreen();\n },\n\n /** A new file has been dropped/selected through the uploadbox plugin */\n _eventAnnounce: function(index, file) {\n this.counter.announce++;\n var new_model = new UploadModel.Model({\n id: index,\n file_name: file.name,\n file_size: file.size,\n file_mode: file.mode || \"local\",\n file_path: file.path,\n file_data: file,\n extension: this.select_extension.value(),\n genome: this.select_genome.value()\n });\n this.collection.add(new_model);\n var upload_row = new UploadRow(this, { model: new_model });\n this.$(\".upload-table > tbody:first\").append(upload_row.$el);\n this._updateScreen();\n upload_row.render();\n },\n\n /** Progress */\n _eventProgress: function(index, percentage) {\n var it = this.collection.get(index);\n it.set(\"percentage\", percentage);\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(percentage, it.get(\"file_size\")));\n },\n\n /** Success */\n _eventSuccess: function(index, message) {\n // var hdaId = message[\"outputs\"][0][\"id\"];\n var hids = _.pluck(message[\"outputs\"], \"hid\");\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"success\", hids: hids });\n this.ui_button.model.set(\"percentage\", this._uploadPercentage(100, it.get(\"file_size\")));\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.success++;\n this._updateScreen();\n Galaxy.currHistoryPanel.refreshContents();\n },\n\n /** Error */\n _eventError: function(index, message) {\n var it = this.collection.get(index);\n it.set({ percentage: 100, status: \"error\", info: message });\n this.ui_button.model.set({\n percentage: this._uploadPercentage(100, it.get(\"file_size\")),\n status: \"danger\"\n });\n this.upload_completed += it.get(\"file_size\") * 100;\n this.counter.announce--;\n this.counter.error++;\n this._updateScreen();\n },\n\n /** Queue is done */\n _eventComplete: function() {\n this.collection.each(model => {\n model.get(\"status\") == \"queued\" && model.set(\"status\", \"init\");\n });\n this.counter.running = 0;\n this._updateScreen();\n },\n\n _eventBuild: function() {\n var allHids = [];\n _.forEach(this.collection.models, upload => {\n allHids.push.apply(allHids, upload.get(\"hids\"));\n });\n var models = _.map(allHids, hid => Galaxy.currHistoryPanel.collection.getByHid(hid));\n var selection = new Galaxy.currHistoryPanel.collection.constructor(models);\n // I'm building the selection wrong because I need to set this historyId directly.\n selection.historyId = Galaxy.currHistoryPanel.collection.historyId;\n Galaxy.currHistoryPanel.buildCollection(this.collectionType, selection, true);\n this.counter.running = 0;\n this._updateScreen();\n this._eventReset();\n this.app.modal.hide();\n },\n\n /** Remove model from upload list */\n _eventRemove: function(model) {\n var status = model.get(\"status\");\n if (status == \"success\") {\n this.counter.success--;\n } else if (status == \"error\") {\n this.counter.error--;\n } else {\n this.counter.announce--;\n }\n this.uploadbox.remove(model.id);\n this._updateScreen();\n },\n\n //\n // events triggered by this view\n //\n\n /** Show/hide ftp popup */\n _eventFtp: function() {\n if (!this.ftp.visible) {\n this.ftp.empty();\n var self = this;\n this.ftp.append(\n new UploadFtp({\n collection: this.collection,\n ftp_upload_site: this.ftp_upload_site,\n onadd: function(ftp_file) {\n return self.uploadbox.add([\n {\n mode: \"ftp\",\n name: ftp_file.path,\n size: ftp_file.size,\n path: ftp_file.path\n }\n ]);\n },\n onremove: function(model_index) {\n self.collection.remove(model_index);\n }\n }).$el\n );\n this.ftp.show();\n } else {\n this.ftp.hide();\n }\n },\n\n /** Create a new file */\n _eventCreate: function() {\n this.uploadbox.add([{ name: \"New File\", size: 0, mode: \"new\" }]);\n },\n\n /** Start upload process */\n _eventStart: function() {\n if (this.counter.announce == 0 || this.counter.running > 0) {\n return;\n }\n var self = this;\n this.upload_size = 0;\n this.upload_completed = 0;\n this.collection.each(model => {\n if (model.get(\"status\") == \"init\") {\n model.set(\"status\", \"queued\");\n self.upload_size += model.get(\"file_size\");\n }\n });\n this.ui_button.model.set({ percentage: 0, status: \"success\" });\n this.counter.running = this.counter.announce;\n this.history_id = this.app.currentHistory();\n this.uploadbox.start();\n this._updateScreen();\n },\n\n /** Pause upload process */\n _eventStop: function() {\n if (this.counter.running > 0) {\n this.ui_button.model.set(\"status\", \"info\");\n $(\".upload-top-info\").html(\"Queue will pause after completing the current file...\");\n this.uploadbox.stop();\n }\n },\n\n /** Remove all */\n _eventReset: function() {\n if (this.counter.running == 0) {\n this.collection.reset();\n this.counter.reset();\n this.uploadbox.reset();\n this.select_extension.value(this.options.default_extension);\n this.select_genome.value(this.options.default_genome);\n this.ui_button.model.set(\"percentage\", 0);\n this._updateScreen();\n }\n },\n\n /** Update extension for all models */\n updateExtension: function(extension, defaults_only) {\n var self = this;\n this.collection.each(model => {\n if (\n model.get(\"status\") == \"init\" &&\n (model.get(\"extension\") == self.options.default_extension || !defaults_only)\n ) {\n model.set(\"extension\", extension);\n }\n });\n },\n\n /** Update collection type */\n updateCollectionType: function(collectionType) {\n var self = this;\n this.collectionType = collectionType;\n },\n\n /** Update genome for all models */\n updateGenome: function(genome, defaults_only) {\n var self = this;\n this.collection.each(model => {\n if (\n model.get(\"status\") == \"init\" &&\n (model.get(\"genome\") == self.options.default_genome || !defaults_only)\n ) {\n model.set(\"genome\", genome);\n }\n });\n },\n\n /** Set screen */\n _updateScreen: function() {\n var message = \"\";\n if (this.counter.announce == 0) {\n if (this.uploadbox.compatible()) {\n message = \" \";\n } else {\n message =\n \"Browser does not support Drag & Drop. Try Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+.\";\n }\n } else {\n if (this.counter.running == 0) {\n message = `You added ${\n this.counter.announce\n } file(s) to the queue. Add more files or click 'Start' to proceed.`;\n } else {\n message = `Please wait...${this.counter.announce} out of ${this.counter.running} remaining.`;\n }\n }\n this.$(\".upload-top-info\").html(message);\n var enable_reset =\n this.counter.running == 0 && this.counter.announce + this.counter.success + this.counter.error > 0;\n var enable_start = this.counter.running == 0 && this.counter.announce > 0;\n var enable_build =\n this.counter.running == 0 &&\n this.counter.announce == 0 &&\n this.counter.success > 0 &&\n this.counter.error == 0;\n var enable_sources = this.counter.running == 0;\n var show_table = this.counter.announce + this.counter.success + this.counter.error > 0;\n this.btnReset[enable_reset ? \"enable\" : \"disable\"]();\n this.btnStart[enable_start ? \"enable\" : \"disable\"]();\n this.btnStart.$el[enable_start ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnBuild[enable_build ? \"enable\" : \"disable\"]();\n this.btnBuild.$el[enable_build ? \"addClass\" : \"removeClass\"](\"btn-primary\");\n this.btnStop[this.counter.running > 0 ? \"enable\" : \"disable\"]();\n this.btnLocal[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp[enable_sources ? \"enable\" : \"disable\"]();\n this.btnCreate[enable_sources ? \"enable\" : \"disable\"]();\n this.btnFtp.$el[this.ftp_upload_site ? \"show\" : \"hide\"]();\n this.$(\".upload-table\")[show_table ? \"show\" : \"hide\"]();\n this.$(\".upload-helper\")[show_table ? \"hide\" : \"show\"]();\n },\n\n /** Calculate percentage of all queued uploads */\n _uploadPercentage: function(percentage, size) {\n return (this.upload_completed + percentage * size) / this.upload_size;\n },\n\n /** Template */\n _template: function() {\n return (\n '
' +\n '
' +\n '
' +\n \"
\" +\n '
' +\n '
Drop files here
' +\n '
' +\n \"\" +\n \"
\" +\n \"
Name
\" +\n \"
Size
\" +\n \"
Status
\" +\n \"
\" +\n \"
\" +\n \"\" +\n \"\" +\n \"
\" +\n \"
\" +\n '\" +\n '
' +\n \"
\"\n );\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/collection/collection-view.js","/** Renders the collection uploader rows */\nimport Utils from \"utils/utils\";\nimport UploadModel from \"mvc/upload/upload-model\";\nimport UploadSettings from \"mvc/upload/upload-settings\";\nimport Popover from \"mvc/ui/ui-popover\";\nimport Select from \"mvc/ui/ui-select\";\nexport default Backbone.View.extend({\n /** Dictionary of upload states and associated icons */\n status_classes: {\n init: \"upload-icon-button fa fa-trash-o\",\n queued: \"upload-icon fa fa-spinner fa-spin\",\n running: \"upload-icon fa fa-spinner fa-spin\",\n success: \"upload-icon-button fa fa-check\",\n error: \"upload-icon-button fa fa-exclamation-triangle\"\n },\n\n initialize: function(app, options) {\n var self = this;\n this.app = app;\n this.model = options.model;\n this.setElement(this._template(options.model));\n this.$mode = this.$(\".upload-mode\");\n this.$title = this.$(\".upload-title-extended\");\n this.$text = this.$(\".upload-text\");\n this.$size = this.$(\".upload-size\");\n this.$info_text = this.$(\".upload-info-text\");\n this.$info_progress = this.$(\".upload-info-progress\");\n this.$text_content = this.$(\".upload-text-content\");\n this.$symbol = this.$(\".upload-symbol\");\n this.$progress_bar = this.$(\".upload-progress-bar\");\n this.$percentage = this.$(\".upload-percentage\");\n\n // append popup to settings icon\n this.settings = new Popover.View({\n title: \"Upload configuration\",\n container: this.$(\".upload-settings\"),\n placement: \"bottom\"\n });\n\n // identify default genome and extension values\n var default_genome = this.app.select_genome.value();\n var default_extension = this.app.select_extension.value();\n\n // handle click event\n this.$symbol.on(\"click\", () => {\n self._removeRow();\n });\n\n // handle text editing event\n this.$text_content.on(\"change input\", e => {\n self.model.set({\n url_paste: $(e.target).val(),\n file_size: $(e.target).val().length\n });\n });\n\n // model events\n this.listenTo(this.model, \"change:percentage\", () => {\n self._refreshPercentage();\n });\n this.listenTo(this.model, \"change:status\", () => {\n self._refreshStatus();\n });\n this.listenTo(this.model, \"change:info\", () => {\n self._refreshInfo();\n });\n this.listenTo(this.model, \"change:file_size\", () => {\n self._refreshFileSize();\n });\n this.listenTo(this.model, \"remove\", () => {\n self.remove();\n });\n this.app.collection.on(\"reset\", () => {\n self.remove();\n });\n },\n\n render: function() {\n var options = this.model.attributes;\n this.$title.html(_.escape(options.file_name));\n this.$size.html(Utils.bytesToString(options.file_size));\n this.$mode\n .removeClass()\n .addClass(\"upload-mode\")\n .addClass(\"text-primary\");\n if (options.file_mode == \"new\") {\n this.$text\n .css({\n width: `${this.$el.width() - 16}px`,\n top: `${this.$el.height() - 8}px`\n })\n .show();\n this.$el.height(this.$el.height() - 8 + this.$text.height() + 16);\n this.$mode.addClass(\"fa fa-edit\");\n } else if (options.file_mode == \"local\") {\n this.$mode.addClass(\"fa fa-laptop\");\n } else if (options.file_mode == \"ftp\") {\n this.$mode.addClass(\"fa fa-folder-open-o\");\n }\n },\n\n /** Refresh info text */\n _refreshInfo: function() {\n var info = this.model.get(\"info\");\n if (info) {\n this.$info_text.html(`Failed: ${info}`).show();\n } else {\n this.$info_text.hide();\n }\n },\n\n /** Refresh percentage status */\n _refreshPercentage: function() {\n var percentage = parseInt(this.model.get(\"percentage\"));\n this.$progress_bar.css({ width: `${percentage}%` });\n this.$percentage.html(percentage != 100 ? `${percentage}%` : \"Adding to history...\");\n },\n\n /** Refresh status */\n _refreshStatus: function() {\n var status = this.model.get(\"status\");\n this.$symbol\n .removeClass()\n .addClass(\"upload-symbol\")\n .addClass(this.status_classes[status]);\n this.model.set(\"enabled\", status == \"init\");\n var enabled = this.model.get(\"enabled\");\n this.$text_content.attr(\"disabled\", !enabled);\n if (status == \"success\") {\n this.$el.addClass(\"success\");\n this.$percentage.html(\"100%\");\n }\n if (status == \"error\") {\n this.$el.addClass(\"danger\");\n this.$info_progress.hide();\n }\n },\n\n /** Refresh file size */\n _refreshFileSize: function() {\n this.$size.html(Utils.bytesToString(this.model.get(\"file_size\")));\n },\n\n /** Remove row */\n _removeRow: function() {\n if ([\"init\", \"success\", \"error\"].indexOf(this.model.get(\"status\")) !== -1) {\n this.app.collection.remove(this.model);\n }\n },\n\n /** Attach file info popup */\n _showSettings: function() {\n if (!this.settings.visible) {\n this.settings.empty();\n this.settings.append(new UploadSettings(this).$el);\n this.settings.show();\n } else {\n this.settings.hide();\n }\n },\n\n /** View template */\n _template: function(options) {\n return `
You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.
0%
`;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/upload/collection/collection-row.js","export default {\n tool: \"fa-wrench\",\n data_input: \"fa-file-o\",\n data_collection_input: \"fa-folder-o\",\n subworkflow: \"fa-sitemap fa-rotate-270\",\n pause: \"fa-pause\"\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/workflow/workflow-icons.js","import Ui from \"mvc/ui/ui-misc\";\nimport historyOptionsMenu from \"mvc/history/options-menu\";\nimport CurrentHistoryView from \"mvc/history/history-view-edit-current\";\nimport _l from \"utils/localization\";\n\n/** the right hand panel in the analysis page that shows the current history */\nvar HistoryPanel = Backbone.View.extend({\n initialize: function(page, options) {\n var self = this;\n this.userIsAnonymous = Galaxy.user.isAnonymous();\n this.allow_user_dataset_purge = options.config.allow_user_dataset_purge;\n this.root = options.root;\n\n // view of the current history\n this.historyView = new CurrentHistoryView.CurrentHistoryView({\n className: `${CurrentHistoryView.CurrentHistoryView.prototype.className} middle`,\n purgeAllowed: this.allow_user_dataset_purge,\n linkTarget: \"galaxy_main\"\n });\n\n // add history panel to Galaxy object\n Galaxy.currHistoryPanel = this.historyView;\n Galaxy.currHistoryPanel.listenToGalaxy(Galaxy);\n\n // build buttons\n this.buttonRefresh = new Ui.ButtonLink({\n id: \"history-refresh-button\",\n title: \"Refresh history\",\n cls: \"panel-header-button\",\n icon: \"fa fa-refresh\",\n onclick: function() {\n self.historyView.loadCurrentHistory();\n }\n });\n this.buttonOptions = new Ui.ButtonLink({\n id: \"history-options-button\",\n title: \"History options\",\n cls: \"panel-header-button\",\n target: \"galaxy_main\",\n icon: \"fa fa-cog\",\n href: `${this.root}root/history_options`\n });\n this.buttonViewMulti = new Ui.ButtonLink({\n id: \"history-view-multi-button\",\n title: \"View all histories\",\n cls: \"panel-header-button\",\n icon: \"fa fa-columns\",\n href: `${this.root}history/view_multiple`\n });\n\n // define components\n this.model = new Backbone.Model({\n cls: \"history-right-panel\",\n title: _l(\"History\"),\n buttons: [this.buttonRefresh, this.buttonOptions, this.buttonViewMulti]\n });\n\n // build body template and connect history view\n this.setElement(this._template());\n this.historyView.setElement(this.$el);\n this.historyView.connectToQuotaMeter(Galaxy.quotaMeter);\n this.historyView.loadCurrentHistory();\n\n // fetch to update the quota meter adding 'current' for any anon-user's id\n Galaxy.listenTo(this.historyView, \"history-size-change\", () => {\n Galaxy.user.fetch({\n url: `${Galaxy.user.urlRoot()}/${Galaxy.user.id || \"current\"}`\n });\n });\n },\n\n render: function() {\n this.optionsMenu = historyOptionsMenu(this.buttonOptions.$el, {\n anonymous: this.userIsAnonymous,\n purgeAllowed: this.allow_user_dataset_purge,\n root: this.root\n });\n this.buttonViewMulti.$el[!this.userIsAnonymous ? \"show\" : \"hide\"]();\n },\n\n /** add history view div */\n _template: function(data) {\n return [''].join(\"\");\n },\n\n toString: function() {\n return \"historyPanel\";\n }\n});\n\nexport default HistoryPanel;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/apps/panels/history-panel.js","import PopupMenu from \"mvc/ui/popup-menu\";\nimport historyCopyDialog from \"mvc/history/copy-dialog\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport Webhooks from \"mvc/webhooks\";\n\n// ============================================================================\nvar menu = [\n {\n html: _l(\"History Lists\"),\n header: true\n },\n {\n html: _l(\"Saved Histories\"),\n href: \"histories/list\",\n target: \"_top\"\n },\n {\n html: _l(\"Histories Shared with Me\"),\n href: \"histories/list_shared\",\n target: \"_top\"\n },\n {\n html: _l(\"Current History\"),\n header: true,\n anon: true\n },\n {\n html: _l(\"Create New\"),\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.createNewHistory();\n }\n }\n },\n {\n html: _l(\"Copy History\"),\n func: function() {\n historyCopyDialog(Galaxy.currHistoryPanel.model).done(() => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n },\n {\n html: _l(\"Share or Publish\"),\n href: \"history/sharing\"\n },\n {\n html: _l(\"Show Structure\"),\n href: \"history/display_structured\",\n anon: true\n },\n {\n html: _l(\"Extract Workflow\"),\n href: \"workflow/build_from_current_history\"\n },\n {\n html: _l(\"Delete\"),\n anon: true,\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel && confirm(_l(\"Really delete the current history?\"))) {\n Galaxy.currHistoryPanel.model._delete().done(() => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n {\n html: _l(\"Delete Permanently\"),\n purge: true,\n anon: true,\n func: function() {\n if (\n Galaxy &&\n Galaxy.currHistoryPanel &&\n confirm(_l(\"Really delete the current history permanently? This cannot be undone.\"))\n ) {\n Galaxy.currHistoryPanel.model.purge().done(() => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n\n {\n html: _l(\"Dataset Actions\"),\n header: true,\n anon: true\n },\n {\n html: _l(\"Copy Datasets\"),\n href: \"dataset/copy_datasets\"\n },\n {\n html: _l(\"Dataset Security\"),\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel && Galaxy.router) {\n Galaxy.router.push(`/histories/permissions?id=${Galaxy.currHistoryPanel.model.id}`);\n }\n }\n },\n {\n html: _l(\"Resume Paused Jobs\"),\n href: \"history/resume_paused_jobs?current=True\",\n anon: true\n },\n {\n html: _l(\"Collapse Expanded Datasets\"),\n func: function() {\n if (Galaxy && Galaxy.currHistoryPanel) {\n Galaxy.currHistoryPanel.collapseAll();\n }\n }\n },\n {\n html: _l(\"Unhide Hidden Datasets\"),\n anon: true,\n func: function() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm(_l(\"Really unhide all hidden datasets?\"))) {\n $.post(`${Galaxy.root}history/adjust_hidden`, { user_action: \"unhide\" }, () => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n {\n html: _l(\"Delete Hidden Datasets\"),\n anon: true,\n func: function() {\n // TODO: Deprecate this functionality and replace with group dataset selector and action combination\n if (Galaxy && Galaxy.currHistoryPanel && confirm(_l(\"Really delete all hidden datasets?\"))) {\n $.post(`${Galaxy.root}history/adjust_hidden`, { user_action: \"delete\" }, () => {\n Galaxy.currHistoryPanel.loadCurrentHistory();\n });\n }\n }\n },\n {\n html: _l(\"Purge Deleted Datasets\"),\n confirm: _l(\"Really delete all deleted datasets permanently? This cannot be undone.\"),\n href: \"history/purge_deleted_datasets\",\n purge: true,\n anon: true\n },\n\n {\n html: _l(\"Downloads\"),\n header: true\n },\n {\n html: _l(\"Export Tool Citations\"),\n href: \"history/citations\",\n anon: true\n },\n {\n html: _l(\"Export History to File\"),\n href: \"history/export_archive?preview=True\",\n anon: true\n },\n\n {\n html: _l(\"Other Actions\"),\n header: true\n },\n {\n html: _l(\"Import from File\"),\n href: \"history/import_archive\"\n }\n];\n\n// Webhooks\nWebhooks.add({\n url: \"api/webhooks/history-menu/all\",\n async: false, // (hypothetically) slows down the performance\n callback: function(webhooks) {\n var webhooks_menu = [];\n\n $.each(webhooks.models, (index, model) => {\n var webhook = model.toJSON();\n if (webhook.activate) {\n webhooks_menu.push({\n html: _l(webhook.config.title),\n // func: function() {},\n anon: true\n });\n }\n });\n\n if (webhooks_menu.length > 0) {\n webhooks_menu.unshift({\n html: _l(\"Webhooks\"),\n header: true\n });\n $.merge(menu, webhooks_menu);\n }\n }\n});\n\nfunction buildMenu(isAnon, purgeAllowed, urlRoot) {\n return _.clone(menu).filter(menuOption => {\n if (isAnon && !menuOption.anon) {\n return false;\n }\n if (!purgeAllowed && menuOption.purge) {\n return false;\n }\n\n //TODO:?? hard-coded galaxy_main\n if (menuOption.href) {\n menuOption.href = urlRoot + menuOption.href;\n menuOption.target = menuOption.target || \"galaxy_main\";\n }\n\n if (menuOption.confirm) {\n menuOption.func = () => {\n if (confirm(menuOption.confirm)) {\n galaxy_main.location = menuOption.href;\n }\n };\n }\n return true;\n });\n}\n\nvar create = ($button, options) => {\n options = options || {};\n var isAnon = options.anonymous === undefined ? true : options.anonymous;\n var purgeAllowed = options.purgeAllowed || false;\n var menu = buildMenu(isAnon, purgeAllowed, Galaxy.root);\n //console.debug( 'menu:', menu );\n return new PopupMenu($button, menu);\n};\n\n// ============================================================================\nexport default create;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/options-menu.js","import HISTORY_MODEL from \"mvc/history/history-model\";\nimport HISTORY_VIEW_EDIT from \"mvc/history/history-view-edit\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n// ============================================================================\n/** session storage for history panel preferences (and to maintain state)\n */\nvar HistoryViewPrefs = BASE_MVC.SessionStorageModel.extend(\n /** @lends HistoryViewPrefs.prototype */ {\n defaults: {\n /** should the tags editor be shown or hidden initially? */\n tagsEditorShown: false,\n /** should the annotation editor be shown or hidden initially? */\n annotationEditorShown: false,\n ///** what is the currently focused content (dataset or collection) in the current history?\n // * (the history panel will highlight and scroll to the focused content view)\n // */\n //focusedContentId : null\n /** Current scroll position */\n scrollPosition: 0\n },\n toString: function() {\n return `HistoryViewPrefs(${JSON.stringify(this.toJSON())})`;\n }\n }\n);\n\n/** key string to store panel prefs (made accessible on class so you can access sessionStorage directly) */\nHistoryViewPrefs.storageKey = function storageKey() {\n return \"history-panel\";\n};\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = HISTORY_VIEW_EDIT.HistoryViewEdit;\n// used in root/index.mako\n/** @class View/Controller for the user's current history model as used in the history\n * panel (current right hand panel) of the analysis page.\n *\n * The only history panel that:\n * will poll for updates.\n * displays datasets in reverse hid order.\n */\nvar CurrentHistoryView = _super.extend(\n /** @lends CurrentHistoryView.prototype */ {\n className: `${_super.prototype.className} current-history-panel`,\n\n /** override to use drilldown (and not foldout) for how collections are displayed */\n HDCAViewClass: _super.prototype.HDCAViewClass.extend({\n foldoutStyle: \"drilldown\"\n }),\n\n emptyMsg: [\n _l(\"This history is empty\"),\n \". \",\n _l(\"You can \"),\n '',\n _l(\"load your own data\"),\n \"\",\n _l(\" or \"),\n '',\n _l(\"get data from an external source\"),\n \"\"\n ].join(\"\"),\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events */\n initialize: function(attributes) {\n attributes = attributes || {};\n\n // ---- persistent preferences\n /** maintain state / preferences over page loads */\n this.preferences = new HistoryViewPrefs(\n _.extend(\n {\n id: HistoryViewPrefs.storageKey()\n },\n _.pick(attributes, _.keys(HistoryViewPrefs.prototype.defaults))\n )\n );\n\n _super.prototype.initialize.call(this, attributes);\n\n /** sub-views that will overlay this panel (collections) */\n this.panelStack = [];\n\n /** id of currently focused content */\n this.currentContentId = attributes.currentContentId || null;\n //NOTE: purposely not sent to localstorage since panel recreation roughly lines up with a reset of this value\n },\n\n /** Override to cache the current scroll position with a listener */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n\n var panel = this;\n // reset scroll position when there's a new history\n this.on(\"new-model\", () => {\n panel.preferences.set(\"scrollPosition\", 0);\n });\n },\n\n // ------------------------------------------------------------------------ loading history/item models\n // TODO: next three more appropriate moved to the app level\n /** (re-)loads the user's current history & contents w/ details */\n loadCurrentHistory: function() {\n return this.loadHistory(null, {\n url: `${Galaxy.root}history/current_history_json`\n });\n },\n\n /** loads a history & contents w/ details and makes them the current history */\n switchToHistory: function(historyId, attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", _l(\"You must be logged in to switch histories\"), _l(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(historyId, {\n url: `${Galaxy.root}history/set_as_current?id=${historyId}`\n });\n },\n\n /** creates a new history on the server and sets it as the user's current history */\n createNewHistory: function(attributes) {\n if (Galaxy.user.isAnonymous()) {\n this.trigger(\"error\", _l(\"You must be logged in to create histories\"), _l(\"Anonymous user\"));\n return $.when();\n }\n return this.loadHistory(null, {\n url: `${Galaxy.root}history/create_new_current`\n });\n },\n\n /** release/free/shutdown old models and set up panel for new models */\n setModel: function(model, attributes, render) {\n _super.prototype.setModel.call(this, model, attributes, render);\n if (this.model && this.model.id) {\n this.log(\"checking for updates\");\n this.model.checkForUpdates();\n }\n return this;\n },\n\n // ------------------------------------------------------------------------ history/content event listening\n /** listening for history events */\n _setUpModelListeners: function() {\n _super.prototype._setUpModelListeners.call(this);\n // re-broadcast any model change events so that listeners don't have to re-bind to each history\n return this.listenTo(this.model, {\n \"change:nice_size change:size\": function() {\n this.trigger(\"history-size-change\", this, this.model, arguments);\n },\n \"change:id\": function() {\n this.once(\"loading-done\", function() {\n this.model.checkForUpdates();\n });\n }\n });\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n // if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,\n // then: remove it from the collection if the panel is set to NOT show hidden datasets\n this.listenTo(this.collection, \"state:ready\", function(model, newState, oldState) {\n if (!model.get(\"visible\") && !this.collection.storage.includeHidden()) {\n this.removeItemView(model);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** override to add a handler to capture the scroll position when the parent scrolls */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n // console.log( '_setUpBehaviors', this.$scrollContainer( $where ).get(0), this.$list( $where ) );\n // we need to call this in _setUpBehaviors which is called after render since the $el\n // may not be attached to $el.parent and $scrollContainer() may not work\n var panel = this;\n _super.prototype._setUpBehaviors.call(panel, $where);\n\n // cache the handler to remove and re-add so we don't pile up the handlers\n if (!this._debouncedScrollCaptureHandler) {\n this._debouncedScrollCaptureHandler = _.debounce(function scrollCapture() {\n // cache the scroll position (only if visible)\n if (panel.$el.is(\":visible\")) {\n panel.preferences.set(\"scrollPosition\", $(this).scrollTop());\n }\n }, 40);\n }\n\n panel\n .$scrollContainer($where)\n .off(\"scroll\", this._debouncedScrollCaptureHandler)\n .on(\"scroll\", this._debouncedScrollCaptureHandler);\n return panel;\n },\n\n /** In this override, handle null models and move the search input to the top */\n _buildNewRender: function() {\n if (!this.model) {\n return $();\n }\n var $newRender = _super.prototype._buildNewRender.call(this);\n $newRender.find(\".search\").prependTo($newRender.find(\"> .controls\"));\n this._renderQuotaMessage($newRender);\n return $newRender;\n },\n\n /** render the message displayed when a user is over quota and can't run jobs */\n _renderQuotaMessage: function($whereTo) {\n $whereTo = $whereTo || this.$el;\n return $(this.templates.quotaMsg({}, this)).prependTo($whereTo.find(\".messages\"));\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderTags: function($where) {\n var panel = this;\n // render tags and show/hide based on preferences\n _super.prototype._renderTags.call(panel, $where);\n if (panel.preferences.get(\"tagsEditorShown\")) {\n panel.tagsEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(panel.tagsEditor, \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\", tagsEditor => {\n panel.preferences.set(\"tagsEditorShown\", tagsEditor.hidden);\n });\n },\n\n /** In this override, get and set current panel preferences when editor is used */\n _renderAnnotation: function($where) {\n var panel = this;\n // render annotation and show/hide based on preferences\n _super.prototype._renderAnnotation.call(panel, $where);\n if (panel.preferences.get(\"annotationEditorShown\")) {\n panel.annotationEditor.toggle(true);\n }\n // store preference when shown or hidden\n panel.listenTo(\n panel.annotationEditor,\n \"hiddenUntilActivated:shown hiddenUntilActivated:hidden\",\n annotationEditor => {\n panel.preferences.set(\"annotationEditorShown\", annotationEditor.hidden);\n }\n );\n },\n\n /** Override to scroll to cached position (in prefs) after swapping */\n _swapNewRender: function($newRender) {\n _super.prototype._swapNewRender.call(this, $newRender);\n var panel = this;\n _.delay(() => {\n var pos = panel.preferences.get(\"scrollPosition\");\n if (pos) {\n panel.scrollTo(pos, 0);\n }\n }, 10);\n //TODO: is this enough of a delay on larger histories?\n\n return this;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** Override to add the current-content highlight class to currentContentId's view */\n _attachItems: function($whereTo) {\n _super.prototype._attachItems.call(this, $whereTo);\n var panel = this;\n if (panel.currentContentId) {\n panel._setCurrentContentById(panel.currentContentId);\n }\n return this;\n },\n\n /** Override to remove any drill down panels */\n addItemView: function(model, collection, options) {\n var view = _super.prototype.addItemView.call(this, model, collection, options);\n if (!view) {\n return view;\n }\n if (this.panelStack.length) {\n return this._collapseDrilldownPanel();\n }\n return view;\n },\n\n // ------------------------------------------------------------------------ collection sub-views\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n // use pub-sub to: handle drilldown expansion and collapse\n return panel.listenTo(view, {\n \"expanded:drilldown\": function(v, drilldown) {\n this._expandDrilldownPanel(drilldown);\n },\n \"collapsed:drilldown\": function(v, drilldown) {\n this._collapseDrilldownPanel(drilldown);\n }\n });\n },\n\n /** display 'current content': add a visible highlight and store the id of a content item */\n setCurrentContent: function(view) {\n this.$(\".history-content.current-content\").removeClass(\"current-content\");\n if (view) {\n view.$el.addClass(\"current-content\");\n this.currentContentId = view.model.id;\n } else {\n this.currentContentId = null;\n }\n },\n\n /** find the view with the id and then call setCurrentContent on it */\n _setCurrentContentById: function(id) {\n var view = this.viewFromModelId(id) || null;\n this.setCurrentContent(view);\n },\n\n /** Handle drill down by hiding this panels list and controls and showing the sub-panel */\n _expandDrilldownPanel: function(drilldown) {\n this.panelStack.push(drilldown);\n // hide this panel's controls and list, set the name for back navigation, and attach to the $el\n this.$controls()\n .add(this.$list())\n .hide();\n drilldown.parentName = this.model.get(\"name\");\n drilldown\n .delegateEvents()\n .render()\n .$el.appendTo(this.$el);\n },\n\n /** Handle drilldown close by freeing the panel and re-rendering this panel */\n _collapseDrilldownPanel: function(drilldown) {\n this.panelStack.pop();\n //TODO: MEM: free the panel\n this.$controls()\n .add(this.$list())\n .show();\n },\n\n // ........................................................................ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n // the two links in the empty message\n \"click .uploader-link\": function(ev) {\n Galaxy.upload.show(ev);\n },\n \"click .get-data-link\": function(ev) {\n var $toolMenu = $(\".toolMenuContainer\");\n $toolMenu.parent().scrollTop(0);\n $toolMenu.find('span:contains(\"Get Data\")').click();\n }\n }),\n\n // ........................................................................ external objects/MVC\n listenToGalaxy: function(galaxy) {\n this.listenTo(galaxy, {\n // when the galaxy_main iframe is loaded with a new page,\n // compare the url to the following list and if there's a match\n // pull the id from url and indicate in the history view that\n // the dataset with that id is the 'current'ly active dataset\n \"center-frame:load\": function(data) {\n var pathToMatch = data.fullpath;\n var hdaId = null;\n var useToURLRegexMap = {\n display: /datasets\\/([a-f0-9]+)\\/display/,\n edit: /datasets\\/([a-f0-9]+)\\/edit/,\n report_error: /dataset\\/errors\\?id=([a-f0-9]+)/,\n rerun: /tool_runner\\/rerun\\?id=([a-f0-9]+)/,\n show_params: /datasets\\/([a-f0-9]+)\\/show_params/\n // no great way to do this here? (leave it in the dataset event handlers above?)\n // 'visualization' : 'visualization',\n };\n _.find(useToURLRegexMap, (regex, use) => {\n // grab the more specific match result (1), save, and use it as the find flag\n hdaId = _.result(pathToMatch.match(regex), 1);\n return hdaId;\n });\n // need to type mangle to go from web route to history contents\n this._setCurrentContentById(hdaId ? `dataset-${hdaId}` : null);\n },\n // when the center panel is given a new view, clear the current indicator\n \"center-panel:load\": function(view) {\n this._setCurrentContentById();\n }\n });\n },\n\n //TODO: remove quota meter from panel and remove this\n /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */\n connectToQuotaMeter: function(quotaMeter) {\n if (!quotaMeter) {\n return this;\n }\n // show/hide the 'over quota message' in the history when the meter tells it to\n this.listenTo(quotaMeter, \"quota:over\", this.showQuotaMessage);\n this.listenTo(quotaMeter, \"quota:under\", this.hideQuotaMessage);\n\n // having to add this to handle re-render of hview while overquota (the above do not fire)\n this.on(\"rendered rendered:initial\", function() {\n if (quotaMeter && quotaMeter.isOverQuota()) {\n this.showQuotaMessage();\n }\n });\n return this;\n },\n\n /** Override to preserve the quota message */\n clearMessages: function(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target = $target.not(\".quota-message\");\n $target.fadeOut(this.fxSpeed, function() {\n $(this).remove();\n });\n return this;\n },\n\n /** Show the over quota message (which happens to be in the history panel).\n */\n showQuotaMessage: function() {\n var $msg = this.$(\".quota-message\");\n if ($msg.is(\":hidden\")) {\n $msg.slideDown(this.fxSpeed);\n }\n },\n\n /** Hide the over quota message (which happens to be in the history panel).\n */\n hideQuotaMessage: function() {\n var $msg = this.$(\".quota-message\");\n if (!$msg.is(\":hidden\")) {\n $msg.slideUp(this.fxSpeed);\n }\n },\n\n // ........................................................................ options menu\n //TODO: remove to batch\n /** unhide any hidden datasets */\n unhideHidden: function() {\n var self = this;\n if (confirm(_l(\"Really unhide all hidden datasets?\"))) {\n // get all hidden, regardless of deleted/purged\n return self.model.contents\n ._filterAndUpdate({ visible: false, deleted: \"\", purged: \"\" }, { visible: true })\n .done(() => {\n // TODO: would be better to render these as they're unhidden instead of all at once\n if (!self.model.contents.includeHidden) {\n self.renderItems();\n }\n });\n }\n return jQuery.when();\n },\n\n /** delete any hidden datasets */\n deleteHidden: function() {\n var self = this;\n if (confirm(_l(\"Really delete all hidden datasets?\"))) {\n return self.model.contents._filterAndUpdate(\n // get all hidden, regardless of deleted/purged\n { visible: false, deleted: \"\", purged: \"\" },\n // both delete *and* unhide them\n { deleted: true, visible: true }\n );\n }\n return jQuery.when();\n },\n\n /** Return a string rep of the history */\n toString: function() {\n return `CurrentHistoryView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nCurrentHistoryView.prototype.templates = (() => {\n var quotaMsgTemplate = BASE_MVC.wrapTemplate(\n [\n '
',\n _l(\"You are over your disk quota\"),\n \". \",\n _l(\"Tool execution is on hold until your disk usage drops below your allocated quota\"),\n \".\",\n \"
\"\n ],\n \"history\"\n );\n return _.extend(_.clone(_super.prototype.templates), {\n quotaMsg: quotaMsgTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n CurrentHistoryView: CurrentHistoryView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-view-edit-current.js","//ASSUMES: jquery\n//=============================================================================\n/** @class AjaxQueue\n * Class that allows queueing functions that return jQuery promises (such\n * as ajax calls). Each function waits for the previous to complete before\n * being called\n *\n * @constructor accepts a list of functions and automatically begins\n * processing them\n */\nclass AjaxQueue {\n constructor(initialFunctions) {\n /** the main deferred for the entire queue - note: also sends notifications of progress */\n this.deferred = jQuery.Deferred();\n /** the queue array of functions */\n this.queue = [];\n /** cache the response from each deferred call - error or success */\n this.responses = [];\n /** total number of fn's to process */\n this.numToProcess = 0;\n /** is the queue processing/waiting for any calls to return? */\n this.running = false;\n\n this.init(initialFunctions || []);\n this.start();\n }\n\n /** add all fns in initialFunctions (if any) to the queue */\n init(initialFunctions) {\n initialFunctions.forEach(fn => {\n this.add(fn);\n });\n }\n\n add(fn) {\n var index = this.queue.length;\n this.numToProcess += 1;\n\n this.queue.push(() => {\n var fnIndex = index;\n var xhr = fn();\n // if successful, notify using the deferred to allow tracking progress\n xhr.done(response => {\n this.deferred.notify({\n curr: fnIndex,\n total: this.numToProcess,\n response: response\n });\n });\n // (regardless of previous error or success) if not last ajax call, shift and call the next\n // if last fn, resolve deferred\n xhr.always(response => {\n this.responses.push(response);\n if (this.queue.length) {\n this.queue.shift()();\n } else {\n this.stop();\n }\n });\n });\n return this;\n }\n\n start() {\n if (this.queue.length) {\n this.running = true;\n this.queue.shift()();\n }\n return this;\n }\n\n /** stop the queue\n * @param {boolean} causeFail cause an error/fail on the main deferred\n * @param {String} msg message to send when rejecting the main deferred\n */\n stop(causeFail, msg) {\n //TODO: doesn't abort current call\n this.running = false;\n this.queue = [];\n if (causeFail) {\n //TODO: spliced args instead\n this.deferred.reject(msg);\n } else {\n this.deferred.resolve(this.responses);\n }\n this.numToProcess = 0;\n this.deferred = jQuery.Deferred();\n return this;\n }\n\n // only a handful of the deferred interface for now - possible YAGNI\n /** implement done from the jq deferred interface */\n done(fn) {\n return this.deferred.done(fn);\n }\n\n /** implement fail from the jq deferred interface */\n fail(fn) {\n return this.deferred.fail(fn);\n }\n\n /** implement always from the jq deferred interface */\n always(fn) {\n return this.deferred.always(fn);\n }\n\n /** implement progress from the jq deferred interface */\n progress(fn) {\n return this.deferred.progress(fn);\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n static create(initialFunctions) {\n return new AjaxQueue(initialFunctions).deferred;\n }\n}\n\n//=============================================================================\n/** @class NamedAjaxQueue\n * @augments AjaxQueue\n * Allows associating a name with a deferring fn and prevents adding deferring\n * fns if the name has already been used. Useful to prevent build up of duplicate\n * async calls.\n * Both the array initialFunctions sent to constructor and any added later with\n * add() should be objects (NOT functions) of the form:\n * { name: some unique id,\n * fn: the deferring fn or ajax call }\n */\nclass NamedAjaxQueue extends AjaxQueue {\n constructor(initialFunctions) {\n super(initialFunctions);\n this.names = {};\n }\n\n /** add the obj.fn to the queue if obj.name hasn't been used before */\n add(obj) {\n if (!(obj.hasOwnProperty(\"name\") && obj.hasOwnProperty(\"fn\"))) {\n throw new Error(`NamedAjaxQueue.add requires an object with both \"name\" and \"fn\": ${JSON.stringify(obj)}`);\n }\n if (this.names.hasOwnProperty(obj.name)) {\n //console.warn( 'name has been used:', obj.name );\n return;\n }\n this.names[obj.name] = true;\n return super.add(obj.fn);\n }\n\n clear() {\n this.names = {};\n return this;\n }\n\n /** shortcut constructor / fire and forget\n * @returns {Deferred} the queue's main deferred\n */\n static create(initialFunctions) {\n return new NamedAjaxQueue(initialFunctions).deferred;\n }\n}\n\n//=============================================================================\nexport default {\n AjaxQueue: AjaxQueue,\n NamedAjaxQueue: NamedAjaxQueue\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/ajax-queue.js","import HISTORY_VIEW from \"mvc/history/history-view\";\nimport HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport STATES from \"mvc/dataset/states\";\nimport HDA_MODEL from \"mvc/history/hda-model\";\nimport HDA_LI_EDIT from \"mvc/history/hda-li-edit\";\nimport HDCA_LI_EDIT from \"mvc/history/hdca-li-edit\";\nimport TAGS from \"mvc/tag\";\nimport ANNOTATIONS from \"mvc/annotation\";\nimport LIST_COLLECTION_CREATOR from \"mvc/collection/list-collection-creator\";\nimport PAIR_COLLECTION_CREATOR from \"mvc/collection/pair-collection-creator\";\nimport LIST_OF_PAIRS_COLLECTION_CREATOR from \"mvc/collection/list-of-pairs-collection-creator\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport PopupMenu from \"mvc/ui/popup-menu\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/editable-text\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\nvar _super = HISTORY_VIEW.HistoryView;\n// base class for history-view-edit-current and used as-is in history/view.mako\n/** @class Editable View/Controller for the history model.\n *\n * Allows:\n * (everything HistoryView allows)\n * changing the name\n * displaying and editing tags and annotations\n * multi-selection and operations on mulitple content items\n */\nvar HistoryViewEdit = _super.extend(\n /** @lends HistoryViewEdit.prototype */ {\n /** class to use for constructing the HistoryDatasetAssociation views */\n HDAViewClass: HDA_LI_EDIT.HDAListItemEdit,\n /** class to use for constructing the HistoryDatasetCollectionAssociation views */\n HDCAViewClass: HDCA_LI_EDIT.HDCAListItemEdit,\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes\n */\n initialize: function(attributes) {\n attributes = attributes || {};\n _super.prototype.initialize.call(this, attributes);\n\n // ---- set up instance vars\n /** editor for tags - sub-view */\n this.tagsEditor = null;\n\n /** enable drag and drop - sub-view */\n this.dragItems = true;\n\n /** editor for annotations - sub-view */\n this.annotationEditor = null;\n\n /** allow user purge of dataset files? */\n this.purgeAllowed = attributes.purgeAllowed || false;\n\n // states/modes the panel can be in\n /** is the panel currently showing the dataset selection controls? */\n this.annotationEditorShown = attributes.annotationEditorShown || false;\n this.tagsEditorShown = attributes.tagsEditorShown || false;\n },\n\n /** Override to handle history as drag-drop target */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n return this.on({\n \"droptarget:drop\": function(ev, data) {\n // process whatever was dropped and re-hide the drop target\n this.dataDropped(data);\n this.dropTargetOff();\n },\n \"view:attached view:removed\": function() {\n this._renderCounts();\n },\n \"search:loading-progress\": this._renderSearchProgress,\n \"search:searching\": this._renderSearchFindings\n });\n },\n\n // ------------------------------------------------------------------------ listeners\n /** listening for history and HDA events */\n _setUpModelListeners: function() {\n _super.prototype._setUpModelListeners.call(this);\n this.listenTo(this.model, \"change:size\", this.updateHistoryDiskSize);\n return this;\n },\n\n /** listening for collection events */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n this.listenTo(this.collection, {\n \"change:deleted\": this._handleItemDeletedChange,\n \"change:visible\": this._handleItemVisibleChange,\n \"change:purged\": function(model) {\n // hafta get the new nice-size w/o the purged model\n this.model.fetch();\n },\n // loading indicators for deleted/hidden\n \"fetching-deleted\": function(collection) {\n this.$(\"> .controls .deleted-count\").html(`${_l(\"loading...\")}`);\n },\n \"fetching-hidden\": function(collection) {\n this.$(\"> .controls .hidden-count\").html(`${_l(\"loading...\")}`);\n },\n \"fetching-deleted-done fetching-hidden-done\": this._renderCounts\n });\n return this;\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** In this override, add tag and annotation editors and a btn to toggle the selectors */\n _buildNewRender: function() {\n // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.\n var $newRender = _super.prototype._buildNewRender.call(this);\n if (!this.model) {\n return $newRender;\n }\n\n if (Galaxy && Galaxy.user && Galaxy.user.id && Galaxy.user.id === this.model.get(\"user_id\")) {\n this._renderTags($newRender);\n this._renderAnnotation($newRender);\n }\n return $newRender;\n },\n\n /** Update the history size display (curr. upper right of panel). */\n updateHistoryDiskSize: function() {\n this.$(\".history-size\").text(this.model.get(\"nice_size\"));\n },\n\n /** override to render counts when the items are rendered */\n renderItems: function($whereTo) {\n var views = _super.prototype.renderItems.call(this, $whereTo);\n if (!this.searchFor) {\n this._renderCounts($whereTo);\n } else {\n this._renderSearchFindings($whereTo);\n }\n return views;\n },\n\n /** override to show counts, what's deleted/hidden, and links to toggle those */\n _renderCounts: function($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.counts(this.model.toJSON(), this);\n return $whereTo.find(\"> .controls .subtitle\").html(html);\n },\n\n /** render the tags sub-view controller */\n _renderTags: function($where) {\n var panel = this;\n this.tagsEditor = new TAGS.TagsEditor({\n model: this.model,\n el: $where.find(\".controls .tags-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // show hide sub-view tag editors when this is shown/hidden\n onshow: function() {\n panel.toggleHDATagEditors(true, panel.fxSpeed);\n },\n onhide: function() {\n panel.toggleHDATagEditors(false, panel.fxSpeed);\n },\n $activator: faIconButton({\n title: _l(\"Edit history tags\"),\n classes: \"history-tag-btn\",\n faIcon: \"fa-tags\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n /** render the annotation sub-view controller */\n _renderAnnotation: function($where) {\n var panel = this;\n this.annotationEditor = new ANNOTATIONS.AnnotationEditor({\n model: this.model,\n el: $where.find(\".controls .annotation-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n // show hide sub-view view annotation editors when this is shown/hidden\n onshow: function() {\n panel.toggleHDAAnnotationEditors(true, panel.fxSpeed);\n },\n onhide: function() {\n panel.toggleHDAAnnotationEditors(false, panel.fxSpeed);\n },\n $activator: faIconButton({\n title: _l(\"Edit history annotation\"),\n classes: \"history-annotate-btn\",\n faIcon: \"fa-comment\"\n }).appendTo($where.find(\".controls .actions\"))\n });\n },\n\n /** Set up HistoryViewEdit js/widget behaviours\n * In this override, make the name editable\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n _super.prototype._setUpBehaviors.call(this, $where);\n if (!this.model) {\n return;\n }\n\n // anon users shouldn't have access to any of the following\n if (!Galaxy.user || Galaxy.user.isAnonymous() || Galaxy.user.id !== this.model.get(\"user_id\")) {\n return;\n }\n\n var panel = this;\n var nameSelector = \"> .controls .name\";\n $where\n .find(nameSelector)\n .attr(\"title\", _l(\"Click to rename history\"))\n .tooltip({ placement: \"bottom\" })\n .make_text_editable({\n on_finish: function(newName) {\n var previousName = panel.model.get(\"name\");\n if (newName && newName !== previousName) {\n panel.$el.find(nameSelector).text(newName);\n panel.model.save({ name: newName }).fail(() => {\n panel.$el.find(nameSelector).text(panel.model.previous(\"name\"));\n });\n } else {\n panel.$el.find(nameSelector).text(previousName);\n }\n }\n });\n },\n\n /** return a new popup menu for choosing a multi selection action\n * ajax calls made for multiple datasets are queued\n */\n multiselectActions: function() {\n var panel = this;\n\n var actions = [\n {\n html: _l(\"Hide datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.hide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n },\n {\n html: _l(\"Unhide datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.unhide;\n panel.getSelectedModels().ajaxQueue(action);\n }\n },\n {\n html: _l(\"Delete datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype[\"delete\"];\n panel.getSelectedModels().ajaxQueue(action);\n }\n },\n {\n html: _l(\"Undelete datasets\"),\n func: function() {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.undelete;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }\n ];\n\n if (panel.purgeAllowed) {\n actions.push({\n html: _l(\"Permanently delete datasets\"),\n func: function() {\n if (confirm(_l(\"This will permanently remove the data in your datasets. Are you sure?\"))) {\n var action = HDA_MODEL.HistoryDatasetAssociation.prototype.purge;\n panel.getSelectedModels().ajaxQueue(action);\n }\n }\n });\n }\n actions = actions.concat(panel._collectionActions());\n return actions;\n },\n\n /** */\n _collectionActions: function() {\n var panel = this;\n return [\n {\n html: _l(\"Build Dataset List\"),\n func: function() {\n panel.buildCollection(\"list\");\n }\n },\n // TODO: Only show quick pair if two things selected.\n {\n html: _l(\"Build Dataset Pair\"),\n func: function() {\n panel.buildCollection(\"paired\");\n }\n },\n {\n html: _l(\"Build List of Dataset Pairs\"),\n func: function() {\n panel.buildCollection(\"list:paired\");\n }\n }\n ];\n },\n\n buildCollection: function(collectionType, selection, hideSourceItems) {\n var panel = this;\n var selection = selection || panel.getSelectedModels();\n var hideSourceItems = hideSourceItems || false;\n var createFunc;\n if (collectionType == \"list\") {\n createFunc = LIST_COLLECTION_CREATOR.createListCollection;\n } else if (collectionType == \"paired\") {\n createFunc = PAIR_COLLECTION_CREATOR.createPairCollection;\n } else if (collectionType == \"list:paired\") {\n createFunc = LIST_OF_PAIRS_COLLECTION_CREATOR.createListOfPairsCollection;\n } else {\n console.warn(`Unknown collectionType encountered ${collectionType}`);\n }\n createFunc(selection, hideSourceItems).done(() => {\n panel.model.refresh();\n });\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** In this override, add purgeAllowed and whether tags/annotation editors should be shown */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n _.extend(options, {\n purgeAllowed: this.purgeAllowed,\n tagsEditorShown: this.tagsEditor && !this.tagsEditor.hidden,\n annotationEditorShown: this.annotationEditor && !this.annotationEditor.hidden\n });\n return options;\n },\n\n /** If this item is deleted and we're not showing deleted items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemDeletedChange: function(itemModel) {\n if (itemModel.get(\"deleted\")) {\n this._handleItemDeletion(itemModel);\n } else {\n this._handleItemUndeletion(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemDeletion: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeDeleted) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUndeletion: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.deleted -= 1;\n if (!this.model.contents.includeDeleted) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** If this item is hidden and we're not showing hidden items, remove the view\n * @param {Model} the item model to check\n */\n _handleItemVisibleChange: function(itemModel) {\n if (itemModel.hidden()) {\n this._handleItemHidden(itemModel);\n } else {\n this._handleItemUnhidden(itemModel);\n }\n this._renderCounts();\n },\n\n _handleItemHidden: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden += 1;\n contentsShown.active -= 1;\n if (!this.model.contents.includeHidden) {\n this.removeItemView(itemModel);\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n _handleItemUnhidden: function(itemModel) {\n var contentsShown = this.model.get(\"contents_active\");\n contentsShown.hidden -= 1;\n if (!this.model.contents.includeHidden) {\n contentsShown.active -= 1;\n }\n this.model.set(\"contents_active\", contentsShown);\n },\n\n /** toggle the visibility of each content's tagsEditor applying all the args sent to this function */\n toggleHDATagEditors: function(showOrHide, speed) {\n _.each(this.views, view => {\n if (view.tagsEditor) {\n view.tagsEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n /** toggle the visibility of each content's annotationEditor applying all the args sent to this function */\n toggleHDAAnnotationEditors: function(showOrHide, speed) {\n _.each(this.views, view => {\n if (view.annotationEditor) {\n view.annotationEditor.toggle(showOrHide, speed);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click .toggle-deleted-link\": function(ev) {\n this.toggleShowDeleted();\n },\n \"click .toggle-hidden-link\": function(ev) {\n this.toggleShowHidden();\n }\n }),\n\n // ------------------------------------------------------------------------ search\n _renderSearchProgress: function(limit, offset) {\n var stop = limit + offset;\n return this.$(\"> .controls .subtitle\").html(\n [\"\", _l(\"Searching \"), stop, \"/\", this.model.contentsShown(), \"\"].join(\"\")\n );\n },\n\n /** override to display number found in subtitle */\n _renderSearchFindings: function($whereTo) {\n $whereTo = $whereTo instanceof jQuery ? $whereTo : this.$el;\n var html = this.templates.found(this.model.toJSON(), this);\n $whereTo.find(\"> .controls .subtitle\").html(html);\n return this;\n },\n\n // ------------------------------------------------------------------------ as drop target\n /** turn all the drag and drop handlers on and add some help text above the drop area */\n dropTargetOn: function() {\n if (this.dropTarget) {\n return this;\n }\n this.dropTarget = true;\n\n //TODO: to init\n var dropHandlers = {\n dragenter: _.bind(this.dragenter, this),\n dragover: _.bind(this.dragover, this),\n dragleave: _.bind(this.dragleave, this),\n drop: _.bind(this.drop, this)\n };\n\n var $dropTarget = this._renderDropTarget();\n this.$list().before([this._renderDropTargetHelp(), $dropTarget]);\n for (var evName in dropHandlers) {\n if (dropHandlers.hasOwnProperty(evName)) {\n //console.debug( evName, dropHandlers[ evName ] );\n $dropTarget.on(evName, dropHandlers[evName]);\n }\n }\n return this;\n },\n\n /** render a box to serve as a 'drop here' area on the history */\n _renderDropTarget: function() {\n this.$(\".history-drop-target\").remove();\n return $(\"\").addClass(\"history-drop-target\");\n },\n\n /** tell the user how it works */\n _renderDropTargetHelp: function() {\n this.$(\".history-drop-target-help\").remove();\n return $(\"\")\n .addClass(\"history-drop-target-help\")\n .text(_l(\"Drag datasets here to copy them to the current history\"));\n },\n\n /** shut down drag and drop event handlers and remove drop target */\n dropTargetOff: function() {\n if (!this.dropTarget) {\n return this;\n }\n //this.log( 'dropTargetOff' );\n this.dropTarget = false;\n var dropTarget = this.$(\".history-drop-target\").get(0);\n for (var evName in this._dropHandlers) {\n if (this._dropHandlers.hasOwnProperty(evName)) {\n dropTarget.off(evName, this._dropHandlers[evName]);\n }\n }\n this.$(\".history-drop-target\").remove();\n this.$(\".history-drop-target-help\").remove();\n return this;\n },\n /** toggle the target on/off */\n dropTargetToggle: function() {\n if (this.dropTarget) {\n this.dropTargetOff();\n } else {\n this.dropTargetOn();\n }\n return this;\n },\n\n dragenter: function(ev) {\n //console.debug( 'dragenter:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"2px solid black\");\n },\n dragover: function(ev) {\n ev.preventDefault();\n ev.stopPropagation();\n },\n dragleave: function(ev) {\n //console.debug( 'dragleave:', this, ev );\n ev.preventDefault();\n ev.stopPropagation();\n this.$(\".history-drop-target\").css(\"border\", \"1px dashed black\");\n },\n /** when (text) is dropped try to parse as json and trigger an event */\n drop: function(ev) {\n ev.preventDefault();\n //ev.stopPropagation();\n\n var self = this;\n var dataTransfer = ev.originalEvent.dataTransfer;\n var data = dataTransfer.getData(\"text\");\n\n dataTransfer.dropEffect = \"move\";\n try {\n data = JSON.parse(data);\n } catch (err) {\n self.warn(\"error parsing JSON from drop:\", data);\n }\n\n self.trigger(\"droptarget:drop\", ev, data, self);\n return false;\n },\n\n /** handler that copies data into the contents */\n dataDropped: function(data) {\n var self = this;\n // HDA: dropping will copy it to the history\n if (_.isObject(data) && data.model_class === \"HistoryDatasetAssociation\" && data.id) {\n if (self.contents.currentPage !== 0) {\n return self.contents.fetchPage(0).then(() => self.model.contents.copy(data.id));\n }\n return self.model.contents.copy(data.id);\n }\n return jQuery.when();\n },\n\n // ........................................................................ misc\n /** Return a string rep of the history */\n toString: function() {\n return `HistoryViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryViewEdit.prototype.templates = (() => {\n var countsTemplate = BASE_MVC.wrapTemplate(\n [\n \"<% var shown = Math.max( view.views.length, history.contents_active.active ) %>\",\n \"<% if( shown ){ %>\",\n '',\n \"<%- shown %> \",\n _l(\"shown\"),\n \"\",\n \"<% } %>\",\n\n \"<% if( history.contents_active.deleted ){ %>\",\n '',\n \"<% if( view.model.contents.includeDeleted ){ %>\",\n '',\n _l(\"hide deleted\"),\n \"\",\n \"<% } else { %>\",\n \"<%- history.contents_active.deleted %> \",\n '',\n _l(\"deleted\"),\n \"\",\n \"<% } %>\",\n \"\",\n \"<% } %>\",\n\n \"<% if( history.contents_active.hidden ){ %>\",\n '',\n \"<% if( view.model.contents.includeHidden ){ %>\",\n '',\n _l(\"hide hidden\"),\n \"\",\n \"<% } else { %>\",\n \"<%- history.contents_active.hidden %> \",\n '',\n _l(\"hidden\"),\n \"\",\n \"<% } %>\",\n \"\",\n \"<% } %>\"\n ],\n \"history\"\n );\n\n var foundTemplate = BASE_MVC.wrapTemplate(\n [\n _l(\"Found\"),\n \" <%- view.views.length %>, \",\n\n \"<% if( history.contents_active.deleted ){ %>\",\n \"<% if( view.model.contents.includeDeleted ){ %>\",\n '',\n _l(\"hide deleted\"),\n \", \",\n \"<% } else { %>\",\n '',\n _l(\"show deleted\"),\n \", \",\n \"<% } %>\",\n \"<% } %>\",\n\n \"<% if( history.contents_active.hidden ){ %>\",\n \"<% if( view.model.contents.includeHidden ){ %>\",\n '',\n _l(\"hide hidden\"),\n \"\",\n \"<% } else { %>\",\n '',\n _l(\"show hidden\"),\n \"\",\n \"<% } %>\",\n \"<% } %>\"\n ],\n \"history\"\n );\n\n return _.extend(_.clone(_super.prototype.templates), {\n counts: countsTemplate,\n found: foundTemplate\n });\n})();\n\n//==============================================================================\nexport default {\n HistoryViewEdit: HistoryViewEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-view-edit.js","import LIST_VIEW from \"mvc/list/list-view\";\nimport HISTORY_MODEL from \"mvc/history/history-model\";\nimport HISTORY_CONTENTS from \"mvc/history/history-contents\";\nimport HISTORY_PREFS from \"mvc/history/history-preferences\";\nimport HDA_LI from \"mvc/history/hda-li\";\nimport HDCA_LI from \"mvc/history/hdca-li\";\nimport USER from \"mvc/user/user-model\";\nimport ERROR_MODAL from \"mvc/ui/error-modal\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/search-input\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class non-editable, read-only View/Controller for a history model.\n * Allows:\n * changing the loaded history\n * displaying data, info, and download\n * tracking history attrs: size, tags, annotations, name, etc.\n * Does not allow:\n * changing the name\n */\nvar _super = LIST_VIEW.ModelListPanel;\nvar HistoryView = _super.extend(\n /** @lends HistoryView.prototype */ {\n _logNamespace: \"history\",\n\n /** class to use for constructing the HDA views */\n HDAViewClass: HDA_LI.HDAListItemView,\n /** class to use for constructing the HDCA views */\n HDCAViewClass: HDCA_LI.HDCAListItemView,\n /** class to used for constructing collection of sub-view models */\n collectionClass: HISTORY_CONTENTS.HistoryContents,\n /** key of attribute in model to assign to this.collection */\n modelCollectionKey: \"contents\",\n\n tagName: \"div\",\n className: `${_super.prototype.className} history-panel`,\n\n /** string to display when the collection is empty */\n emptyMsg: _l(\"This history is empty\"),\n /** displayed when no items match the search terms */\n noneFoundMsg: _l(\"No matching datasets found\"),\n /** string used for search placeholder */\n searchPlaceholder: _l(\"search datasets\"),\n\n /** @type {Number} ms to wait after history load to fetch/decorate hdcas with element_count */\n FETCH_COLLECTION_COUNTS_DELAY: 2000,\n\n // ......................................................................... SET UP\n /** Set up the view, bind listeners.\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n // ---- instance vars\n // control contents/behavior based on where (and in what context) the panel is being used\n /** where should pages from links be displayed? (default to new tab/window) */\n this.linkTarget = attributes.linkTarget || \"_blank\";\n\n /** timeout id for detailed fetch of collection counts, etc... */\n this.detailedFetchTimeoutId = null;\n },\n\n /** create and return a collection for when none is initially passed */\n _createDefaultCollection: function() {\n // override\n return new this.collectionClass([], {\n history: this.model\n });\n },\n\n /** In this override, clear the update timer on the model */\n freeModel: function() {\n _super.prototype.freeModel.call(this);\n if (this.model) {\n this.model.clearUpdateTimeout();\n }\n this._clearDetailedFetchTimeout();\n return this;\n },\n\n /** clear the timeout and the cached timeout id */\n _clearDetailedFetchTimeout: function() {\n if (this.detailedFetchTimeoutId) {\n clearTimeout(this.detailedFetchTimeoutId);\n this.detailedFetchTimeoutId = null;\n }\n },\n\n /** create any event listeners for the panel\n * @fires: rendered:initial on the first render\n * @fires: empty-history when switching to a history with no contents or creating a new history\n */\n _setUpListeners: function() {\n _super.prototype._setUpListeners.call(this);\n this.on({\n error: function(model, xhr, options, msg, details) {\n this.errorHandler(model, xhr, options, msg, details);\n },\n \"loading-done\": () => {\n // after the initial load, decorate with more time consuming fields (like HDCA element_counts)\n this.detailedFetchTimeoutId = _.delay(() => {\n this.detailedFetchTimeoutId = null;\n this.model.contents.fetchCollectionCounts();\n }, this.FETCH_COLLECTION_COUNTS_DELAY);\n },\n \"views:ready view:attached view:removed\": function(view) {\n this._renderSelectButton();\n },\n \"view:attached\": function(view) {\n this.scrollTo(0);\n }\n });\n // this.on( 'all', function(){ console.debug( arguments ); });\n },\n\n // ------------------------------------------------------------------------ loading history/hda models\n /** load the history with the given id then it's contents, sending ajax options to both */\n loadHistory: function(historyId, options, contentsOptions) {\n contentsOptions = _.extend(contentsOptions || { silent: true });\n this.info(\"loadHistory:\", historyId, options, contentsOptions);\n this.setModel(new HISTORY_MODEL.History({ id: historyId }));\n\n contentsOptions.silent = true;\n this.trigger(\"loading\");\n return this.model.fetchWithContents(options, contentsOptions).always(() => {\n this.render();\n this.trigger(\"loading-done\");\n });\n },\n\n /** convenience alias to the model. Updates the item list only (not the history) */\n refreshContents: function(options) {\n if (this.model) {\n return this.model.refresh(options);\n }\n // may have callbacks - so return an empty promise\n return $.when();\n },\n\n /** Override to reset web storage when the id changes (since it needs the id) */\n _setUpCollectionListeners: function() {\n _super.prototype._setUpCollectionListeners.call(this);\n return this.listenTo(this.collection, {\n // 'all' : function(){ console.log( this.collection + ':', arguments ); },\n \"fetching-more\": function() {\n this._toggleContentsLoadingIndicator(true);\n this.$emptyMessage().hide();\n },\n \"fetching-more-done\": function() {\n this._toggleContentsLoadingIndicator(false);\n }\n });\n },\n\n // ------------------------------------------------------------------------ panel rendering\n /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */\n _showLoadingIndicator: function(msg, speed, callback) {\n var $indicator = $('
');\n this.$el.html($indicator.text(msg).slideDown(!_.isUndefined(speed) ? speed : this.fxSpeed));\n },\n\n /** hide the loading indicator */\n _hideLoadingIndicator: function(speed) {\n // make speed a bit slower to compensate for slow rendering of up to 500 contents\n this.$(\".loading-indicator\").slideUp(!_.isUndefined(speed) ? speed : this.fxSpeed + 200, function() {\n $(this).remove();\n });\n },\n\n /** In this override, add a btn to toggle the selectors */\n _buildNewRender: function() {\n var $newRender = _super.prototype._buildNewRender.call(this);\n this._renderSelectButton($newRender);\n return $newRender;\n },\n\n /** button for starting select mode */\n _renderSelectButton: function($where) {\n $where = $where || this.$el;\n // do not render selector option if no actions\n if (!this.multiselectActions().length) {\n return null;\n }\n // do not render (and remove even) if nothing to select\n if (!this.views.length) {\n this.hideSelectors();\n $where.find(\".controls .actions .show-selectors-btn\").remove();\n return null;\n }\n // don't bother rendering if there's one already\n var $existing = $where.find(\".controls .actions .show-selectors-btn\");\n if ($existing.length) {\n return $existing;\n }\n\n return faIconButton({\n title: _l(\"Operations on multiple datasets\"),\n classes: \"show-selectors-btn\",\n faIcon: \"fa-check-square-o\"\n }).prependTo($where.find(\".controls .actions\"));\n },\n\n /** override to avoid showing intial empty message using contents_active */\n _renderEmptyMessage: function($whereTo) {\n var $emptyMsg = this.$emptyMessage($whereTo);\n var empty = this.model.get(\"contents_active\").active <= 0;\n if (empty) {\n return $emptyMsg\n .empty()\n .append(this.emptyMsg)\n .show();\n } else if (this.searchFor && this.model.contents.haveSearchDetails() && !this.views.length) {\n return $emptyMsg\n .empty()\n .append(this.noneFoundMsg)\n .show();\n }\n $emptyMsg.hide();\n return $();\n },\n\n /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */\n $scrollContainer: function($where) {\n // override or set via attributes.$scrollContainer\n return this.$list($where);\n },\n\n // ------------------------------------------------------------------------ subviews\n _toggleContentsLoadingIndicator: function(show) {\n if (!show) {\n this.$list()\n .find(\".contents-loading-indicator\")\n .remove();\n } else {\n this.$list().html(\n '
' + '
'\n );\n }\n },\n\n /** override to render pagination also */\n renderItems: function($whereTo) {\n // console.log( this + '.renderItems-----------------', new Date() );\n $whereTo = $whereTo || this.$el;\n var $list = this.$list($whereTo);\n\n // TODO: bootstrap hack to remove orphaned tooltips\n $(\".tooltip\").remove();\n\n $list.empty();\n this.views = [];\n\n var models = this._filterCollection();\n if (models.length) {\n this._renderPagination($whereTo);\n this.views = this._renderSomeItems(models, $list);\n } else {\n // TODO: consolidate with _renderPagination above by (???) passing in models/length?\n $whereTo.find(\"> .controls .list-pagination\").empty();\n }\n this._renderEmptyMessage($whereTo).toggle(!models.length);\n\n this.trigger(\"views:ready\", this.views);\n return this.views;\n },\n\n /** render pagination controls if not searching and contents says we're paginating */\n _renderPagination: function($whereTo) {\n var $paginationControls = $whereTo.find(\"> .controls .list-pagination\");\n if (this.searchFor || !this.model.contents.shouldPaginate()) return $paginationControls.empty();\n\n $paginationControls.html(\n this.templates.pagination(\n {\n // pagination is 1-based for the user\n current: this.model.contents.currentPage + 1,\n last: this.model.contents.getLastPage() + 1\n },\n this\n )\n );\n $paginationControls.find(\"select.pages\").tooltip();\n return $paginationControls;\n },\n\n /** render a subset of the entire collection (client-side pagination) */\n _renderSomeItems: function(models, $list) {\n var views = [];\n $list.append(\n models.map(m => {\n var view = this._createItemView(m);\n views.push(view);\n return this._renderItemView$el(view);\n })\n );\n return views;\n },\n\n // ------------------------------------------------------------------------ sub-views\n /** in this override, check if the contents would also display based on includeDeleted/hidden */\n _filterItem: function(model) {\n var contents = this.model.contents;\n return (\n (contents.includeHidden || !model.hidden()) &&\n (contents.includeDeleted || !model.isDeletedOrPurged()) &&\n _super.prototype._filterItem.call(this, model)\n );\n },\n\n /** In this override, since history contents are mixed,\n * get the appropo view class based on history_content_type\n */\n _getItemViewClass: function(model) {\n var contentType = model.get(\"history_content_type\");\n switch (contentType) {\n case \"dataset\":\n return this.HDAViewClass;\n case \"dataset_collection\":\n return this.HDCAViewClass;\n }\n throw new TypeError(`Unknown history_content_type: ${contentType}`);\n },\n\n /** in this override, add a linktarget, and expand if id is in web storage */\n _getItemViewOptions: function(model) {\n var options = _super.prototype._getItemViewOptions.call(this, model);\n return _.extend(options, {\n linkTarget: this.linkTarget,\n expanded: this.model.contents.storage.isExpanded(model.id),\n hasUser: this.model.ownedByCurrUser()\n });\n },\n\n /** In this override, add/remove expanded/collapsed model ids to/from web storage */\n _setUpItemViewListeners: function(view) {\n var panel = this;\n _super.prototype._setUpItemViewListeners.call(panel, view);\n //TODO: send from content view: this.model.collection.storage.addExpanded\n // maintain a list of items whose bodies are expanded\n return panel.listenTo(view, {\n expanded: function(v) {\n panel.model.contents.storage.addExpanded(v.model);\n },\n collapsed: function(v) {\n panel.model.contents.storage.removeExpanded(v.model);\n }\n });\n },\n\n /** override to remove expandedIds from webstorage */\n collapseAll: function() {\n this.model.contents.storage.clearExpanded();\n _super.prototype.collapseAll.call(this);\n },\n\n // ------------------------------------------------------------------------ selection\n /** Override to correctly set the historyId of the new collection */\n getSelectedModels: function() {\n var collection = _super.prototype.getSelectedModels.call(this);\n collection.historyId = this.collection.historyId;\n return collection;\n },\n\n // ------------------------------------------------------------------------ panel events\n /** event map */\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .show-selectors-btn\": \"toggleSelectors\",\n \"click > .controls .prev\": \"_clickPrevPage\",\n \"click > .controls .next\": \"_clickNextPage\",\n \"change > .controls .pages\": \"_changePageSelect\",\n // allow (error) messages to be clicked away\n \"click .messages [class$=message]\": \"clearMessages\"\n }),\n\n _clickPrevPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchPrevPage();\n },\n\n _clickNextPage: function(ev) {\n this.model.clearUpdateTimeout();\n this.model.contents.fetchNextPage();\n },\n\n _changePageSelect: function(ev) {\n this.model.clearUpdateTimeout();\n var page = $(ev.currentTarget).val();\n this.model.contents.fetchPage(page);\n },\n\n /** Toggle and store the deleted visibility and re-render items\n * @returns {Boolean} new setting\n */\n toggleShowDeleted: function(show, options) {\n show = show !== undefined ? show : !this.model.contents.includeDeleted;\n var contents = this.model.contents;\n contents.setIncludeDeleted(show, options);\n this.trigger(\"show-deleted\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** Toggle and store whether to render explicity hidden contents\n * @returns {Boolean} new setting\n */\n toggleShowHidden: function(show, store, options) {\n // console.log( 'toggleShowHidden', show, store );\n show = show !== undefined ? show : !this.model.contents.includeHidden;\n var contents = this.model.contents;\n contents.setIncludeHidden(show, options);\n this.trigger(\"show-hidden\", show);\n\n contents.fetchCurrentPage({ renderAll: true });\n return show;\n },\n\n /** On the first search, if there are no details - load them, then search */\n _firstSearch: function(searchFor) {\n var inputSelector = \"> .controls .search-input\";\n this.log(\"onFirstSearch\", searchFor);\n\n // if the contents already have enough details to search, search and return now\n if (this.model.contents.haveSearchDetails()) {\n this.searchItems(searchFor);\n return;\n }\n\n // otherwise, load the details progressively here\n this.$(inputSelector).searchInput(\"toggle-loading\");\n // set this now so that only results will show during progress\n this.searchFor = searchFor;\n var xhr = this.model.contents\n .progressivelyFetchDetails({ silent: true })\n .progress((response, limit, offset) => {\n this.renderItems();\n this.trigger(\"search:loading-progress\", limit, offset);\n })\n .always(() => {\n this.$el.find(inputSelector).searchInput(\"toggle-loading\");\n })\n .done(() => {\n this.searchItems(searchFor, \"force\");\n });\n },\n\n /** clear the search filters and show all views that are normally shown */\n clearSearch: function(searchFor) {\n if (!this.searchFor) return this;\n //this.log( 'onSearchClear', this );\n this.searchFor = \"\";\n this.trigger(\"search:clear\", this);\n this.$(\"> .controls .search-query\").val(\"\");\n // NOTE: silent + render prevents collection update event with merge only\n // - which causes an empty page due to event handler above\n this.model.contents.fetchCurrentPage({ silent: true }).done(() => {\n this.renderItems();\n });\n return this;\n },\n\n // ........................................................................ error handling\n /** Event handler for errors (from the panel, the history, or the history's contents)\n * Alternately use two strings for model and xhr to use custom message and title (respectively)\n * @param {Model or View} model the (Backbone) source of the error\n * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error\n * @param {Object} options the options map commonly used with bbone ajax\n */\n errorHandler: function(model, xhr, options) {\n //TODO: to mixin or base model\n // interrupted ajax or no connection\n if (xhr && xhr.status === 0 && xhr.readyState === 0) {\n // return ERROR_MODAL.offlineErrorModal();\n // fail silently\n return;\n }\n // otherwise, leave something to report in the console\n this.error(model, xhr, options);\n // and feedback to a modal\n // if sent two strings (and possibly details as 'options'), use those as message and title\n if (_.isString(model) && _.isString(xhr)) {\n var message = model;\n var title = xhr;\n return ERROR_MODAL.errorModal(message, title, options);\n }\n // bad gateway\n // TODO: possibly to global handler\n if (xhr && xhr.status === 502) {\n return ERROR_MODAL.badGatewayErrorModal();\n }\n return ERROR_MODAL.ajaxErrorModal(model, xhr, options);\n },\n\n /** Remove all messages from the panel. */\n clearMessages: function(ev) {\n var $target = !_.isUndefined(ev) ? $(ev.currentTarget) : this.$messages().children('[class$=\"message\"]');\n $target.fadeOut(this.fxSpeed, function() {\n $(this).remove();\n });\n return this;\n },\n\n // ........................................................................ scrolling\n /** Scrolls the panel to show the content sub-view with the given hid.\n * @param {Integer} hid the hid of item to scroll into view\n * @returns {HistoryView} the panel\n */\n scrollToHid: function(hid) {\n return this.scrollToItem(_.first(this.viewsWhereModel({ hid: hid })));\n },\n\n // ........................................................................ misc\n /** utility for adding -st, -nd, -rd, -th to numbers */\n ordinalIndicator: function(number) {\n var numStr = `${number}`;\n switch (numStr.charAt(numStr.length - 1)) {\n case \"1\":\n return `${numStr}st`;\n case \"2\":\n return `${numStr}nd`;\n case \"3\":\n return `${numStr}rd`;\n default:\n return `${numStr}th`;\n }\n },\n\n /** Return a string rep of the history */\n toString: function() {\n return `HistoryView(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//------------------------------------------------------------------------------ TEMPLATES\nHistoryView.prototype.templates = (() => {\n var mainTemplate = () =>\n `
\n \n
\n ',\n
`;\n\n var controlsTemplate = BASE_MVC.wrapTemplate(\n [\n '
\",\n \"<% } %>\"\n ],\n \"dataset\"\n )\n });\n\n return _.extend({}, _super.prototype.templates, {\n //NOTE: *steal* the HDAListItemView titleBar\n titleBar: HDA_LI.HDAListItemView.prototype.templates.titleBar,\n warnings: warnings\n });\n})();\n\n//==============================================================================\nexport default {\n HDAListItemEdit: HDAListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hda-li-edit.js","import HDCA_LI from \"mvc/history/hdca-li\";\nimport DC_VIEW_EDIT from \"mvc/collection/collection-view-edit\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar _super = HDCA_LI.HDCAListItemView;\n/** @class Editing view for HistoryDatasetCollectionAssociation.\n */\nvar HDCAListItemEdit = _super.extend(\n /** @lends HDCAListItemEdit.prototype */ {\n /** logger used to record this.log messages, commonly set to console */\n //logger : console,\n\n /** Override to return editable versions of the collection panels */\n _getFoldoutPanelClass: function() {\n var collectionType = this.model.get(\"collection_type\");\n switch (collectionType) {\n case \"list\":\n return DC_VIEW_EDIT.ListCollectionViewEdit;\n case \"paired\":\n return DC_VIEW_EDIT.PairCollectionViewEdit;\n case \"list:paired\":\n return DC_VIEW_EDIT.ListOfPairsCollectionViewEdit;\n case \"list:list\":\n return DC_VIEW_EDIT.ListOfListsCollectionViewEdit;\n }\n throw new TypeError(`Unknown collection_type: ${collectionType}`);\n },\n\n // ......................................................................... delete\n /** In this override, add the delete button. */\n _renderPrimaryActions: function() {\n this.log(`${this}._renderPrimaryActions`);\n // render the display, edit attr and delete icon-buttons\n return _super.prototype._renderPrimaryActions.call(this).concat([this._renderDeleteButton()]);\n },\n\n /** Render icon-button to delete this collection. */\n _renderDeleteButton: function() {\n var deleted = this.model.get(\"deleted\");\n return faIconButton({\n title: deleted ? _l(\"Dataset collection is already deleted\") : _l(\"Delete\"),\n classes: \"delete-btn\",\n faIcon: \"fa-times\",\n disabled: deleted,\n onclick: () => {\n // ...bler... tooltips being left behind in DOM (hover out never called on deletion)\n this.$el.find(\".icon-btn.delete-btn\").trigger(\"mouseout\");\n this.model[\"delete\"]();\n }\n });\n },\n\n // ......................................................................... misc\n /** string rep */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `HDCAListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n HDCAListItemEdit: HDCAListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/hdca-li-edit.js","import DC_VIEW from \"mvc/collection/collection-view\";\nimport DC_MODEL from \"mvc/collection/collection-model\";\nimport DC_EDIT from \"mvc/collection/collection-li-edit\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport TAGS from \"mvc/tag\";\nimport faIconButton from \"ui/fa-icon-button\";\nimport _l from \"utils/localization\";\nimport \"ui/editable-text\";\n\n/* =============================================================================\nTODO:\n\n============================================================================= */\n/** @class editable View/Controller for a dataset collection.\n */\nvar _super = DC_VIEW.CollectionView;\nvar CollectionViewEdit = _super.extend(\n /** @lends CollectionView.prototype */ {\n //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)\n\n /** logger used to record this.log messages, commonly set to console */\n //logger : console,\n\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_EDIT.DatasetDCEListItemEdit,\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit,\n\n // ......................................................................... SET UP\n /** Set up the view, set up storage, bind listeners to HistoryContents events\n * @param {Object} attributes optional settings for the panel\n */\n initialize: function(attributes) {\n _super.prototype.initialize.call(this, attributes);\n },\n\n /** In this override, make the collection name editable\n */\n _setUpBehaviors: function($where) {\n $where = $where || this.$el;\n _super.prototype._setUpBehaviors.call(this, $where);\n if (!this.model) {\n return;\n }\n\n // anon users shouldn't have access to any of the following\n if (!Galaxy.user || Galaxy.user.isAnonymous()) {\n return;\n }\n\n this.tagsEditorShown = true;\n\n //TODO: extract\n var panel = this;\n\n var nameSelector = \"> .controls .name\";\n $where\n .find(nameSelector)\n .attr(\"title\", _l(\"Click to rename collection\"))\n .tooltip({ placement: \"bottom\" })\n .make_text_editable({\n on_finish: function(newName) {\n var previousName = panel.model.get(\"name\");\n if (newName && newName !== previousName) {\n panel.$el.find(nameSelector).text(newName);\n panel.model.save({ name: newName }).fail(() => {\n panel.$el.find(nameSelector).text(panel.model.previous(\"name\"));\n });\n } else {\n panel.$el.find(nameSelector).text(previousName);\n }\n }\n });\n this.tagsEditor = new TAGS.TagsEditor({\n model: this.model,\n el: $where.find(\".tags-display\"),\n onshowFirstTime: function() {\n this.render();\n },\n usePrompt: false\n });\n this.tagsEditor.toggle(true);\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `CollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class non-editable, read-only View/Controller for a dataset collection. */\nvar ListCollectionViewEdit = CollectionViewEdit.extend(\n /** @lends ListCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for datasets */\n DatasetDCEViewClass: DC_EDIT.DatasetDCEListItemEdit,\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class Editable, read-only View/Controller for a dataset collection. */\nvar PairCollectionViewEdit = ListCollectionViewEdit.extend(\n /** @lends PairCollectionViewEdit.prototype */ {\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `PairCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class Editable (roughly since these collections are immutable),\n * View/Controller for a dataset collection.\n */\nvar NestedPairCollectionViewEdit = PairCollectionViewEdit.extend(\n /** @lends NestedPairCollectionViewEdit.prototype */ {\n /** Override to remove the editable text from the name/identifier - these collections are considered immutable */\n _setUpBehaviors: function($where) {\n _super.prototype._setUpBehaviors.call(this, $where);\n },\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `NestedPairCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class editable, View/Controller for a list of pairs dataset collection. */\nvar ListOfPairsCollectionViewEdit = CollectionViewEdit.extend(\n /** @lends ListOfPairsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit.extend({\n foldoutPanelClass: NestedPairCollectionViewEdit\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfPairsCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n// =============================================================================\n/** @class View/Controller for a list of lists dataset collection. */\nvar ListOfListsCollectionViewEdit = CollectionViewEdit.extend(\n /** @lends ListOfListsCollectionView.prototype */ {\n //TODO: not strictly needed - due to switch in CollectionView._getContentClass\n /** sub view class used for nested collections */\n NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit.extend({\n foldoutPanelClass: NestedPairCollectionViewEdit\n }),\n\n // ........................................................................ misc\n /** string rep */\n toString: function() {\n return `ListOfListsCollectionViewEdit(${this.model ? this.model.get(\"name\") : \"\"})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n CollectionViewEdit: CollectionViewEdit,\n ListCollectionViewEdit: ListCollectionViewEdit,\n PairCollectionViewEdit: PairCollectionViewEdit,\n ListOfPairsCollectionViewEdit: ListOfPairsCollectionViewEdit,\n ListOfListsCollectionViewEdit: ListOfListsCollectionViewEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-view-edit.js","import DC_LI from \"mvc/collection/collection-li\";\nimport DATASET_LI_EDIT from \"mvc/dataset/dataset-li-edit\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\n//==============================================================================\nvar DCListItemView = DC_LI.DCListItemView;\n/** @class Edit view for DatasetCollection.\n */\nvar DCListItemEdit = DCListItemView.extend(\n /** @lends DCListItemEdit.prototype */ {\n /** override to add linkTarget */\n initialize: function(attributes) {\n DCListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DCListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nvar DCEListItemView = DC_LI.DCEListItemView;\n/** @class Read only view for DatasetCollectionElement.\n */\nvar DCEListItemEdit = DCEListItemView.extend(\n /** @lends DCEListItemEdit.prototype */ {\n //TODO: this might be expendable - compacted with HDAListItemView\n\n /** set up */\n initialize: function(attributes) {\n DCEListItemView.prototype.initialize.call(this, attributes);\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DCEListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\n// NOTE: this does not inherit from DatasetDCEListItemView as you would expect\n//TODO: but should - if we can find something simpler than using diamond\n/** @class Editable view for a DatasetCollectionElement that is also an DatasetAssociation\n * (a dataset contained in a dataset collection).\n */\nvar DatasetDCEListItemEdit = DATASET_LI_EDIT.DatasetListItemEdit.extend(\n /** @lends DatasetDCEListItemEdit.prototype */ {\n /** set up */\n initialize: function(attributes) {\n DATASET_LI_EDIT.DatasetListItemEdit.prototype.initialize.call(this, attributes);\n },\n\n // NOTE: this does not inherit from DatasetDCEListItemView - so we duplicate this here\n //TODO: fix\n /** In this override, only get details if in the ready state.\n * Note: fetch with no 'change' event triggering to prevent automatic rendering.\n */\n _fetchModelDetails: function() {\n var view = this;\n if (view.model.inReadyState() && !view.model.hasDetails()) {\n return view.model.fetch({ silent: true });\n }\n return jQuery.when();\n },\n\n /** Override to remove delete button */\n _renderDeleteButton: function() {\n return null;\n },\n\n // ......................................................................... misc\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `DatasetDCEListItemEdit(${modelString})`;\n }\n }\n);\n\n// ............................................................................ TEMPLATES\n/** underscore templates */\nDatasetDCEListItemEdit.prototype.templates = (() =>\n _.extend({}, DATASET_LI_EDIT.DatasetListItemEdit.prototype.templates, {\n titleBar: DC_LI.DatasetDCEListItemView.prototype.templates.titleBar\n }))();\n\n//==============================================================================\n/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection\n * (a nested DC).\n */\nvar NestedDCDCEListItemEdit = DC_LI.NestedDCDCEListItemView.extend(\n /** @lends NestedDCDCEListItemEdit.prototype */ {\n /** String representation */\n toString: function() {\n var modelString = this.model ? `${this.model}` : \"(no model)\";\n return `NestedDCDCEListItemEdit(${modelString})`;\n }\n }\n);\n\n//==============================================================================\nexport default {\n DCListItemEdit: DCListItemEdit,\n DCEListItemEdit: DCEListItemEdit,\n DatasetDCEListItemEdit: DatasetDCEListItemEdit,\n NestedDCDCEListItemEdit: NestedDCDCEListItemEdit\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/collection-li-edit.js","import LIST_CREATOR from \"mvc/collection/list-collection-creator\";\nimport HDCA from \"mvc/history/hdca-model\";\nimport BASE_MVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\n\nvar logNamespace = \"collections\";\n/*==============================================================================\nTODO:\n the paired creator doesn't really mesh with the list creator as parent\n it may be better to make an abstract super class for both\n composites may inherit from this (or vis-versa)\n PairedDatasetCollectionElementView doesn't make a lot of sense\n\n==============================================================================*/\n/** */\nvar PairedDatasetCollectionElementView = Backbone.View.extend(BASE_MVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n //TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))\n tagName: \"li\",\n className: \"collection-element\",\n\n initialize: function(attributes) {\n this.element = attributes.element || {};\n this.identifier = attributes.identifier;\n },\n\n render: function() {\n this.$el.attr(\"data-element-id\", this.element.id).html(\n this.template({\n identifier: this.identifier,\n element: this.element\n })\n );\n return this;\n },\n\n //TODO: lots of unused space in the element - possibly load details and display them horiz.\n template: _.template(\n ['<%- identifier %>', '<%- element.name %>'].join(\"\")\n ),\n\n /** remove the DOM and any listeners */\n destroy: function() {\n this.off();\n this.$el.remove();\n },\n\n /** string rep */\n toString: function() {\n return \"DatasetCollectionElementView()\";\n }\n});\n\n// ============================================================================\nvar _super = LIST_CREATOR.ListCollectionCreator;\n\n/** An interface for building collections.\n */\nvar PairCollectionCreator = _super.extend({\n /** the class used to display individual elements */\n elementViewClass: PairedDatasetCollectionElementView,\n /** the class this creator will create and save */\n collectionClass: HDCA.HistoryPairDatasetCollection,\n className: \"pair-collection-creator collection-creator flex-row-container\",\n\n /** override to no-op */\n _mangleDuplicateNames: function() {},\n\n // TODO: this whole pattern sucks. There needs to be two classes of problem area:\n // bad inital choices and\n // when the user has painted his/her self into a corner during creation/use-of-the-creator\n /** render the entire interface */\n render: function(speed, callback) {\n if (this.workingElements.length === 2) {\n return _super.prototype.render.call(this, speed, callback);\n }\n return this._renderInvalid(speed, callback);\n },\n\n // ------------------------------------------------------------------------ rendering elements\n /** render forward/reverse */\n _renderList: function(speed, callback) {\n //this.debug( '-- _renderList' );\n //precondition: there are two valid elements in workingElements\n var creator = this;\n\n var $tmp = jQuery(\"\");\n var $list = creator.$list();\n\n // lose the original views, create the new, append all at once, then call their renders\n _.each(this.elementViews, view => {\n view.destroy();\n creator.removeElementView(view);\n });\n $tmp.append(creator._createForwardElementView().$el);\n $tmp.append(creator._createReverseElementView().$el);\n $list.empty().append($tmp.children());\n _.invoke(creator.elementViews, \"render\");\n },\n\n /** create the forward element view */\n _createForwardElementView: function() {\n return this._createElementView(this.workingElements[0], {\n identifier: \"forward\"\n });\n },\n\n /** create the forward element view */\n _createReverseElementView: function() {\n return this._createElementView(this.workingElements[1], {\n identifier: \"reverse\"\n });\n },\n\n /** create an element view, cache in elementViews, and return */\n _createElementView: function(element, options) {\n var elementView = new this.elementViewClass(\n _.extend(options, {\n element: element\n })\n );\n this.elementViews.push(elementView);\n return elementView;\n },\n\n /** swap the forward, reverse elements and re-render */\n swap: function() {\n this.workingElements = [this.workingElements[1], this.workingElements[0]];\n this._renderList();\n },\n\n events: _.extend(_.clone(_super.prototype.events), {\n \"click .swap\": \"swap\"\n }),\n\n // ------------------------------------------------------------------------ templates\n //TODO: move to require text plugin and load these as text\n //TODO: underscore currently unnecc. bc no vars are used\n //TODO: better way of localizing text-nodes in long strings\n /** underscore template fns attached to class */\n templates: _.extend(_.clone(_super.prototype.templates), {\n /** the middle: element list */\n middle: _.template(\n [\n '
\",\n _l(\n [\n \"Pair collections are permanent collections containing two datasets: one forward and one reverse. \",\n \"Often these are forward and reverse reads. The pair collections can be passed to tools and \",\n \"workflows in order to have analyses done on both datasets. This interface allows \",\n \"you to create a pair, name it, and swap which is forward and which reverse.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n 'Click the \"Swap\" link to make your forward dataset the reverse ',\n \"and the reverse dataset forward.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(['Click the \"Cancel\" button to exit the interface.'].join(\"\")),\n \"
\",\n \"
\",\n \"
\",\n _l(\n [\n 'Once your collection is complete, enter a name and ',\n 'click \"Create list\".'\n ].join(\"\")\n ),\n \"
\"\n ].join(\"\")\n ),\n\n /** a simplified page communicating what went wrong and why the user needs to reselect something else */\n invalidInitial: _.template(\n [\n '
',\n '
',\n '',\n \"<% if( _.size( problems ) ){ %>\",\n _l(\"The following selections could not be included due to problems\"),\n \"
<% _.each( problems, function( problem ){ %>\",\n \"
<%- problem.element.name %>: <%- problem.text %>
\",\n \"<% }); %>
\",\n \"<% } else if( _.size( elements ) === 0 ){ %>\",\n _l(\"No datasets were selected\"),\n \".\",\n \"<% } else if( _.size( elements ) === 1 ){ %>\",\n _l(\"Only one dataset was selected\"),\n \": <%- elements[0].name %>\",\n \"<% } else if( _.size( elements ) > 2 ){ %>\",\n _l(\"Too many datasets were selected\"),\n ': <%- _.pluck( elements, \"name\" ).join( \", \") %>',\n \"<% } %>\",\n \" \",\n _l(\"Two (and only two) elements are needed for the pair\"),\n \". \",\n _l(\"You may need to \"),\n '',\n _l(\"cancel\"),\n \" \",\n _l(\"and reselect new elements\"),\n \".\",\n \"\",\n \"
\",\n \"
\",\n '\"\n ].join(\"\")\n )\n }),\n\n // ------------------------------------------------------------------------ misc\n /** string rep */\n toString: function() {\n return \"PairCollectionCreator\";\n }\n});\n\n//==============================================================================\n/** List collection flavor of collectionCreatorModal. */\nvar pairCollectionCreatorModal = function _pairCollectionCreatorModal(elements, options) {\n options = options || {};\n options.title = _l(\"Create a collection from a pair of datasets\");\n return LIST_CREATOR.collectionCreatorModal(elements, options, PairCollectionCreator);\n};\n\n//==============================================================================\n/** Use a modal to create a pair collection, then add it to the given history contents.\n * @returns {Deferred} resolved when the collection is added to the history.\n */\nfunction createPairCollection(contents, defaultHideSourceItems) {\n var elements = contents.toJSON();\n\n var promise = pairCollectionCreatorModal(elements, {\n defaultHideSourceItems: defaultHideSourceItems,\n creationFn: function(elements, name, hideSourceItems) {\n elements = [\n { name: \"forward\", src: \"hda\", id: elements[0].id },\n { name: \"reverse\", src: \"hda\", id: elements[1].id }\n ];\n return contents.createHDCA(elements, \"paired\", name, hideSourceItems);\n }\n });\n\n return promise;\n}\n\n//==============================================================================\nexport default {\n PairCollectionCreator: PairCollectionCreator,\n pairCollectionCreatorModal: pairCollectionCreatorModal,\n createPairCollection: createPairCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/pair-collection-creator.js","import levenshteinDistance from \"utils/levenshtein\";\nimport naturalSort from \"utils/natural-sort\";\nimport baseCreator from \"mvc/collection/base-creator\";\nimport baseMVC from \"mvc/base-mvc\";\nimport _l from \"utils/localization\";\nimport \"ui/hoverhighlight\";\n\nvar logNamespace = \"collections\";\n/* ============================================================================\nTODO:\n\n\nPROGRAMMATICALLY:\ncurrPanel.once( 'rendered', function(){\n currPanel.showSelectors();\n currPanel.selectAll();\n _.last( currPanel.actionsPopup.options ).func();\n});\n\n============================================================================ */\n/** A view for paired datasets in the collections creator.\n */\nvar PairView = Backbone.View.extend(baseMVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n tagName: \"li\",\n className: \"dataset paired\",\n\n initialize: function(attributes) {\n this.pair = attributes.pair || {};\n },\n\n template: _.template(\n [\n '<%- pair.forward.name %>',\n '',\n '<%- pair.name %>',\n \"\",\n '<%- pair.reverse.name %>'\n ].join(\"\")\n ),\n\n render: function() {\n this.dragStartHandler = _.bind(this._dragstart, this);\n this.dragEndHandler = _.bind(this._dragend, this);\n var handle = this.$el\n .attr(\"draggable\", true)\n .data(\"pair\", this.pair)\n .html(this.template({ pair: this.pair }))\n .addClass(\"flex-column-container\")\n .get(0);\n handle.addEventListener(\"dragstart\", this.dragStartHandler, false);\n handle.addEventListener(\"dragend\", this.dragEndHandler, false);\n return this;\n },\n\n events: {\n dragover: \"_sendToParent\",\n drop: \"_sendToParent\"\n },\n\n /** dragging pairs for re-ordering */\n _dragstart: function(ev) {\n ev.currentTarget.style.opacity = \"0.4\";\n if (ev.originalEvent) {\n ev = ev.originalEvent;\n }\n\n ev.dataTransfer.effectAllowed = \"move\";\n ev.dataTransfer.setData(\"text/plain\", JSON.stringify(this.pair));\n\n this.$el.parent().trigger(\"pair.dragstart\", [this]);\n },\n\n /** dragging pairs for re-ordering */\n _dragend: function(ev) {\n ev.currentTarget.style.opacity = \"1.0\";\n this.$el.parent().trigger(\"pair.dragend\", [this]);\n },\n\n /** manually bubble up an event to the parent/container */\n _sendToParent: function(ev) {\n this.$el.parent().trigger(ev);\n },\n\n /** string rep */\n toString: function() {\n return `PairView(${this.pair.name})`;\n }\n});\n\n// ============================================================================\n/** returns an autopair function that uses the provided options.match function */\nfunction autoPairFnBuilder(options) {\n options = options || {};\n options.createPair =\n options.createPair ||\n function _defaultCreatePair(params) {\n params = params || {};\n var a = params.listA.splice(params.indexA, 1)[0];\n var b = params.listB.splice(params.indexB, 1)[0];\n var aInBIndex = params.listB.indexOf(a);\n var bInAIndex = params.listA.indexOf(b);\n if (aInBIndex !== -1) {\n params.listB.splice(aInBIndex, 1);\n }\n if (bInAIndex !== -1) {\n params.listA.splice(bInAIndex, 1);\n }\n return this._pair(a, b, { silent: true });\n };\n // compile these here outside of the loop\n var _regexps = [];\n function getRegExps() {\n if (!_regexps.length) {\n _regexps = [new RegExp(this.filters[0]), new RegExp(this.filters[1])];\n }\n return _regexps;\n }\n // mangle params as needed\n options.preprocessMatch =\n options.preprocessMatch ||\n function _defaultPreprocessMatch(params) {\n var regexps = getRegExps.call(this);\n return _.extend(params, {\n matchTo: params.matchTo.name.replace(regexps[0], \"\"),\n possible: params.possible.name.replace(regexps[1], \"\")\n });\n };\n\n return function _strategy(params) {\n this.debug(\"autopair _strategy ---------------------------\");\n params = params || {};\n var listA = params.listA;\n var listB = params.listB;\n var indexA = 0;\n var indexB;\n\n var bestMatch = {\n score: 0.0,\n index: null\n };\n\n var paired = [];\n //console.debug( 'params:', JSON.stringify( params, null, ' ' ) );\n this.debug(\"starting list lens:\", listA.length, listB.length);\n this.debug(\"bestMatch (starting):\", JSON.stringify(bestMatch, null, \" \"));\n\n while (indexA < listA.length) {\n var matchTo = listA[indexA];\n bestMatch.score = 0.0;\n\n for (indexB = 0; indexB < listB.length; indexB++) {\n var possible = listB[indexB];\n this.debug(`${indexA}:${matchTo.name}`);\n this.debug(`${indexB}:${possible.name}`);\n\n // no matching with self\n if (listA[indexA] !== listB[indexB]) {\n bestMatch = options.match.call(\n this,\n options.preprocessMatch.call(this, {\n matchTo: matchTo,\n possible: possible,\n index: indexB,\n bestMatch: bestMatch\n })\n );\n this.debug(\"bestMatch:\", JSON.stringify(bestMatch, null, \" \"));\n if (bestMatch.score === 1.0) {\n this.debug(\"breaking early due to perfect match\");\n break;\n }\n }\n }\n var scoreThreshold = options.scoreThreshold.call(this);\n this.debug(\"scoreThreshold:\", scoreThreshold);\n this.debug(\"bestMatch.score:\", bestMatch.score);\n\n if (bestMatch.score >= scoreThreshold) {\n //console.debug( 'autoPairFnBuilder.strategy', listA[ indexA ].name, listB[ bestMatch.index ].name );\n paired.push(\n options.createPair.call(this, {\n listA: listA,\n indexA: indexA,\n listB: listB,\n indexB: bestMatch.index\n })\n );\n //console.debug( 'list lens now:', listA.length, listB.length );\n } else {\n indexA += 1;\n }\n if (!listA.length || !listB.length) {\n return paired;\n }\n }\n this.debug(\"paired:\", JSON.stringify(paired, null, \" \"));\n this.debug(\"autopair _strategy ---------------------------\");\n return paired;\n };\n}\n\n// ============================================================================\n/** An interface for building collections of paired datasets.\n */\nvar PairedCollectionCreator = Backbone.View.extend(baseMVC.LoggableMixin)\n .extend(baseCreator.CollectionCreatorMixin)\n .extend({\n _logNamespace: logNamespace,\n\n className: \"list-of-pairs-collection-creator collection-creator flex-row-container\",\n\n /** set up initial options, instance vars, behaviors, and autopair (if set to do so) */\n initialize: function(attributes) {\n this.metric(\"PairedCollectionCreator.initialize\", attributes);\n //this.debug( '-- PairedCollectionCreator:', attributes );\n\n attributes = _.defaults(attributes, {\n datasets: [],\n filters: this.DEFAULT_FILTERS,\n automaticallyPair: true,\n strategy: \"lcs\",\n matchPercentage: 0.9,\n twoPassAutopairing: true\n });\n\n /** unordered, original list */\n this.initialList = attributes.datasets;\n\n /** is this from a history? if so, what's its id? */\n this.historyId = attributes.historyId;\n\n /** which filters should be used initially? (String[2] or name in commonFilters) */\n this.filters = this.commonFilters[attributes.filters] || this.commonFilters[this.DEFAULT_FILTERS];\n if (_.isArray(attributes.filters)) {\n this.filters = attributes.filters;\n }\n\n /** try to auto pair the unpaired datasets on load? */\n this.automaticallyPair = attributes.automaticallyPair;\n\n /** what method to use for auto pairing (will be passed aggression level) */\n this.strategy = this.strategies[attributes.strategy] || this.strategies[this.DEFAULT_STRATEGY];\n if (_.isFunction(attributes.strategy)) {\n this.strategy = attributes.strategy;\n }\n\n /** distance/mismatch level allowed for autopairing */\n this.matchPercentage = attributes.matchPercentage;\n\n /** try to autopair using simple first, then this.strategy on the remainder */\n this.twoPassAutopairing = attributes.twoPassAutopairing;\n\n /** remove file extensions (\\.*) from created pair names? */\n this.removeExtensions = true;\n //this.removeExtensions = false;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.oncancel = attributes.oncancel;\n /** fn to call when the collection is created (scoped to this) */\n this.oncreate = attributes.oncreate;\n\n /** fn to call when the cancel button is clicked (scoped to this) - if falsy, no btn is displayed */\n this.autoscrollDist = attributes.autoscrollDist || 24;\n\n /** is the unpaired panel shown? */\n this.unpairedPanelHidden = false;\n /** is the paired panel shown? */\n this.pairedPanelHidden = false;\n\n /** DOM elements currently being dragged */\n this.$dragging = null;\n\n /** Used for blocking UI events during ajax/operations (don't post twice) */\n this.blocking = false;\n\n this._setUpCommonSettings(attributes);\n this._setUpBehaviors();\n this._dataSetUp();\n },\n\n /** map of common filter pairs by name */\n commonFilters: {\n illumina: [\"_1\", \"_2\"],\n Rs: [\"_R1\", \"_R2\"]\n },\n /** which commonFilter to use by default */\n DEFAULT_FILTERS: \"illumina\",\n\n /** map of name->fn for autopairing */\n strategies: {\n simple: \"autopairSimple\",\n lcs: \"autopairLCS\",\n levenshtein: \"autopairLevenshtein\"\n },\n /** default autopair strategy name */\n DEFAULT_STRATEGY: \"lcs\",\n\n // ------------------------------------------------------------------------ process raw list\n /** set up main data: cache initialList, sort, and autopair */\n _dataSetUp: function() {\n //this.debug( '-- _dataSetUp' );\n\n this.paired = [];\n this.unpaired = [];\n\n this.selectedIds = [];\n\n // sort initial list, add ids if needed, and save new working copy to unpaired\n this._sortInitialList();\n this._ensureIds();\n this.unpaired = this.initialList.slice(0);\n\n if (this.automaticallyPair) {\n this.autoPair();\n this.once(\"rendered:initial\", function() {\n this.trigger(\"autopair\");\n });\n }\n },\n\n /** sort initial list */\n _sortInitialList: function() {\n //this.debug( '-- _sortInitialList' );\n this._sortDatasetList(this.initialList);\n },\n\n /** sort a list of datasets */\n _sortDatasetList: function(list) {\n // currently only natural sort by name\n list.sort((a, b) => naturalSort(a.name, b.name));\n return list;\n },\n\n /** add ids to dataset objs in initial list if none */\n _ensureIds: function() {\n this.initialList.forEach(dataset => {\n if (!dataset.hasOwnProperty(\"id\")) {\n dataset.id = _.uniqueId();\n }\n });\n return this.initialList;\n },\n\n /** split initial list into two lists, those that pass forward filters & those passing reverse */\n _splitByFilters: function() {\n var regexFilters = this.filters.map(stringFilter => new RegExp(stringFilter));\n\n var split = [[], []];\n\n function _filter(unpaired, filter) {\n return filter.test(unpaired.name);\n //return dataset.name.indexOf( filter ) >= 0;\n }\n this.unpaired.forEach(function _filterEach(unpaired) {\n // 90% of the time this seems to work, but:\n //TODO: this treats *all* strings as regex which may confuse people - possibly check for // surrounding?\n // would need explanation in help as well\n regexFilters.forEach((filter, i) => {\n if (_filter(unpaired, filter)) {\n split[i].push(unpaired);\n }\n });\n });\n return split;\n },\n\n /** add a dataset to the unpaired list in it's proper order */\n _addToUnpaired: function(dataset) {\n // currently, unpaired is natural sorted by name, use binary search to find insertion point\n var binSearchSortedIndex = (low, hi) => {\n if (low === hi) {\n return low;\n }\n\n var mid = Math.floor((hi - low) / 2) + low;\n\n var compared = naturalSort(dataset.name, this.unpaired[mid].name);\n\n if (compared < 0) {\n return binSearchSortedIndex(low, mid);\n } else if (compared > 0) {\n return binSearchSortedIndex(mid + 1, hi);\n }\n // walk the equal to find the last\n while (this.unpaired[mid] && this.unpaired[mid].name === dataset.name) {\n mid++;\n }\n return mid;\n };\n\n this.unpaired.splice(binSearchSortedIndex(0, this.unpaired.length), 0, dataset);\n },\n\n // ------------------------------------------------------------------------ auto pairing\n /** two passes to automatically create pairs:\n * use both simpleAutoPair, then the fn mentioned in strategy\n */\n autoPair: function(strategy) {\n // split first using exact matching\n var split = this._splitByFilters();\n\n var paired = [];\n if (this.twoPassAutopairing) {\n paired = this.autopairSimple({\n listA: split[0],\n listB: split[1]\n });\n split = this._splitByFilters();\n }\n\n // uncomment to see printlns while running tests\n //this.debug = function(){ console.log.apply( console, arguments ); };\n\n // then try the remainder with something less strict\n strategy = strategy || this.strategy;\n split = this._splitByFilters();\n paired = paired.concat(\n this[strategy].call(this, {\n listA: split[0],\n listB: split[1]\n })\n );\n return paired;\n },\n\n /** autopair by exact match */\n autopairSimple: autoPairFnBuilder({\n scoreThreshold: function() {\n return 0.6;\n },\n match: function _match(params) {\n params = params || {};\n if (params.matchTo === params.possible) {\n return {\n index: params.index,\n score: 1.0\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by levenshtein edit distance scoring */\n autopairLevenshtein: autoPairFnBuilder({\n scoreThreshold: function() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var distance = levenshteinDistance(params.matchTo, params.possible);\n\n var score = 1.0 - distance / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** autopair by longest common substrings scoring */\n autopairLCS: autoPairFnBuilder({\n scoreThreshold: function() {\n return this.matchPercentage;\n },\n match: function _matches(params) {\n params = params || {};\n\n var match = this._naiveStartingAndEndingLCS(params.matchTo, params.possible).length;\n\n var score = match / Math.max(params.matchTo.length, params.possible.length);\n\n if (score > params.bestMatch.score) {\n return {\n index: params.index,\n score: score\n };\n }\n return params.bestMatch;\n }\n }),\n\n /** return the concat'd longest common prefix and suffix from two strings */\n _naiveStartingAndEndingLCS: function(s1, s2) {\n var fwdLCS = \"\";\n var revLCS = \"\";\n var i = 0;\n var j = 0;\n while (i < s1.length && i < s2.length) {\n if (s1[i] !== s2[i]) {\n break;\n }\n fwdLCS += s1[i];\n i += 1;\n }\n if (i === s1.length) {\n return s1;\n }\n if (i === s2.length) {\n return s2;\n }\n\n i = s1.length - 1;\n j = s2.length - 1;\n while (i >= 0 && j >= 0) {\n if (s1[i] !== s2[j]) {\n break;\n }\n revLCS = [s1[i], revLCS].join(\"\");\n i -= 1;\n j -= 1;\n }\n return fwdLCS + revLCS;\n },\n\n // ------------------------------------------------------------------------ pairing / unpairing\n /** create a pair from fwd and rev, removing them from unpaired, and placing the new pair in paired */\n _pair: function(fwd, rev, options) {\n options = options || {};\n this.debug(\"_pair:\", fwd, rev);\n var pair = this._createPair(fwd, rev, options.name);\n this.paired.push(pair);\n this.unpaired = _.without(this.unpaired, fwd, rev);\n if (!options.silent) {\n this.trigger(\"pair:new\", pair);\n }\n return pair;\n },\n\n /** create a pair Object from fwd and rev, adding the name attribute (will guess if not given) */\n _createPair: function(fwd, rev, name) {\n // ensure existance and don't pair something with itself\n if (!(fwd && rev) || fwd === rev) {\n throw new Error(`Bad pairing: ${[JSON.stringify(fwd), JSON.stringify(rev)]}`);\n }\n name = name || this._guessNameForPair(fwd, rev);\n return { forward: fwd, name: name, reverse: rev };\n },\n\n /** try to find a good pair name for the given fwd and rev datasets */\n _guessNameForPair: function(fwd, rev, removeExtensions) {\n removeExtensions = removeExtensions !== undefined ? removeExtensions : this.removeExtensions;\n var fwdName = fwd.name;\n var revName = rev.name;\n\n var lcs = this._naiveStartingAndEndingLCS(\n fwdName.replace(new RegExp(this.filters[0]), \"\"),\n revName.replace(new RegExp(this.filters[1]), \"\")\n );\n\n if (removeExtensions) {\n var lastDotIndex = lcs.lastIndexOf(\".\");\n if (lastDotIndex > 0) {\n var extension = lcs.slice(lastDotIndex, lcs.length);\n lcs = lcs.replace(extension, \"\");\n fwdName = fwdName.replace(extension, \"\");\n revName = revName.replace(extension, \"\");\n }\n }\n return lcs || `${fwdName} & ${revName}`;\n },\n\n /** unpair a pair, removing it from paired, and adding the fwd,rev datasets back into unpaired */\n _unpair: function(pair, options) {\n options = options || {};\n if (!pair) {\n throw new Error(`Bad pair: ${JSON.stringify(pair)}`);\n }\n this.paired = _.without(this.paired, pair);\n this._addToUnpaired(pair.forward);\n this._addToUnpaired(pair.reverse);\n\n if (!options.silent) {\n this.trigger(\"pair:unpair\", [pair]);\n }\n return pair;\n },\n\n /** unpair all paired datasets */\n unpairAll: function() {\n var pairs = [];\n while (this.paired.length) {\n pairs.push(this._unpair(this.paired[0], { silent: true }));\n }\n this.trigger(\"pair:unpair\", pairs);\n },\n\n // ------------------------------------------------------------------------ API\n /** convert a pair into JSON compatible with the collections API */\n _pairToJSON: function(pair, src) {\n src = src || \"hda\";\n //TODO: consider making this the pair structure when created instead\n return {\n collection_type: \"paired\",\n src: \"new_collection\",\n name: pair.name,\n element_identifiers: [\n {\n name: \"forward\",\n id: pair.forward.id,\n src: src\n },\n {\n name: \"reverse\",\n id: pair.reverse.id,\n src: src\n }\n ]\n };\n },\n\n /** create the collection via the API\n * @returns {jQuery.xhr Object} the jquery ajax request\n */\n createList: function(name) {\n var self = this;\n\n var url = `${Galaxy.root}api/histories/${this.historyId}/contents/dataset_collections`;\n\n //TODO: use ListPairedCollection.create()\n var ajaxData = {\n type: \"dataset_collection\",\n collection_type: \"list:paired\",\n hide_source_items: self.hideOriginals || false,\n name: _.escape(name || self.$(\".collection-name\").val()),\n element_identifiers: self.paired.map(pair => self._pairToJSON(pair))\n };\n //this.debug( JSON.stringify( ajaxData ) );\n self.blocking = true;\n return jQuery\n .ajax(url, {\n type: \"POST\",\n contentType: \"application/json\",\n dataType: \"json\",\n data: JSON.stringify(ajaxData)\n })\n .always(() => {\n self.blocking = false;\n })\n .fail((xhr, status, message) => {\n self._ajaxErrHandler(xhr, status, message);\n })\n .done(function(response, message, xhr) {\n //this.info( 'ok', response, message, xhr );\n self.trigger(\"collection:created\", response, message, xhr);\n self.metric(\"collection:created\", response);\n if (typeof self.oncreate === \"function\") {\n self.oncreate.call(this, response, message, xhr);\n }\n });\n },\n\n /** handle ajax errors with feedback and details to the user (if available) */\n _ajaxErrHandler: function(xhr, status, message) {\n this.error(xhr, status, message);\n var self = this;\n var content = _l(\"An error occurred while creating this collection\");\n if (xhr) {\n if (xhr.readyState === 0 && xhr.status === 0) {\n content += `: ${_l(\"Galaxy could not be reached and may be updating.\")}${_l(\n \" Try again in a few minutes.\"\n )}`;\n } else if (xhr.responseJSON) {\n content += `
${JSON.stringify(xhr.responseJSON)}
`;\n } else {\n content += `: ${message}`;\n }\n }\n self._showAlert(content, \"alert-danger\");\n },\n\n // ------------------------------------------------------------------------ rendering\n /** render the entire interface */\n render: function(speed, callback) {\n //this.debug( '-- _render' );\n //this.$el.empty().html( this.templates.main() );\n this.$el.empty().html(this.templates.main());\n this._renderHeader(speed);\n this._renderMiddle(speed);\n this._renderFooter(speed);\n this._addPluginComponents();\n this.trigger(\"rendered\", this);\n return this;\n },\n\n /** render the header section */\n _renderHeader: function(speed, callback) {\n //this.debug( '-- _renderHeader' );\n var $header = this.$(\".header\")\n .empty()\n .html(this.templates.header())\n .find(\".help-content\")\n .prepend($(this.templates.helpContent()));\n\n this._renderFilters();\n return $header;\n },\n /** fill the filter inputs with the filter values */\n _renderFilters: function() {\n return this.$(\".forward-column .column-header input\")\n .val(this.filters[0])\n .add(this.$(\".reverse-column .column-header input\").val(this.filters[1]));\n },\n\n /** render the middle including unpaired and paired sections (which may be hidden) */\n _renderMiddle: function(speed, callback) {\n var $middle = this.$(\".middle\")\n .empty()\n .html(this.templates.middle());\n\n // (re-) hide the un/paired panels based on instance vars\n if (this.unpairedPanelHidden) {\n this.$(\".unpaired-columns\").hide();\n } else if (this.pairedPanelHidden) {\n this.$(\".paired-columns\").hide();\n }\n\n this._renderUnpaired();\n this._renderPaired();\n return $middle;\n },\n /** render the unpaired section, showing datasets accrd. to filters, update the unpaired counts */\n _renderUnpaired: function(speed, callback) {\n //this.debug( '-- _renderUnpaired' );\n var self = this;\n\n var $fwd;\n var $rev;\n var $prd = [];\n var split = this._splitByFilters();\n // update unpaired counts\n this.$(\".forward-column .title\").text([split[0].length, _l(\"unpaired forward\")].join(\" \"));\n this.$(\".forward-column .unpaired-info\").text(\n this._renderUnpairedDisplayStr(this.unpaired.length - split[0].length)\n );\n this.$(\".reverse-column .title\").text([split[1].length, _l(\"unpaired reverse\")].join(\" \"));\n this.$(\".reverse-column .unpaired-info\").text(\n this._renderUnpairedDisplayStr(this.unpaired.length - split[1].length)\n );\n\n this.$(\".unpaired-columns .column-datasets\").empty();\n\n // show/hide the auto pair button if any unpaired are left\n this.$(\".autopair-link\").toggle(this.unpaired.length !== 0);\n if (this.unpaired.length === 0) {\n this._renderUnpairedEmpty();\n return;\n }\n\n // create the dataset dom arrays\n $rev = split[1].map((dataset, i) => {\n // if there'll be a fwd dataset across the way, add a button to pair the row\n if (split[0][i] !== undefined && split[0][i] !== dataset) {\n $prd.push(self._renderPairButton());\n }\n return self._renderUnpairedDataset(dataset);\n });\n $fwd = split[0].map(dataset => self._renderUnpairedDataset(dataset));\n\n if (!$fwd.length && !$rev.length) {\n this._renderUnpairedNotShown();\n return;\n }\n // add to appropo cols\n //TODO: not the best way to render - consider rendering the entire unpaired-columns section in a fragment\n // and swapping out that\n this.$(\".unpaired-columns .forward-column .column-datasets\")\n .append($fwd)\n .add(this.$(\".unpaired-columns .paired-column .column-datasets\").append($prd))\n .add(this.$(\".unpaired-columns .reverse-column .column-datasets\").append($rev));\n this._adjUnpairedOnScrollbar();\n },\n /** return a string to display the count of filtered out datasets */\n _renderUnpairedDisplayStr: function(numFiltered) {\n return [\"(\", numFiltered, \" \", _l(\"filtered out\"), \")\"].join(\"\");\n },\n /** return an unattached jQuery DOM element to represent an unpaired dataset */\n _renderUnpairedDataset: function(dataset) {\n //TODO: to underscore template\n return (\n $(\"\")\n .attr(\"id\", `dataset-${dataset.id}`)\n .addClass(\"dataset unpaired\")\n .attr(\"draggable\", true)\n .addClass(dataset.selected ? \"selected\" : \"\")\n .append(\n $(\"\")\n .addClass(\"dataset-name\")\n .text(dataset.name)\n )\n //??\n .data(\"dataset\", dataset)\n );\n },\n /** render the button that may go between unpaired datasets, allowing the user to pair a row */\n _renderPairButton: function() {\n //TODO: *not* a dataset - don't pretend like it is\n return $(\"\")\n .addClass(\"dataset unpaired\")\n .append(\n $(\"\")\n .addClass(\"dataset-name\")\n .text(_l(\"Pair these datasets\"))\n );\n },\n /** a message to display when no unpaired left */\n _renderUnpairedEmpty: function() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(`(${_l(\"no remaining unpaired datasets\")})`);\n this.$(\".unpaired-columns .paired-column .column-datasets\")\n .empty()\n .prepend($msg);\n return $msg;\n },\n /** a message to display when no unpaired can be shown with the current filters */\n _renderUnpairedNotShown: function() {\n //this.debug( '-- renderUnpairedEmpty' );\n var $msg = $('').text(\n `(${_l(\"no datasets were found matching the current filters\")})`\n );\n this.$(\".unpaired-columns .paired-column .column-datasets\")\n .empty()\n .prepend($msg);\n return $msg;\n },\n /** try to detect if the unpaired section has a scrollbar and adjust left column for better centering of all */\n _adjUnpairedOnScrollbar: function() {\n var $unpairedColumns = this.$(\".unpaired-columns\").last();\n\n var $firstDataset = this.$(\".unpaired-columns .reverse-column .dataset\").first();\n\n if (!$firstDataset.length) {\n return;\n }\n\n var ucRight = $unpairedColumns.offset().left + $unpairedColumns.outerWidth();\n\n var dsRight = $firstDataset.offset().left + $firstDataset.outerWidth();\n\n var rightDiff = Math.floor(ucRight) - Math.floor(dsRight);\n //this.debug( 'rightDiff:', ucRight, '-', dsRight, '=', rightDiff );\n this.$(\".unpaired-columns .forward-column\").css(\"margin-left\", rightDiff > 0 ? rightDiff : 0);\n },\n\n /** render the paired section and update counts of paired datasets */\n _renderPaired: function(speed, callback) {\n //this.debug( '-- _renderPaired' );\n this.$(\".paired-column-title .title\").text([this.paired.length, _l(\"paired\")].join(\" \"));\n // show/hide the unpair all link\n this.$(\".unpair-all-link\").toggle(this.paired.length !== 0);\n if (this.paired.length === 0) {\n this._renderPairedEmpty();\n return;\n //TODO: would be best to return here (the $columns)\n } else {\n // show/hide 'remove extensions link' when any paired and they seem to have extensions\n this.$(\".remove-extensions-link\").show();\n }\n\n this.$(\".paired-columns .column-datasets\").empty();\n var self = this;\n this.paired.forEach((pair, i) => {\n //TODO: cache these?\n var pairView = new PairView({ pair: pair });\n self\n .$(\".paired-columns .column-datasets\")\n .append(pairView.render().$el)\n .append(\n [\n '\"\n ].join(\"\")\n );\n });\n },\n /** a message to display when none paired */\n _renderPairedEmpty: function() {\n var $msg = $('').text(`(${_l(\"no paired datasets yet\")})`);\n this.$(\".paired-columns .column-datasets\")\n .empty()\n .prepend($msg);\n return $msg;\n },\n\n footerSettings: {\n \".hide-originals\": \"hideOriginals\",\n \".remove-extensions\": \"removeExtensions\"\n },\n\n /** add any jQuery/bootstrap/custom plugins to elements rendered */\n _addPluginComponents: function() {\n this._chooseFiltersPopover(\".choose-filters-link\");\n this.$(\".help-content i\").hoverhighlight(\".collection-creator\", \"rgba( 64, 255, 255, 1.0 )\");\n },\n\n /** build a filter selection popover allowing selection of common filter pairs */\n _chooseFiltersPopover: function(selector) {\n function filterChoice(val1, val2) {\n return [\n '\"\n ].join(\"\");\n }\n var $popoverContent = $(\n _.template(\n [\n '
',\n '
',\n _l(\"Choose from the following filters to change which unpaired reads are shown in the display\"),\n \":
\"\n ].join(\"\")\n ),\n\n /** the middle: unpaired, divider, and paired */\n middle: _.template(\n [\n // contains two flex rows (rows that fill available space) and a divider btwn\n '
\",\n _l(\n [\n \"Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). \",\n \"These collections can be passed to tools and workflows in order to have analyses done on each member of \",\n \"the entire group. This interface allows you to create a collection, choose which datasets are paired, \",\n \"and re-order the final collection.\"\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'Unpaired datasets are shown in the unpaired section ',\n \"(hover over the underlined words to highlight below). \",\n 'Paired datasets are shown in the paired section.',\n \"
To pair datasets, you can:\",\n \"
Click a dataset in the \",\n 'forward column ',\n \"to select it then click a dataset in the \",\n 'reverse column.',\n \"
\",\n '
Click one of the \"Pair these datasets\" buttons in the ',\n 'middle column ',\n \"to pair the datasets in a particular row.\",\n \"
\",\n '
Click \"Auto-pair\" ',\n \"to have your datasets automatically paired based on name.\",\n \"
\",\n \"
\"\n ].join(\"\")\n ),\n \"\",\n \"
\",\n _l(\n [\n \"
You can filter what is shown in the unpaired sections by:\",\n \"
Entering partial dataset names in either the \",\n 'forward filter or ',\n 'reverse filter.',\n \"
\",\n \"
Choosing from a list of preset filters by clicking the \",\n '\"Choose filters\" link.',\n \"
Clearing the filters by clicking the \",\n '\"Clear filters\" link.',\n \"
\",\n \"
\"\n ].join(\"\")\n ),\n \"\",\n \"
\",\n _l(\n [\n \"To unpair individual dataset pairs, click the \",\n 'unpair buttons ( ). ',\n 'Click the \"Unpair all\" link to unpair all pairs.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'You can include or remove the file extensions (e.g. \".fastq\") from your pair names by toggling the ',\n '\"Remove file extensions from pair names?\" control.'\n ].join(\"\")\n ),\n \"
\",\n \"
\",\n _l(\n [\n 'Once your collection is complete, enter a name and ',\n 'click \"Create list\". ',\n \"(Note: you do not have to pair all unpaired datasets to finish.)\"\n ].join(\"\")\n ),\n \"
\"\n ].join(\"\")\n )\n })\n });\n\n//=============================================================================\n/** a modal version of the paired collection creator */\nvar pairedCollectionCreatorModal = function _pairedCollectionCreatorModal(datasets, options) {\n var deferred = jQuery.Deferred();\n var creator;\n\n options = _.defaults(options || {}, {\n datasets: datasets,\n oncancel: function() {\n Galaxy.modal.hide();\n deferred.reject(\"cancelled\");\n },\n oncreate: function(creator, response) {\n Galaxy.modal.hide();\n deferred.resolve(response);\n }\n });\n\n if (!window.Galaxy || !Galaxy.modal) {\n throw new Error(\"Galaxy or Galaxy.modal not found\");\n }\n\n creator = new PairedCollectionCreator(options);\n Galaxy.modal.show({\n title: \"Create a collection of paired datasets\",\n body: creator.$el,\n width: \"80%\",\n height: \"800px\",\n closing_events: true\n });\n creator.render();\n window.creator = creator;\n\n //TODO: remove modal header\n return deferred;\n};\n\n//=============================================================================\nfunction createListOfPairsCollection(collection, defaultHideSourceItems) {\n var elements = collection.toJSON();\n //TODO: validate elements\n return pairedCollectionCreatorModal(elements, {\n historyId: collection.historyId,\n defaultHideSourceItems: defaultHideSourceItems\n });\n}\n\n//=============================================================================\nexport default {\n PairedCollectionCreator: PairedCollectionCreator,\n pairedCollectionCreatorModal: pairedCollectionCreatorModal,\n createListOfPairsCollection: createListOfPairsCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js","//=============================================================================\n/**\n(Imported for edit distance algorith. From: https://gist.github.com/andrei-m/982927)\nCopyright (c) 2011 Andrei Mackenzie\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the\nSoftware.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n// Compute the edit distance between the two given strings\n//exports.getEditDistance = function(a, b){\nfunction levenshteinDistance(a, b) {\n if (a.length === 0) {\n return b.length;\n }\n if (b.length === 0) {\n return a.length;\n }\n\n var matrix = [];\n\n // increment along the first column of each row\n var i;\n for (i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n\n // increment each column in the first row\n var j;\n for (j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n\n // Fill in the rest of the matrix\n for (i = 1; i <= b.length; i++) {\n for (j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1, // substitution\n Math.min(\n matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j] + 1\n )\n ); // deletion\n }\n }\n }\n\n //console.debug( '\\t\\t levenshteinDistance', a, b, matrix[b.length][a.length] );\n return matrix[b.length][a.length];\n}\n\n//=============================================================================\nexport default levenshteinDistance;\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/utils/levenshtein.js","/** User Preferences view */\nimport Form from \"mvc/form/form-view\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport QueryStringParsing from \"utils/query-string-parsing\";\n/** Contains descriptive dictionaries describing user forms */\nvar Model = Backbone.Model.extend({\n initialize: function(options) {\n options = options || {};\n options.user_id = options.user_id || Galaxy.user.id;\n this.set({\n user_id: options.user_id,\n information: {\n title: \"Manage information\",\n description: \"Edit your email, addresses and custom parameters or change your username.\",\n url: `api/users/${options.user_id}/information/inputs`,\n icon: \"fa-user\",\n redirect: \"user\"\n },\n password: {\n title: \"Change password\",\n description: \"Allows you to change your login credentials.\",\n icon: \"fa-unlock-alt\",\n url: `api/users/${options.user_id}/password/inputs`,\n submit_title: \"Save password\",\n redirect: \"user\"\n },\n communication: {\n title: \"Change communication settings\",\n description: \"Enable or disable the communication feature to chat with other users.\",\n url: `api/users/${options.user_id}/communication/inputs`,\n icon: \"fa-comments-o\",\n redirect: \"user\"\n },\n permissions: {\n title: \"Set dataset permissions for new histories\",\n description:\n \"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.\",\n url: `api/users/${options.user_id}/permissions/inputs`,\n icon: \"fa-users\",\n submit_title: \"Save permissions\",\n redirect: \"user\"\n },\n api_key: {\n title: \"Manage API key\",\n description: \"Access your current API key or create a new one.\",\n url: `api/users/${options.user_id}/api_key/inputs`,\n icon: \"fa-key\",\n submit_title: \"Create a new key\",\n submit_icon: \"fa-check\"\n },\n toolbox_filters: {\n title: \"Manage Toolbox filters\",\n description: \"Customize your Toolbox by displaying or omitting sets of Tools.\",\n url: `api/users/${options.user_id}/toolbox_filters/inputs`,\n icon: \"fa-filter\",\n submit_title: \"Save filters\",\n redirect: \"user\"\n },\n openids: {\n title: \"Manage OpenIDs\",\n description: \"Associate OpenIDs with your account.\",\n icon: \"fa-openid\",\n onclick: function() {\n window.location.href = `${Galaxy.root}user/openid_manage?cntrller=user&use_panels=True`;\n }\n },\n custom_builds: {\n title: \"Manage custom builds\",\n description: \"Add or remove custom builds using history datasets.\",\n icon: \"fa-cubes\",\n onclick: function() {\n window.location.href = `${Galaxy.root}custom_builds`;\n }\n },\n logout: {\n title: \"Sign out\",\n description: \"Click here to sign out of all sessions.\",\n icon: \"fa-sign-out\",\n onclick: function() {\n Galaxy.modal.show({\n title: \"Sign out\",\n body: \"Do you want to continue and sign out of all active sessions?\",\n buttons: {\n Cancel: function() {\n Galaxy.modal.hide();\n },\n \"Sign out\": function() {\n window.location.href = `${Galaxy.root}user/logout?session_csrf_token=${\n Galaxy.session_csrf_token\n }`;\n }\n }\n });\n }\n }\n });\n }\n});\n\n/** View of the main user preference panel with links to individual user forms */\nvar View = Backbone.View.extend({\n title: \"User Preferences\",\n initialize: function() {\n this.model = new Model();\n this.setElement(\"\");\n this.render();\n },\n\n render: function() {\n var self = this;\n var config = Galaxy.config;\n $.getJSON(`${Galaxy.root}api/users/${Galaxy.user.id}`, data => {\n self.$preferences = $(\"\")\n .addClass(\"ui-panel\")\n .append($(\"\").append(\"User preferences\"))\n .append($(\"\").append(`You are logged in as ${_.escape(data.email)}.`))\n .append((self.$table = $(\"
\").addClass(\"ui-panel-table\")));\n var message = QueryStringParsing.get(\"message\");\n var status = QueryStringParsing.get(\"status\");\n if (message && status) {\n self.$preferences.prepend(new Ui.Message({ message: message, status: status }).$el);\n }\n if (!config.use_remote_user) {\n self._addLink(\"information\");\n self._addLink(\"password\");\n }\n if (config.enable_communication_server) {\n self._addLink(\"communication\");\n }\n self._addLink(\"custom_builds\");\n self._addLink(\"permissions\");\n self._addLink(\"api_key\");\n if (config.has_user_tool_filters) {\n self._addLink(\"toolbox_filters\");\n }\n if (config.enable_openid && !config.use_remote_user) {\n self._addLink(\"openids\");\n }\n if (Galaxy.session_csrf_token) {\n self._addLink(\"logout\");\n }\n self.$preferences.append(self._templateFooter(data));\n self.$el.empty().append(self.$preferences);\n });\n },\n\n _addLink: function(action) {\n var options = this.model.get(action);\n var $row = $(this._templateLink(options));\n var $a = $row.find(\"a\");\n if (options.onclick) {\n $a.on(\"click\", () => {\n options.onclick();\n });\n } else {\n $a.attr(\"href\", `${Galaxy.root}user/${action}`);\n }\n this.$table.append($row);\n },\n\n _templateLink: function(options) {\n return `
You are using ${\n options.nice_total_disk_usage\n } of disk space in this Galaxy instance. ${\n Galaxy.config.enable_quotas ? `Your disk quota is: ${options.quota}. ` : \"\"\n }Is your usage more than expected? See the documentation for tips on how to find all of the data in your account.
`;\n }\n});\n\nexport default {\n View: View,\n Model: Model\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/user/user-preferences.js","/** This class renders the chart configuration form. */\nimport Utils from \"utils/utils\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\nimport Table from \"mvc/ui/ui-table\";\nvar Collection = Backbone.Collection.extend({\n comparator: function(a, b) {\n a = a.get(\"name\");\n b = b.get(\"name\");\n return a > b ? 1 : a < b ? -1 : 0;\n }\n});\n\nvar View = Backbone.View.extend({\n initialize: function(options) {\n var self = this;\n var history_id = Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.model.id;\n this.model = new Backbone.Model();\n this.model.url = `${Galaxy.root}api/histories/${history_id}/custom_builds_metadata`;\n this.collection = new Collection();\n this.collection.url = `${Galaxy.root}api/users/${Galaxy.user.id}/custom_builds`;\n this.message = new Ui.Message({});\n this.installed_builds = new Ui.Select.View({\n optional: true,\n onchange: function() {\n self.installed_builds.value(null);\n },\n empty_text: \"List of available builds:\",\n error_text: \"No system installed builds available.\"\n });\n this.table = new Table.View({ cls: \"grid\", selectable: false });\n this.table.addHeader(\"Name\");\n this.table.addHeader(\"Key\");\n this.table.addHeader(\"Number of chroms/contigs\");\n this.table.addHeader(\"\");\n this.table.appendHeader();\n this.setElement(\n $(\"\")\n .append($(\"\").text(\"Current Custom Builds\"))\n .append(this.table.$el)\n .append(\n (this.$installed = $(\"\")\n .append(\n $(\"\")\n .text(\"System Installed Builds\")\n .addClass(\"ui-margin-top\")\n )\n .append(this.installed_builds.$el))\n )\n .append(\n $(\"\")\n .text(\"Add a Custom Build\")\n .addClass(\"ui-margin-top\")\n )\n .append(\n $(\"\")\n .addClass(\"ui-column\")\n .append(\n $(\"\")\n .addClass(\"ui-column-left\")\n .append(this.message.$el)\n .append((this.$form = $(\"\").addClass(\"ui-margin-top\")))\n )\n .append((this.$help = $(\"\").addClass(\"ui-column-right\")))\n )\n );\n this.listenTo(this.collection, \"add remove reset\", () => {\n self._renderTable();\n });\n this.listenTo(this.model, \"change\", () => {\n self._renderForm();\n });\n this.collection.fetch();\n this.model.fetch();\n },\n\n render: function() {\n this._renderTable();\n this._renderForm();\n },\n\n _renderTable: function() {\n var self = this;\n this.table.delAll();\n this.collection.sort();\n this.collection.each(model => {\n self.table.add(model.get(\"name\"));\n self.table.add(model.id);\n self.table.add(model.get(\"count\") !== undefined ? model.get(\"count\") : \"Processing...\");\n self.table.add(\n new Ui.ButtonIcon({\n icon: \"fa-trash-o\",\n cls: \"ui-button-icon-plain\",\n tooltip: \"Delete custom build.\",\n onclick: function() {\n model.destroy();\n }\n }).$el\n );\n self.table.append(model.id);\n });\n },\n\n _renderForm: function() {\n var self = this;\n var initial_type = \"fasta\";\n var form = new Form({\n inputs: [\n {\n type: \"text\",\n name: \"name\",\n label: \"Name\",\n help: \"Specify a build name e.g. Hamster.\"\n },\n {\n type: \"text\",\n name: \"id\",\n label: \"Key\",\n help: \"Specify a build key e.g. hamster_v1.\"\n },\n {\n name: \"len\",\n type: \"conditional\",\n test_param: {\n name: \"type\",\n label: \"Definition\",\n help: \"Provide the data source.\",\n type: \"select\",\n value: initial_type,\n data: [\n {\n value: \"fasta\",\n label: \"FASTA-file from history\"\n },\n {\n value: \"file\",\n label: \"Len-file from disk\"\n },\n {\n value: \"text\",\n label: \"Len-file by copy/paste\"\n }\n ]\n },\n cases: [\n {\n value: \"fasta\",\n inputs: [\n {\n type: \"select\",\n name: \"value\",\n label: \"FASTA-file\",\n data: this.model.get(\"fasta_hdas\")\n }\n ]\n },\n {\n value: \"file\",\n inputs: [\n {\n type: \"upload\",\n name: \"value\",\n label: \"Len-file\",\n data: this.model.get(\"len_hdas\")\n }\n ]\n },\n {\n value: \"text\",\n inputs: [\n {\n type: \"text\",\n area: true,\n name: \"value\",\n label: \"Edit/Paste\"\n }\n ]\n }\n ]\n }\n ],\n buttons: {\n save: new Ui.Button({\n icon: \"fa-save\",\n tooltip: \"Create new Build\",\n title: \"Save\",\n cls: \"btn btn-primary ui-clear-float\",\n onclick: function() {\n var data = form.data.create();\n if (!data.id || !data.name) {\n self.message.update({\n message: \"All inputs are required.\",\n status: \"danger\"\n });\n } else {\n self.collection.create(data, {\n wait: true,\n success: function(response) {\n if (response.get(\"message\")) {\n self.message.update({\n message: response.get(\"message\"),\n status: \"warning\"\n });\n } else {\n self.message.update({\n message: \"Successfully added a new custom build.\",\n status: \"success\"\n });\n }\n },\n error: function(response, err) {\n var message = err && err.responseJSON && err.responseJSON.err_msg;\n self.message.update({\n message: message || \"Failed to create custom build.\",\n status: \"danger\"\n });\n }\n });\n }\n }\n })\n },\n onchange: function() {\n var input_id = form.data.match(\"len|type\");\n if (input_id) {\n var input_field = form.field_list[input_id];\n self._renderHelp(input_field.value());\n }\n }\n });\n this.$form.empty().append(form.$el);\n var installed_builds = this.model.get(\"installed_builds\");\n if (installed_builds && installed_builds.length) {\n this.$installed.show();\n this.installed_builds.update(this.model.get(\"installed_builds\"));\n } else {\n this.$installed.hide();\n }\n this._renderHelp(initial_type);\n },\n\n _renderHelp: function(len_type) {\n this.$help\n .empty()\n .addClass(\"alert alert-info\")\n .html(len_type == \"fasta\" ? this._templateFasta() : this._templateLen());\n },\n\n _templateLen: function() {\n return (\n \"
Length Format
\" +\n \"
\" +\n \"The length format is two-column, separated by whitespace, of the form:\" +\n \"
chrom/contig length of chrom/contig
\" +\n \"\" +\n \"
\" +\n \"For example, the first few entries of mm9.len are as follows:\" +\n \"
Trackster uses this information to populate the select box for chrom/contig, and\" +\n \"to set the maximum basepair of the track browser. You may either upload a .len file\" +\n \"of this format (Len File option), or directly enter the information into the box \" +\n \"(Len Entry option).
\" +\n \"This is a multi-fasta file from your current history that provides the genome\" +\n \"sequences for each chromosome/contig in your build.\" +\n \"
\" +\n \"
\" +\n \"Here is a snippet from an example multi-fasta file:\" +\n \"
`\n );\n });\n $tmpl.append($table);\n } else {\n $tmpl.append(`No ${this.model.get(\"plural\").toLowerCase()} have been shared with you.`);\n }\n return $tmpl;\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/grid/grid-shared.js","/** Workflow view */\nimport * as mod_toastr from \"libs/toastr\";\nimport TAGS from \"mvc/tag\";\nimport WORKFLOWS from \"mvc/workflow/workflow-model\";\nimport QueryStringParsing from \"utils/query-string-parsing\";\n/** View of the individual workflows */\nvar WorkflowItemView = Backbone.View.extend({\n tagName: \"tr\", // name of (orphan) root tag in this.el\n initialize: function() {\n _.bindAll(\n this,\n \"render\",\n \"_rowTemplate\",\n \"renderTagEditor\",\n \"_templateActions\",\n \"removeWorkflow\",\n \"copyWorkflow\"\n ); // every function that uses 'this' as the current object should be in here\n mod_toastr.options.timeOut = 1500;\n },\n\n events: {\n \"click #show-in-tool-panel\": \"showInToolPanel\",\n \"click #delete-workflow\": \"removeWorkflow\",\n \"click #rename-workflow\": \"renameWorkflow\",\n \"click #copy-workflow\": \"copyWorkflow\"\n },\n\n render: function() {\n $(this.el).html(this._rowTemplate());\n return this;\n },\n\n showInToolPanel: function() {\n this.model.set(\"show_in_tool_panel\", !this.model.get(\"show_in_tool_panel\"));\n this.model.save();\n // This reloads the whole page, so that the workflow appears in the tool panel.\n // Ideally we would notify only the tool panel of a change\n window.location = `${Galaxy.root}workflow`;\n },\n\n removeWorkflow: function() {\n var wfName = this.model.get(\"name\");\n if (window.confirm(`Are you sure you want to delete workflow '${wfName}'?`)) {\n this.model.destroy({\n success: function() {\n mod_toastr.success(`Successfully deleted workflow '${wfName}'`);\n }\n });\n this.remove();\n }\n },\n\n renameWorkflow: function() {\n var oldName = this.model.get(\"name\");\n var newName = window.prompt(`Enter a new Name for workflow '${oldName}'`, oldName);\n if (newName) {\n this.model.save(\n { name: newName },\n {\n success: function() {\n mod_toastr.success(`Successfully renamed workflow '${oldName}' to '${newName}'`);\n }\n }\n );\n this.render();\n }\n },\n\n copyWorkflow: function() {\n var self = this;\n var oldName = this.model.get(\"name\");\n $.getJSON(`${this.model.urlRoot}/${this.model.id}/download`, wfJson => {\n var newName = `Copy of ${oldName}`;\n var currentOwner = self.model.get(\"owner\");\n if (currentOwner != Galaxy.user.attributes.username) {\n newName += ` shared by user ${currentOwner}`;\n }\n wfJson.name = newName;\n self.collection.create(wfJson, {\n at: 0,\n wait: true,\n success: function() {\n mod_toastr.success(`Successfully copied workflow '${oldName}' to '${newName}'`);\n },\n error: function(model, resp, options) {\n // signature seems to have changed over the course of backbone dev\n // see https://github.com/jashkenas/backbone/issues/2606#issuecomment-19289483\n mod_toastr.error(options.errorThrown);\n }\n });\n }).error((jqXHR, textStatus, errorThrown) => {\n mod_toastr.error(jqXHR.responseJSON.err_msg);\n });\n },\n\n _rowTemplate: function() {\n var show = this.model.get(\"show_in_tool_panel\");\n var wfId = this.model.id;\n var checkboxHtml = ``;\n var trHtml = `
Click the link above to visit myExperiment and browse for Galaxy workflows.
`;\n }\n});\n\nexport default {\n View: WorkflowListView,\n ImportWorkflowView: ImportWorkflowView\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/workflow/workflow.js","import baseMVC from \"mvc/base-mvc\";\n/* global Backbone */\n// workflow model\n\nvar logNamespace = \"workflow\";\n//==============================================================================\n/** @class model for a single workflow.\n * @name WorkflowItem\n * @augments Backbone.Model\n */\nvar WorkflowItem = Backbone.Model.extend(baseMVC.LoggableMixin).extend({\n _logNamespace: logNamespace,\n\n urlRoot: `${Galaxy.root}api/workflows`,\n\n toJSON: function() {\n // need to overwrite this as endpoint expects the 'workflow' key in payload\n return { workflow: this.attributes };\n }\n});\n\n//==============================================================================\n/** @class collection for workflows.\n * @name WorkflowCollection\n * @augments Backbone.Collection\n */\nvar WorkflowCollection = Backbone.Collection.extend({\n model: WorkflowItem,\n url: `${Galaxy.root}api/workflows`\n});\n\n//==============================================================================\n\nexport default {\n WorkflowItem: WorkflowItem,\n WorkflowCollection: WorkflowCollection\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/workflow/workflow-model.js","/** This class renders the grid list. */\nimport Utils from \"utils/utils\";\nimport GridView from \"mvc/grid/grid-view\";\nimport HistoryModel from \"mvc/history/history-model\";\nimport historyCopyDialog from \"mvc/history/copy-dialog\";\nvar View = Backbone.View.extend({\n title: \"Histories\",\n initialize: function(options) {\n var self = this;\n this.setElement($(\"\"));\n this.model = new Backbone.Model();\n Utils.get({\n url: `${Galaxy.root}history/${options.action_id}?${$.param(Galaxy.params)}`,\n success: function(response) {\n response[\"dict_format\"] = true;\n _.each(response[\"operations\"], operation => {\n if (operation.label == \"Copy\") {\n operation.onclick = id => {\n self._showCopyDialog(id);\n };\n }\n });\n self.model.set(response);\n self.render();\n }\n });\n },\n\n render: function() {\n var grid = new GridView(this.model.attributes);\n this.$el.empty().append(grid.$el);\n },\n\n _showCopyDialog: function(id) {\n var history = new HistoryModel.History({ id: id });\n history\n .fetch()\n .fail(() => {\n alert(\"History could not be fetched. Please contact an administrator\");\n })\n .done(() => {\n historyCopyDialog(history, {}).done(() => {\n if (window.parent && window.parent.Galaxy && window.parent.Galaxy.currHistoryPanel) {\n window.parent.Galaxy.currHistoryPanel.loadCurrentHistory();\n }\n window.location.reload(true);\n });\n });\n }\n});\n\nexport default {\n View: View\n};\n\n\n\n// WEBPACK FOOTER //\n// ./galaxy/scripts/mvc/history/history-list.js","import Utils from \"utils/utils\";\nimport Ui from \"mvc/ui/ui-misc\";\nimport Form from \"mvc/form/form-view\";\n/** Dataset edit attributes view */\nvar View = Backbone.View.extend({\n initialize: function() {\n this.setElement(\"\");\n this.model = new Backbone.Model({\n dataset_id: Galaxy.params.dataset_id\n });\n this.render();\n },\n\n // Fetch data for the selected dataset and\n render: function() {\n var data_url = `${Galaxy.root}api/datasets/${this.model.get(\"dataset_id\")}`;\n\n var self = this;\n\n Utils.get({\n url: data_url,\n success: function(dataset) {\n var job_url = `${Galaxy.root}api/jobs/${dataset.creating_job}?full=True`;\n Utils.get({\n url: job_url,\n success: function(job) {\n var job_url = `${Galaxy.root}api/jobs/${dataset.creating_job}?full=True`;\n self.render_error_page(self, dataset, job);\n },\n error: function(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the job.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n error: function(response) {\n var error_response = {\n status: \"error\",\n message: \"Error occured while loading the dataset.\",\n persistent: true,\n cls: \"errormessage\"\n };\n self.display_message(error_response, self.$(\".response-message\"));\n }\n });\n },\n\n /** Render the view */\n render_error_page: function(self, dataset, job) {\n self.$el.empty().append(self._templateHeader());\n self.$el.append(\"
Dataset Error
\");\n self.$el.append(`
An error occured while running the tool ${job.tool_id}.
`);\n self.$el.append(\"
Tool execution generated the following messages:
\");\n self.$el.append(`
${job.stderr}
`);\n self.$el.append(\"
Report This Error\");\n self.$el.append(\n \"
Usually the local Galaxy administrators regularly review errors that occur on the server. However, if you would like to provide additional information (such as what you were trying to do when the error occurred) and a contact e-mail address, we will be better able to investigate your problem and get back to you.