",
- ],
- "collection"
- );
-
- return _.extend({}, FoldoutListItemView.prototype.templates, {
- warnings: warnings,
- titleBar: titleBarTemplate,
- subtitle: subtitleTemplate,
- });
-})();
-
-//==============================================================================
-/** @class Read only view for DatasetCollectionElement.
- */
-var DCEListItemView = ListItemView.extend(
- /** @lends DCEListItemView.prototype */ {
- /** add the DCE class to the list item */
- className: `${ListItemView.prototype.className} dataset-collection-element`,
-
- /** set up */
- initialize: function (attributes) {
- if (attributes.logger) {
- this.logger = this.model.logger = attributes.logger;
- }
- this.log("DCEListItemView.initialize:", attributes);
- ListItemView.prototype.initialize.call(this, attributes);
- },
-
- // ......................................................................... misc
- /** String representation */
- toString: function () {
- var modelString = this.model ? `${this.model}` : "(no model)";
- return `DCEListItemView(${modelString})`;
- },
- }
-);
-
-// ............................................................................ TEMPLATES
-/** underscore templates */
-DCEListItemView.prototype.templates = (() => {
- // use the element identifier here - since that will persist and the user will need it
- var titleBarTemplate = BASE_MVC.wrapTemplate(
- [
- '
',
- '
',
- '<%- element.element_identifier %>',
- "
",
- '',
- "
",
- ],
- "element"
- );
-
- return _.extend({}, ListItemView.prototype.templates, {
- titleBar: titleBarTemplate,
- });
-})();
-
-//==============================================================================
-/** @class Read only view for a DatasetCollectionElement that is also an DatasetAssociation
- * (a dataset contained in a dataset collection).
- */
-var DatasetDCEListItemView = DatasetListItemView.extend(
- /** @lends DatasetDCEListItemView.prototype */ {
- className: `${DatasetListItemView.prototype.className} dataset-collection-element`,
-
- /** set up */
- initialize: function (attributes) {
- if (attributes.logger) {
- this.logger = this.model.logger = attributes.logger;
- }
- this.log("DatasetDCEListItemView.initialize:", attributes);
- DatasetListItemView.prototype.initialize.call(this, attributes);
- },
-
- /** In this override, only get details if in the ready state.
- * Note: fetch with no 'change' event triggering to prevent automatic rendering.
- */
- _fetchModelDetails: function () {
- var view = this;
- if (view.model.inReadyState() && !view.model.hasDetails()) {
- return view.model.fetch({ silent: true });
- }
- return $.when();
- },
-
- // ......................................................................... misc
- /** String representation */
- toString: function () {
- var modelString = this.model ? `${this.model}` : "(no model)";
- return `DatasetDCEListItemView(${modelString})`;
- },
- }
-);
-
-// ............................................................................ TEMPLATES
-/** underscore templates */
-DatasetDCEListItemView.prototype.templates = (() => {
- // use the element identifier here and not the dataset name
- //TODO:?? can we steal the DCE titlebar?
- var titleBarTemplate = BASE_MVC.wrapTemplate(
- [
- '
',
- '',
- '
',
- '<%- element.element_identifier %>',
- "
",
- "
",
- ],
- "element"
- );
-
- return _.extend({}, DatasetListItemView.prototype.templates, {
- titleBar: titleBarTemplate,
- });
-})();
-
-//==============================================================================
-/** @class Read only view for a DatasetCollectionElement that is also a DatasetCollection
- * (a nested DC).
- */
-var NestedDCDCEListItemView = DCListItemView.extend(
- /** @lends NestedDCDCEListItemView.prototype */ {
- className: `${DCListItemView.prototype.className} dataset-collection-element`,
-
- /** In this override, add the state as a class for use with state-based CSS */
- _swapNewRender: function ($newRender) {
- DCListItemView.prototype._swapNewRender.call(this, $newRender);
- var state = this.model.get("state") || "ok";
- this.$el.addClass(`state-${state}`);
- this.$el.attr("data-state", state);
- return this.$el;
- },
-
- // ......................................................................... misc
- /** String representation */
- toString: function () {
- var modelString = this.model ? `${this.model}` : "(no model)";
- return `NestedDCDCEListItemView(${modelString})`;
- },
- }
-);
-
-//==============================================================================
-export default {
- DCListItemView: DCListItemView,
- DCEListItemView: DCEListItemView,
- DatasetDCEListItemView: DatasetDCEListItemView,
- NestedDCDCEListItemView: NestedDCDCEListItemView,
-};
diff --git a/client/src/mvc/collection/collection-model.js b/client/src/mvc/collection/collection-model.js
deleted file mode 100644
index 8c70bf2ce79..00000000000
--- a/client/src/mvc/collection/collection-model.js
+++ /dev/null
@@ -1,396 +0,0 @@
-import $ from "jquery";
-import _ from "underscore";
-import Backbone from "backbone";
-import { getAppRoot } from "onload/loadConfig";
-import DATASET_MODEL from "mvc/dataset/dataset-model";
-import BASE_MVC from "mvc/base-mvc";
-import Utils from "utils/utils";
-
-//==============================================================================
-/*
-Notes:
-
-Terminology:
- DatasetCollection/DC : a container of datasets or nested DatasetCollections
- Element/DatasetCollectionElement/DCE : an item contained in a DatasetCollection
- HistoryDatasetCollectionAssociation/HDCA: a DatasetCollection contained in a history
-
-
-This all seems too complex unfortunately:
-
-- Terminology collision between DatasetCollections (DCs) and Backbone Collections.
-- In the DatasetCollections API JSON, DC Elements use a 'Has A' stucture to *contain*
- either a dataset or a nested DC. This would make the hierarchy much taller. I've
- decided to merge the contained JSON with the DC element json - making the 'has a'
- relation into an 'is a' relation. This seems simpler to me and allowed a lot of
- DRY in both models and views, but may make tracking or tracing within these models
- more difficult (since DatasetCollectionElements are now *also* DatasetAssociations
- or DatasetCollections (nested)). This also violates the rule of thumb about
- favoring aggregation over inheritance.
-- Currently, there are three DatasetCollection subclasses: List, Pair, and ListPaired.
- These each should a) be usable on their own, b) be usable in the context of
- nesting within a collection model (at least in the case of ListPaired), and
- c) be usable within the context of other container models (like History or
- LibraryFolder, etc.). I've tried to separate/extract classes in order to
- handle those three situations, but it's proven difficult to do in a simple,
- readable manner.
-- Ideally, histories and libraries would inherit from the same server models as
- dataset collections do since they are (in essence) dataset collections themselves -
- making the whole nested structure simpler. This would be a large, error-prone
- refactoring and migration.
-
-Many of the classes and heirarchy are meant as extension points so, while the
-relations and flow may be difficult to understand initially, they'll allow us to
-handle the growth or flux dataset collection in the future (w/o actually implementing
-any YAGNI).
-
-*/
-//_________________________________________________________________________________________________ ELEMENTS
-/** @class mixin for Dataset collection elements.
- * When collection elements are passed from the API, the underlying element is
- * in a sub-object 'object' (IOW, a DCE representing an HDA will have HDA json in element.object).
- * This mixin uses the constructor and parse methods to merge that JSON with the DCE attribtues
- * effectively changing a DCE from a container to a subclass (has a --> is a).
- */
-var DatasetCollectionElementMixin = {
- /** default attributes used by elements in a dataset collection */
- defaults: {
- model_class: "DatasetCollectionElement",
- element_identifier: null,
- element_index: null,
- element_type: null,
- },
-
- /** merge the attributes of the sub-object 'object' into this model */
- _mergeObject: function (attributes) {
- // Don't let the dataset ID replace the DCE's ID so record it as the
- // element_id and when fetching dataset details below use the element_id
- // instead of this.id.
- const object = attributes.object;
- let elementId = this.elementId;
- if (object) {
- elementId = attributes.object.id;
- delete attributes.object.id;
- }
- _.extend(attributes, attributes.object, {
- element_id: elementId,
- });
- delete attributes.object;
- return attributes;
- },
-
- /** override to merge this.object into this */
- constructor: function (attributes, options) {
- // console.debug( '\t DatasetCollectionElement.constructor:', attributes, options );
- attributes = this._mergeObject(attributes);
- this.idAttribute = "element_id";
- Backbone.Model.apply(this, arguments);
- },
-
- /** when the model is fetched, merge this.object into this */
- parse: function (response, options) {
- var attributes = response;
- attributes = this._mergeObject(attributes);
- return attributes;
- },
-};
-
-/** @class Concrete class of Generic DatasetCollectionElement */
-var DatasetCollectionElement = Backbone.Model.extend(BASE_MVC.LoggableMixin)
- .extend(DatasetCollectionElementMixin)
- .extend({ _logNamespace: "collections" });
-
-//==============================================================================
-/** @class Base/Abstract Backbone collection for Generic DCEs -
- current may be associated with a dataset (DatasetDCECollection)
- or another collection (NestedDCDCECollection).
-*/
-var DCECollection = Backbone.Collection.extend(BASE_MVC.LoggableMixin).extend(
- /** @lends DCECollection.prototype */ {
- _logNamespace: "collections",
-
- model: DatasetCollectionElement,
-
- /** String representation. */
- toString: function () {
- return ["DatasetCollectionElementCollection(", this.length, ")"].join("");
- },
- }
-);
-
-//==============================================================================
-/** @class Backbone model for a dataset collection element that is a dataset (HDA).
- */
-var DatasetDCE = DATASET_MODEL.DatasetAssociation.extend(
- BASE_MVC.mixin(
- DatasetCollectionElementMixin,
- /** @lends DatasetDCE.prototype */ {
- /** url fn */
- url: function () {
- // won't always be an hda
- if (!this.has("history_id")) {
- console.warn("no endpoint for non-hdas within a collection yet");
- // (a little silly since this api endpoint *also* points at hdas)
- return `${getAppRoot()}api/datasets`;
- }
- const datasetId = this._getDatasetId();
- return `${getAppRoot()}api/histories/${this.get("history_id")}/contents/${datasetId}`;
- },
-
- _getDatasetId: function () {
- // I'm a DCE acting as dataset, this URL needs to be the dataset URL so
- // use element_id instead of id. See note above in _mergeObject and
- // discussion on #3782 for more context.
- return this.get("element_id");
- },
-
- defaults: _.extend(
- {},
- DATASET_MODEL.DatasetAssociation.prototype.defaults,
- DatasetCollectionElementMixin.defaults
- ),
-
- _downloadQueryParameters: function () {
- // Setting the file extension to just 'data' defers that
- // decision to the serverside, setting based on the datatype.
- var fileExt = this.get("file_ext") || "data";
- var elementIdentifier = this.get("element_identifier");
- var parentHdcaId = this.get("parent_hdca_id");
- return `?to_ext=${fileExt}&hdca_id=${parentHdcaId}&element_identifier=${elementIdentifier}`;
- },
-
- // because all objects have constructors (as this hashmap would even if this next line wasn't present)
- // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model
- // - re-apply manually for now
- /** call the mixin constructor */
- constructor: function (attributes, options) {
- this.debug("\t DatasetDCE.constructor:", attributes, options);
- //DATASET_MODEL.DatasetAssociation.prototype.constructor.call( this, attributes, options );
- DatasetCollectionElementMixin.constructor.call(this, attributes, options);
- },
-
- /** Does this model already contain detailed data (as opposed to just summary level data)? */
- hasDetails: function () {
- return this.elements && this.elements.length;
- },
-
- /** String representation. */
- toString: function () {
- var objStr = this.get("element_identifier");
- return `DatasetDCE(${objStr})`;
- },
- }
- )
-);
-
-//==============================================================================
-/** @class DCECollection of DatasetDCE's (a list of datasets, a pair of datasets).
- */
-var DatasetDCECollection = DCECollection.extend(
- /** @lends DatasetDCECollection.prototype */ {
- model: DatasetDCE,
-
- /** String representation. */
- toString: function () {
- return ["DatasetDCECollection(", this.length, ")"].join("");
- },
- }
-);
-
-//_________________________________________________________________________________________________ COLLECTIONS
-/** @class Backbone model for Dataset Collections.
- * The DC API returns an array of JSON objects under the attribute elements.
- * This model:
- * - removes that array/attribute ('elements') from the model,
- * - creates a bbone collection (of the class defined in the 'collectionClass' attribute),
- * - passes that json onto the bbone collection
- * - caches the bbone collection in this.elements
- */
-var DatasetCollection = Backbone.Model.extend(BASE_MVC.LoggableMixin)
- .extend(BASE_MVC.SearchableModelMixin)
- .extend(
- /** @lends DatasetCollection.prototype */ {
- _logNamespace: "collections",
-
- /** default attributes for a model */
- defaults: {
- /* 'list', 'paired', or 'list:paired' */
- collection_type: null,
- //??
- deleted: false,
- },
-
- /** Which class to use for elements */
- collectionClass: function () {
- if (this.attributes.collection_type.indexOf(":") > 0) {
- return NestedDCDCECollection;
- } else {
- return DatasetDCECollection;
- }
- },
-
- /** set up: create elements instance var and (on changes to elements) update them */
- initialize: function (model, options) {
- this.debug(`${this}(DatasetCollection).initialize:`, model, options, this);
- this.elements = this._createElementsModel();
- this.on("change:elements", function () {
- this.log("change:elements");
- //TODO: prob. better to update the collection instead of re-creating it
- this.elements = this._createElementsModel();
- });
- },
-
- /** move elements model attribute to full collection */
- _createElementsModel: function () {
- var collectionClass = this.collectionClass();
- this.debug(`${this}._createElementsModel`, collectionClass, this.get("elements"), this.elements);
- //TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?
- var elements = this.get("elements") || [];
- this.unset("elements", { silent: true });
- var parentHdcaId = this.get("parent_hdca_id") || this.get("id");
- _.each(elements, (element, index) => {
- _.extend(element, {
- parent_hdca_id: parentHdcaId,
- });
-
- // Warning: MEGA-hack ahead...
- if (!element.element_type && !element.object) {
- // The DCE has to be in error state... so we simulate it
- _.extend(element, {
- element_type: "hda",
- object: { state: "error" },
- });
- }
- });
- this.elements = new collectionClass(elements);
- //this.debug( 'collectionClass:', this.collectionClass + '', this.elements );
- return this.elements;
- },
-
- // ........................................................................ common queries
- /** pass the elements back within the model json when this is serialized */
- toJSON: function () {
- var json = Backbone.Model.prototype.toJSON.call(this);
- if (this.elements) {
- json.elements = this.elements.toJSON();
- }
- return json;
- },
-
- /** Is this collection in a 'ready' state no processing (for the collection) is left
- * to do on the server.
- */
- inReadyState: function () {
- var populated = this.get("populated");
- return this.isDeletedOrPurged() || populated;
- },
-
- //TODO:?? the following are the same interface as DatasetAssociation - can we combine?
- /** Does the DC contain any elements yet? Is a fetch() required? */
- hasDetails: function () {
- return this.elements.length !== 0;
- },
-
- /** Given the filters, what models in this.elements would be returned? */
- getVisibleContents: function (filters) {
- // filters unused for now
- return this.elements;
- },
-
- // ........................................................................ ajax
- /** override to use actual Dates objects for create/update times */
- parse: function (response, options) {
- var parsed = Backbone.Model.prototype.parse.call(this, response, options);
- if (parsed.create_time) {
- parsed.create_time = new Date(parsed.create_time);
- }
- if (parsed.update_time) {
- parsed.update_time = new Date(parsed.update_time);
- }
- return parsed;
- },
-
- /** save this collection, _Mark_ing it as deleted (just a flag) */
- delete: function (recursive, purge, options) {
- recursive = recursive || false;
- purge = purge || false;
- if (this.get("deleted")) {
- return $.when();
- }
- options = Utils.merge(options, { method: "delete" });
- return this.save({ deleted: true, recursive: recursive, purge: purge }, options);
- },
- /** save this collection, _Mark_ing it as undeleted */
- undelete: function (options) {
- if (!this.get("deleted")) {
- return $.when();
- }
- return this.save({ deleted: false }, options);
- },
-
- /** Is this collection deleted or purged? */
- isDeletedOrPurged: function () {
- return this.get("deleted") || this.get("purged");
- },
-
- // ........................................................................ searchable
- /** searchable attributes for collections */
- searchAttributes: ["name", "tags"],
-
- // ........................................................................ misc
- /** String representation */
- toString: function () {
- var idAndName = [this.get("id"), this.get("name") || this.get("element_identifier")];
- return `DatasetCollection(${idAndName.join(",")})`;
- },
- }
- );
-
-//_________________________________________________________________________________________________ NESTED COLLECTIONS
-// this is where things get weird, man. Weird.
-//TODO: it might be possible to compact all the following...I think.
-//==============================================================================
-/** @class Backbone model for a Generic DatasetCollectionElement that is also a DatasetCollection
- * (a nested collection).
- */
-var NestedDCDCE = DatasetCollection.extend(
- BASE_MVC.mixin(
- DatasetCollectionElementMixin,
- /** @lends NestedDCDCE.prototype */ {
- // because all objects have constructors (as this hashmap would even if this next line wasn't present)
- // the constructor in hcontentMixin won't be attached by BASE_MVC.mixin to this model
- // - re-apply manually it now
- /** call the mixin constructor */
- constructor: function (attributes, options) {
- this.debug("\t NestedDCDCE.constructor:", attributes, options);
- DatasetCollectionElementMixin.constructor.call(this, attributes, options);
- },
-
- /** String representation. */
- toString: function () {
- var objStr = this.object ? `${this.object}` : this.get("element_identifier");
- return ["NestedDCDCE(", objStr, ")"].join("");
- },
- }
- )
-);
-
-//==============================================================================
-/** @class Backbone collection containing Generic NestedDCDCE's (nested dataset collections).
- */
-var NestedDCDCECollection = DCECollection.extend(
- /** @lends NestedDCDCECollection.prototype */ {
- /** This is a collection of nested collections */
- model: NestedDCDCE,
-
- /** String representation. */
- toString: function () {
- return ["NestedDCDCECollection(", this.length, ")"].join("");
- },
- }
-);
-
-//==============================================================================
-export default {
- DatasetCollection: DatasetCollection,
-};
diff --git a/client/src/mvc/collection/collection-view-edit.js b/client/src/mvc/collection/collection-view-edit.js
deleted file mode 100644
index b07e77ec503..00000000000
--- a/client/src/mvc/collection/collection-view-edit.js
+++ /dev/null
@@ -1,114 +0,0 @@
-import $ from "jquery";
-import { getGalaxyInstance } from "app";
-import DC_VIEW from "mvc/collection/collection-view";
-import DC_EDIT from "mvc/collection/collection-li-edit";
-import { mountModelTags } from "components/Tags";
-import _l from "utils/localization";
-import "ui/editable-text";
-
-/* =============================================================================
-TODO:
-
-============================================================================= */
-/** @class editable View/Controller for a dataset collection.
- */
-var _super = DC_VIEW.CollectionView;
-var CollectionViewEdit = _super.extend(
- /** @lends CollectionView.prototype */ {
- //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)
-
- /** logger used to record this.log messages, commonly set to console */
- //logger : console,
-
- /** sub view class used for datasets */
- DatasetDCEViewClass: DC_EDIT.DatasetDCEListItemEdit,
- /** sub view class used for nested collections */
- NestedDCDCEViewClass: DC_EDIT.NestedDCDCEListItemEdit,
-
- getNestedDCDCEViewClass: function () {
- return DC_EDIT.NestedDCDCEListItemEdit.extend({
- foldoutPanelClass: CollectionViewEdit,
- });
- },
-
- // ......................................................................... SET UP
- /** Set up the view, set up storage, bind listeners to HistoryContents events
- * @param {Object} attributes optional settings for the panel
- */
- initialize: function (attributes) {
- _super.prototype.initialize.call(this, attributes);
- },
-
- /** In this override, make the collection name editable
- */
- _setUpBehaviors: function ($where) {
- $where = $where || this.$el;
- _super.prototype._setUpBehaviors.call(this, $where);
- if (!this.model) {
- return;
- }
-
- // anon users shouldn't have access to any of the following
- const Galaxy = getGalaxyInstance();
- if (!Galaxy.user || Galaxy.user.isAnonymous()) {
- return;
- }
-
- this.tagsEditorShown = true;
-
- //TODO: extract
- var panel = this;
-
- var nameSelector = "> .controls .name";
- $where
- .find(nameSelector)
- .attr("title", _l("Click to rename collection"))
- .tooltip({ placement: "bottom" })
- .make_text_editable({
- on_finish: function (newName) {
- var previousName = panel.model.get("name");
- if (newName && newName !== previousName) {
- panel.$el.find(nameSelector).text(newName);
- panel.model.save({ name: newName }).fail(() => {
- panel.$el.find(nameSelector).text(panel.model.previous("name"));
- });
- } else {
- panel.$el.find(nameSelector).text(previousName);
- }
- },
- });
-
- const el = $where.find(".tags-display")[0];
- const propsData = {
- model: this.model,
- disabled: false,
- context: "collection-view-edit",
- };
-
- const vm = mountModelTags(propsData, el);
-
- const toggleEditor = () => {
- $(vm.$el).toggleClass("active");
- this.tagsEditorShown = $(vm.$el).hasClass("active");
- };
-
- if (this.tagsEditorShown) {
- const editorIsOpen = $(vm.$el).hasClass("active");
- if (!editorIsOpen) {
- toggleEditor();
- }
- }
- },
-
- // ........................................................................ misc
- /** string rep */
- toString: function () {
- return `CollectionViewEdit(${this.model ? this.model.get("name") : ""})`;
- },
- }
-);
-
-//==============================================================================
-export default {
- CollectionViewEdit: CollectionViewEdit,
-};
diff --git a/client/src/mvc/collection/collection-view.js b/client/src/mvc/collection/collection-view.js
deleted file mode 100644
index 13b10d5e0c1..00000000000
--- a/client/src/mvc/collection/collection-view.js
+++ /dev/null
@@ -1,235 +0,0 @@
-import _ from "underscore";
-import { getAppRoot } from "onload/loadConfig";
-import LIST_VIEW from "mvc/list/list-view";
-import DC_LI from "mvc/collection/collection-li";
-import _l from "utils/localization";
-
-var logNamespace = "collections";
-/* =============================================================================
-TODO:
-
-============================================================================= */
-/** @class non-editable, read-only View/Controller for a dataset collection.
- */
-var _super = LIST_VIEW.ModelListPanel;
-var CollectionView = _super.extend(
- /** @lends CollectionView.prototype */ {
- //MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)
- _logNamespace: logNamespace,
-
- className: `${_super.prototype.className} dataset-collection-panel`,
-
- /** sub view class used for datasets */
- DatasetDCEViewClass: DC_LI.DatasetDCEListItemView,
-
- /** key of attribute in model to assign to this.collection */
- modelCollectionKey: "elements",
-
- // ......................................................................... SET UP
- /** Set up the view, set up storage, bind listeners to HistoryContents events
- * @param {Object} attributes optional settings for the panel
- */
- initialize: function (attributes) {
- _super.prototype.initialize.call(this, attributes);
- this.linkTarget = attributes.linkTarget || "_blank";
- this.dragItems = true;
- this.hasUser = attributes.hasUser;
- /** A stack of panels that currently cover or hide this panel */
- this.panelStack = [];
- /** The text of the link to go back to the panel containing this one */
- this.parentName = attributes.parentName;
- /** foldout or drilldown */
- this.foldoutStyle = attributes.foldoutStyle || "foldout";
- this.downloadUrl = `${getAppRoot()}api/dataset_collections/${this.model.attributes.id}/download`;
- },
-
- getNestedDCDCEViewClass: function () {
- return DC_LI.NestedDCDCEListItemView.extend({
- foldoutPanelClass: CollectionView,
- });
- },
-
- _queueNewRender: function ($newRender, speed) {
- speed = speed === undefined ? this.fxSpeed : speed;
- var panel = this;
- this.handleWarning($newRender);
- panel.log("_queueNewRender:", $newRender, speed);
- // TODO: jquery@1.12 doesn't change display when the elem has display: flex
- // this causes display: block for those elems after the use of show/hide animations
- // animations are removed from this view for now until fixed
- panel._swapNewRender($newRender);
- panel.trigger("rendered", panel);
- },
-
- handleWarning: function ($newRender) {
- var $warns = $newRender.find(".elements-warning");
- if (this.model.get("populated_state") === "failed") {
- var error = _l(`${this.model.get("populated_state_message")}`);
- $warns.html(`
${error}
`);
- return;
- }
- var viewLength = this.views.length;
- var elementCount = this.model.get("element_count");
- if (elementCount && elementCount !== viewLength) {
- var warning = _l(`displaying only ${viewLength} of ${elementCount} items`);
- $warns.html(`
${warning}
`);
- }
- },
-
- // ------------------------------------------------------------------------ sub-views
- /** In this override, use model.getVisibleContents */
- _filterCollection: function () {
- //TODO: should *not* be model.getVisibleContents - visibility is not model related
- return this.model.getVisibleContents();
- },
-
- /** override to return proper view class based on element_type */
- _getItemViewClass: function (model) {
- //this.debug( this + '._getItemViewClass:', model );
- //TODO: subclasses use DCEViewClass - but are currently unused - decide
- switch (model.get("element_type")) {
- case "hda":
- return this.DatasetDCEViewClass;
- case "dataset_collection":
- return this.getNestedDCDCEViewClass();
- }
- throw new TypeError("Unknown element type:", model.get("element_type"));
- },
-
- /** override to add link target and anon */
- _getItemViewOptions: function (model) {
- var options = _super.prototype._getItemViewOptions.call(this, model);
- return _.extend(options, {
- linkTarget: this.linkTarget,
- hasUser: this.hasUser,
- //TODO: could move to only nested: list:paired
- foldoutStyle: this.foldoutStyle,
- });
- },
-
- // ------------------------------------------------------------------------ collection sub-views
- /** In this override, add/remove expanded/collapsed model ids to/from web storage */
- _setUpItemViewListeners: function (view) {
- var panel = this;
- _super.prototype._setUpItemViewListeners.call(panel, view);
-
- // use pub-sub to: handle drilldown expansion and collapse
- panel.listenTo(view, {
- "expanded:drilldown": function (v, drilldown) {
- this._expandDrilldownPanel(drilldown);
- },
- "collapsed:drilldown": function (v, drilldown) {
- this._collapseDrilldownPanel(drilldown);
- },
- });
- return this;
- },
-
- /** Handle drill down by hiding this panels list and controls and showing the sub-panel */
- _expandDrilldownPanel: function (drilldown) {
- this.panelStack.push(drilldown);
- // hide this panel's controls and list, set the name for back navigation, and attach to the $el
- this.$("> .controls").add(this.$list()).hide();
- drilldown.parentName = this.model.get("name");
- this.$el.append(drilldown.render().$el);
- },
-
- /** Handle drilldown close by freeing the panel and re-rendering this panel */
- _collapseDrilldownPanel: function (drilldown) {
- this.panelStack.pop();
- this.render();
- },
-
- // ------------------------------------------------------------------------ panel events
- /** event map */
- events: {
- "click .navigation .back": "close",
- },
-
- /** close/remove this collection panel */
- close: function (event) {
- this.remove();
- this.trigger("close");
- },
-
- // ........................................................................ misc
- /** string rep */
- toString: function () {
- return `CollectionView(${this.model ? this.model.get("name") : ""})`;
- },
- }
-);
-
-//------------------------------------------------------------------------------ TEMPLATES
-CollectionView.prototype.templates = (() => {
- var controlsTemplate = (collection, view) => {
- var subtitle = collectionDescription(view.model);
- return `
-