Merge branch 'history.updating' into dev

This commit is contained in:
Dannon Baker
2016-03-10 09:38:24 -05:00
21 changed files with 186 additions and 126 deletions
@@ -2,9 +2,10 @@ define([
"mvc/history/history-content-model",
"mvc/history/hda-model",
"mvc/history/hdca-model",
"mvc/dataset/states",
"mvc/base-mvc",
"utils/localization"
], function( HISTORY_CONTENT, HDA_MODEL, HDCA_MODEL, BASE_MVC, _l ){
], function( HISTORY_CONTENT, HDA_MODEL, HDCA_MODEL, STATES, BASE_MVC, _l ){
'use strict';
@@ -102,15 +103,8 @@ var HistoryContents = Backbone.Collection
* @see HistoryDatasetAssociation#inReadyState
*/
running : function(){
var idList = [];
this.each( function( item ){
var isRunning = !item.inReadyState();
if( isRunning ){
//TODO: is this still correct since type_id
idList.push( item.get( 'id' ) );
}
});
return idList;
function filterFn( c ){ return !c.inReadyState(); }
return new HistoryContents( this.filter( filterFn ) );
},
/** Get the model with the given hid
@@ -156,12 +150,53 @@ var HistoryContents = Backbone.Collection
return new HistoryContents( this.filter( filterFn ) );
},
/** return a new contents collection of only hidden items */
visibleAndUndeleted : function(){
function filterFn( c ){ return c.get( 'visible' ) && !c.get( 'deleted' ); }
return new HistoryContents( this.filter( filterFn ) );
},
/** return true if any contents don't have details */
haveDetails : function(){
return this.all( function( content ){ return content.hasDetails(); });
},
// ........................................................................ ajax
/** override to use newest (versioned) api */
fetch : function( options ){
options = options || {};
options.data = _.defaults( options.data || {}, {
v : 'dev'
});
return Backbone.Collection.prototype.fetch.call( this, options );
},
/** override to use newest (versioned) api */
fetchUpdated : function( since, options ){
options = options || {};
options.traditional = true;
// TODO: this is painful - simplify here or move q/qv to named/mappable params
options.data = [{ name: 'v', value: 'dev' }];
if( since ){
options.data = options.data.concat( this._filtersFromMap({
'update_time-ge' : since.toISOString(),
}));
}
options.merge = true;
options.remove = false;
return this.fetch( options );
},
_filtersFromMap : function( filterMap ){
var filters = [];
// TODO: this seems unnecessary
_.each( filterMap, function( val, key ){
filters.push({ name: 'q', value: key });
filters.push({ name: 'qv', value: val });
});
return filters;
},
/** fetch detailed model data for all contents in this collection */
fetchAllDetails : function( options ){
options = options || {};
@@ -293,7 +328,6 @@ var HistoryContents = Backbone.Collection
});
},
/** In this override, copy the historyId to the clone */
clone : function(){
var clone = Backbone.Collection.prototype.clone.call( this );
@@ -137,6 +137,18 @@ var History = Backbone.Model
return _.reduce( _.values( this.get( 'state_details' ) ), function( memo, num ){ return memo + num; }, 0 );
},
/** Return the number of running jobs assoc with this history (note: unknown === 0) */
numOfUnfinishedJobs : function(){
var unfinishedJobIds = this.get( 'non_ready_jobs' );
return unfinishedJobIds? unfinishedJobIds.length : 0;
},
/** Return the number of running hda/hdcas in this history (note: unknown === 0) */
numOfUnfinishedShownContents : function(){
var contents = this.contents.running().visibleAndUndeleted();
return contents? contents.length : 0;
},
// ........................................................................ search
/** What model fields to search with */
searchAttributes : [
@@ -150,39 +162,56 @@ var History = Backbone.Model
},
// ........................................................................ updates
/** does the contents collection indicate they're still running and need to be updated later?
* delay + update if needed
* @param {Function} onReadyCallback function to run when all contents are in the ready state
* events: ready
*/
checkForUpdates : function( onReadyCallback ){
//this.info( 'checkForUpdates' )
// get overall History state from collection, run updater if History has running/queued contents
// boiling it down on the client to running/not
if( this.contents.running().length ){
this.setUpdateTimeout();
} else {
this.trigger( 'ready' );
if( _.isFunction( onReadyCallback ) ){
onReadyCallback.call( this );
}
}
return this;
_getSizeAndRunning : function(){
return this.fetch({ data : $.param({ keys : 'size,non_ready_jobs' }) });
},
/** create a timeout (after UPDATE_DELAY or delay ms) to refetch the contents. Clear any prev. timeout */
setUpdateTimeout : function( delay ){
delay = delay || History.UPDATE_DELAY;
var history = this;
/** */
refresh : function( options ){
options = options || {};
var self = this;
// prevent buildup of updater timeouts by clearing previous if any, then set new and cache id
this.clearUpdateTimeout();
this.updateTimeoutId = setTimeout( function(){
history.refresh();
}, delay );
return this.updateTimeoutId;
var lastUpdateTime = self.lastUpdateTime;
self.lastUpdateTime = new Date();
// note if there was no previous update time, all summary contents will be fetched
return self.contents.fetchUpdated( lastUpdateTime )
.done( _.bind( self.checkForUpdates, self ) );
},
/** */
checkForUpdates : function( options ){
options = options || {};
var delay = History.UPDATE_DELAY;
var self = this;
function _delayThenUpdate(){
// prevent buildup of updater timeouts by clearing previous if any, then set new and cache id
self.clearUpdateTimeout();
self.updateTimeoutId = setTimeout( function(){
self.refresh( options );
}, delay );
}
// if there are still datasets in the non-ready state, recurse into this function with the new time
if( this.numOfUnfinishedShownContents() > 0 ){
_delayThenUpdate();
} else {
// no datasets are running, but currently runnning jobs may still produce new datasets
// see if the history has any running jobs and continue to update if so
// (also update the size for the user in either case)
self._getSizeAndRunning()
.done( function( historyData ){
if( self.numOfUnfinishedJobs() > 0 ){
_delayThenUpdate();
} else {
// otherwise, let listeners know that all updates have stopped
self.trigger( 'ready' );
// self.lastUpdateTime = null;
}
});
}
},
/** clear the timeout and the cached timeout id */
@@ -193,32 +222,6 @@ var History = Backbone.Model
}
},
/* update the contents, getting full detailed model data for any whose id is in detailIds
* set up to run this again in some interval of time
* @param {String[]} detailIds list of content ids to get detailed model data for
* @param {Object} options std. backbone fetch options map
*/
refresh : function( detailIds, options ){
//this.info( 'refresh:', detailIds, this.contents );
detailIds = detailIds || [];
options = options || {};
var history = this;
// add detailIds to options as CSV string
options.data = options.data || {};
if( detailIds.length ){
options.data.details = detailIds.join( ',' );
}
var xhr = this.contents.fetch( options );
xhr.done( function( models ){
history.checkForUpdates( function(){
// fetch the history inside onReadyCallback in order to recalc history size
this.fetch();
});
});
return xhr;
},
// ........................................................................ ajax
/** save this history, _Mark_ing it as deleted (just a flag) */
_delete : function( options ){
@@ -330,14 +333,11 @@ History.getHistoryData = function getHistoryData( historyId, options ){
if( _.isFunction( hdcaDetailIds ) ){
hdcaDetailIds = hdcaDetailIds( historyData );
}
var data = {};
var data = {
v : 'dev'
};
if( detailIdsFn.length ) {
data.dataset_details = detailIdsFn.join( ',' );
}
if( hdcaDetailIds.length ) {
// for symmetry, not actually used by backend of consumed
// by frontend.
data.dataset_collection_details = hdcaDetailIds.join( ',' );
data.details = detailIdsFn.join( ',' );
}
return jQuery.ajax( Galaxy.root + 'api/histories/' + historyData.id + '/contents', { data: data });
}
@@ -131,8 +131,8 @@ var HistoryView = _super.extend(
/** In this override, clear the update timer on the model */
freeModel : function(){
_super.prototype.freeModel.call( this );
//TODO: move to History.free()
if( this.model ){
//TODO: move to History.free()
this.model.clearUpdateTimeout();
}
return this;
@@ -221,9 +221,9 @@ var HistoryView = _super.extend(
},
/** convenience alias to the model. Updates the item list only (not the history) */
refreshContents : function( detailIds, options ){
refreshContents : function( options ){
if( this.model ){
return this.model.refresh( detailIds, options );
return this.model.refresh( options );
}
// may have callbacks - so return an empty promise
return $.when();
@@ -453,7 +453,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
handleDeletedHistory : function handleDeletedHistory( history ){
if( history.get( 'deleted' ) || history.get( 'purged' ) ){
this.log( 'handleDeletedHistory', this.collection.includeDeleted, history );
var multipanel = this;
var multipanel = this,
column = multipanel.columnMap[ history.id ];
if( !column ){ return; }
@@ -723,7 +723,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var xhrData = {},
ids = _.values( column.panel.storage.get( 'expandedIds' ) ).join();
if( ids ){
xhrData.dataset_details = ids;
xhrData.details = ids;
}
// this uses a 'named' queue so that duplicate requests are ignored
this.hdaQueue.add({
+22 -2
View File
@@ -5,13 +5,16 @@ Histories are containers for datasets or dataset collections
created (or copied) by users over the course of an analysis.
"""
from sqlalchemy import desc, asc
from sqlalchemy import desc
from sqlalchemy import asc
from galaxy import model
from galaxy import exceptions as glx_exceptions
from galaxy.managers import sharable
from galaxy.managers import deletable
from galaxy.managers import hdas
# from galaxy.managers import hdcas
from galaxy.managers import history_contents
from galaxy.managers import collections_util
@@ -34,6 +37,8 @@ class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMi
def __init__( self, app, *args, **kwargs ):
super( HistoryManager, self ).__init__( app, *args, **kwargs )
self.hda_manager = hdas.HDAManager( app )
self.contents_manager = history_contents.HistoryContentsManager( app )
self.contents_filters = history_contents.HistoryContentsFilters( app )
def copy( self, history, user, **kwargs ):
"""
@@ -147,6 +152,19 @@ class HistoryManager( sharable.SharableModelManager, deletable.PurgableManagerMi
raise glx_exceptions.RequestParameterInvalidException( 'Unkown order_by', order_by=order_by_string,
available=[ 'create_time', 'update_time', 'name', 'size' ])
def non_ready_jobs( self, history ):
"""Return the currently running job objects associated with this history.
Where running is defined as new, waiting, queued, running, resubmitted,
and upload.
"""
# TODO: defer to jobModelManager (if there was one)
# TODO: genericize the params to allow other filters
jobs = ( self.session().query( model.Job )
.filter( model.Job.history == history )
.filter( model.Job.state.in_( model.Job.non_ready_states ) ) )
return jobs
class HistorySerializer( sharable.SharableModelSerializer, deletable.PurgableSerializerMixin ):
"""
@@ -215,7 +233,9 @@ class HistorySerializer( sharable.SharableModelSerializer, deletable.PurgableSer
'hdas' : lambda i, k, **c: [ self.app.security.encode_id( hda.id ) for hda in i.datasets ],
'state_details' : self.serialize_state_counts,
'state_ids' : self.serialize_state_ids,
'contents' : self.serialize_contents
'contents' : self.serialize_contents,
'non_ready_jobs': lambda i, k, **c: [ self.app.security.encode_id( job.id ) for job
in self.manager.non_ready_jobs( i ) ],
})
# remove this
+3 -7
View File
@@ -14,7 +14,6 @@ from galaxy.managers import base
from galaxy.managers import deletable
from galaxy.managers import containers
from galaxy.managers import hdas
from galaxy.managers import collections
import logging
log = logging.getLogger( __name__ )
@@ -31,7 +30,6 @@ class HistoryContentsManager( containers.ContainerManagerMixin ):
contained_class_type_name = 'dataset'
subcontainer_class = model.HistoryDatasetCollectionAssociation
# TODO:
subcontainer_class_manager_class = None
subcontainer_class_type_name = 'dataset_collection'
@@ -59,7 +57,6 @@ class HistoryContentsManager( containers.ContainerManagerMixin ):
def __init__( self, app ):
self.app = app
self.contained_manager = self.contained_class_manager_class( app )
self.subcontainer_manager = collections.DatasetCollectionManager( app )
# ---- interface
def contained( self, container, filters=None, limit=None, offset=None, order_by=None, **kwargs ):
@@ -136,15 +133,14 @@ class HistoryContentsManager( containers.ContainerManagerMixin ):
def _get_filter_for_contained( self, container, content_class ):
return content_class.history == container
def _union_of_contents( self, container, **kwargs ):
def _union_of_contents( self, container, expand_models=True, **kwargs ):
"""
Returns a limited and offset list of both types of contents, filtered
and in some order.
"""
contents_results = self._union_of_contents_query( container, **kwargs ).all()
# import pprint
# for result in contents_results:
# pprint.pprint( result )
if not expand_models:
return contents_results
# partition ids into a map of { component_class names -> list of ids } from the above union query
id_map = dict( (( self.contained_class_type_name, [] ), ( self.subcontainer_class_type_name, [] )) )
+10
View File
@@ -368,6 +368,15 @@ class Job( object, JobLike, Dictifiable ):
terminal_states = [ states.OK,
states.ERROR,
states.DELETED ]
#: job states where the job hasn't finished and the model may still change
non_ready_states = [
states.NEW,
states.RESUBMITTED,
states.UPLOAD,
states.WAITING,
states.QUEUED,
states.RUNNING,
]
# Please include an accessor (get/set pair) for any new columns/members.
def __init__( self ):
@@ -1622,6 +1631,7 @@ class Dataset( StorableObject ):
# failed_metadata is only valid as DatasetInstance state currently
non_ready_states = (
states.NEW,
states.UPLOAD,
states.QUEUED,
states.RUNNING,
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
webpackJsonp([4],[function(e,r,n){(function(e){var r=n(1),a=r,i=n(60).GalaxyApp,o=n(10),t=n(5),l=n(62);window.app=function(n,c){window.Galaxy=new i(n,c),Galaxy.debug("login app");var d=encodeURI(n.redirect);if(!n.show_welcome_with_login){var w=r.param({use_panels:"True",redirect:d});return void(window.location.href=Galaxy.root+"user/login?"+w)}var p=new l.PageLayoutView(e.extend(n,{el:"body",center:new o.CenterPanel({el:"#center"}),right:new o.RightPanel({title:t("Login required"),el:"#right"})}));a(function(){var e=r.param({redirect:d}),a=Galaxy.root+"user/login?"+e;p.render(),p.center.$("#galaxy_main").prop("src",n.welcome_url),p.right.$(".unified-panel-body").css("overflow","hidden").html('<iframe src="'+a+'" frameborder="0" style="width: 100%; height: 100%;"/>')})}}).call(r,n(3))}]);
webpackJsonp([4],[function(e,r,n){(function(e){var r=n(1),a=r,i=n(60).GalaxyApp,o=n(11),t=n(5),l=n(62);window.app=function(n,c){window.Galaxy=new i(n,c),Galaxy.debug("login app");var d=encodeURI(n.redirect);if(!n.show_welcome_with_login){var w=r.param({use_panels:"True",redirect:d});return void(window.location.href=Galaxy.root+"user/login?"+w)}var p=new l.PageLayoutView(e.extend(n,{el:"body",center:new o.CenterPanel({el:"#center"}),right:new o.RightPanel({title:t("Login required"),el:"#right"})}));a(function(){var e=r.param({redirect:d}),a=Galaxy.root+"user/login?"+e;p.render(),p.center.$("#galaxy_main").prop("src",n.welcome_url),p.right.$(".unified-panel-body").css("overflow","hidden").html('<iframe src="'+a+'" frameborder="0" style="width: 100%; height: 100%;"/>')})}}).call(r,n(3))}]);
//# sourceMappingURL=login.bundled.js.map
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
define(["mvc/history/history-content-model","mvc/history/hda-model","mvc/history/hdca-model","mvc/base-mvc","utils/localization"],function(a,b,c,d){"use strict";var e="history",f=Backbone.Collection.extend(d.LoggableMixin).extend({_logNamespace:e,model:function(a,d){if("dataset"===a.history_content_type)return new b.HistoryDatasetAssociation(a,d);if("dataset_collection"===a.history_content_type){switch(a.collection_type){case"list":return new c.HistoryListDatasetCollection(a,d);case"paired":return new c.HistoryPairDatasetCollection(a,d);case"list:paired":return new c.HistoryListPairedDatasetCollection(a,d)}return{validationError:"Unknown collection_type: "+a.history_content_type}}return{validationError:"Unknown history_content_type: "+a.history_content_type}},initialize:function(a,b){b=b||{},this.historyId=b.historyId,this.model.prototype.idAttribute="type_id",this.on("all",function(){this.debug(this+".event:",arguments)})},urlRoot:Galaxy.root+"api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},ids:function(){return this.map(function(a){return a.get("id")})},notReady:function(){return this.filter(function(a){return!a.inReadyState()})},running:function(){var a=[];return this.each(function(b){var c=!b.inReadyState();c&&a.push(b.get("id"))}),a},getByHid:function(a){return _.first(this.filter(function(b){return b.get("hid")===a}))},getVisible:function(a,b,c){c=c||[],this.debug("checking isVisible");var d=new f(this.filter(function(c){return c.isVisible(a,b)}));return _.each(c,function(a){_.isFunction(a)&&(d=new f(d.filter(a)))}),d},hidden:function(){function a(a){return a.hidden()}return new f(this.filter(a))},deleted:function(){function a(a){return a.get("deleted")}return new f(this.filter(a))},haveDetails:function(){return this.all(function(a){return a.hasDetails()})},fetchAllDetails:function(a){a=a||{};var b={details:"all"};return a.data=a.data?_.extend(a.data,b):b,this.fetch(a)},ajaxQueue:function(a,b){var c=jQuery.Deferred(),d=this.length,e=[];if(!d)return c.resolve([]),c;var f=this.chain().reverse().map(function(g,h){return function(){var i=a.call(g,b);i.done(function(a){c.notify({curr:h,total:d,response:a,model:g})}),i.always(function(a){e.push(a),f.length?f.shift()():c.resolve(e)})}}).value();return f.shift()(),c},isCopyable:function(a){var b=["HistoryDatasetAssociation","HistoryDatasetCollectionAssociation"];return _.isObject(a)&&a.id&&_.contains(b,a.model_class)},copy:function(a){var b,c,d;_.isString(a)?(b=a,d="hda",c="dataset"):(b=a.id,d={HistoryDatasetAssociation:"hda",LibraryDatasetDatasetAssociation:"ldda",HistoryDatasetCollectionAssociation:"hdca"}[a.model_class]||"hda",c="hdca"===d?"dataset_collection":"dataset");var e=this,f=jQuery.post(this.url(),{content:b,source:d,type:c}).done(function(a){e.add([a])}).fail(function(){e.trigger("error",e,f,{},"Error copying contents",{type:c,id:b,source:d})});return f},matches:function(a){return this.filter(function(b){return b.matches(a)})},set:function(b,c){b=_.isArray(b)?b:[b],_.each(b,function(b){b.type_id&&b.get&&b.get("type_id")||(b.type_id=a.typeIdStr(b.history_content_type,b.id))}),Backbone.Collection.prototype.set.call(this,b,c)},createHDCA:function(a,b,d){var e=this,f={list:c.HistoryListDatasetCollection,paired:c.HistoryPairDatasetCollection},g=new f[b]({history_id:this.historyId,name:d,element_identifiers:a});return g.save().done(function(){e.add(g)}).fail(function(a,b,c){e.trigger("error",a,b,c)})},clone:function(){var a=Backbone.Collection.prototype.clone.call(this);return a.historyId=this.historyId,a},print:function(){var a=this;a.each(function(b){a.debug(b),b.elements&&a.debug(" elements:",b.elements)})},toString:function(){return["HistoryContents(",[this.historyId,this.length].join(),")"].join("")}});return{HistoryContents:f}});
define(["mvc/history/history-content-model","mvc/history/hda-model","mvc/history/hdca-model","mvc/dataset/states","mvc/base-mvc","utils/localization"],function(a,b,c,d,e){"use strict";var f="history",g=Backbone.Collection.extend(e.LoggableMixin).extend({_logNamespace:f,model:function(a,d){if("dataset"===a.history_content_type)return new b.HistoryDatasetAssociation(a,d);if("dataset_collection"===a.history_content_type){switch(a.collection_type){case"list":return new c.HistoryListDatasetCollection(a,d);case"paired":return new c.HistoryPairDatasetCollection(a,d);case"list:paired":return new c.HistoryListPairedDatasetCollection(a,d)}return{validationError:"Unknown collection_type: "+a.history_content_type}}return{validationError:"Unknown history_content_type: "+a.history_content_type}},initialize:function(a,b){b=b||{},this.historyId=b.historyId,this.model.prototype.idAttribute="type_id",this.on("all",function(){this.debug(this+".event:",arguments)})},urlRoot:Galaxy.root+"api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},ids:function(){return this.map(function(a){return a.get("id")})},notReady:function(){return this.filter(function(a){return!a.inReadyState()})},running:function(){function a(a){return!a.inReadyState()}return new g(this.filter(a))},getByHid:function(a){return _.first(this.filter(function(b){return b.get("hid")===a}))},getVisible:function(a,b,c){c=c||[],this.debug("checking isVisible");var d=new g(this.filter(function(c){return c.isVisible(a,b)}));return _.each(c,function(a){_.isFunction(a)&&(d=new g(d.filter(a)))}),d},hidden:function(){function a(a){return a.hidden()}return new g(this.filter(a))},deleted:function(){function a(a){return a.get("deleted")}return new g(this.filter(a))},visibleAndUndeleted:function(){function a(a){return a.get("visible")&&!a.get("deleted")}return new g(this.filter(a))},haveDetails:function(){return this.all(function(a){return a.hasDetails()})},fetch:function(a){return a=a||{},a.data=_.defaults(a.data||{},{v:"dev"}),Backbone.Collection.prototype.fetch.call(this,a)},fetchUpdated:function(a,b){return b=b||{},b.traditional=!0,b.data=[{name:"v",value:"dev"}],a&&(b.data=b.data.concat(this._filtersFromMap({"update_time-ge":a.toISOString()}))),b.merge=!0,b.remove=!1,this.fetch(b)},_filtersFromMap:function(a){var b=[];return _.each(a,function(a,c){b.push({name:"q",value:c}),b.push({name:"qv",value:a})}),b},fetchAllDetails:function(a){a=a||{};var b={details:"all"};return a.data=a.data?_.extend(a.data,b):b,this.fetch(a)},ajaxQueue:function(a,b){var c=jQuery.Deferred(),d=this.length,e=[];if(!d)return c.resolve([]),c;var f=this.chain().reverse().map(function(g,h){return function(){var i=a.call(g,b);i.done(function(a){c.notify({curr:h,total:d,response:a,model:g})}),i.always(function(a){e.push(a),f.length?f.shift()():c.resolve(e)})}}).value();return f.shift()(),c},isCopyable:function(a){var b=["HistoryDatasetAssociation","HistoryDatasetCollectionAssociation"];return _.isObject(a)&&a.id&&_.contains(b,a.model_class)},copy:function(a){var b,c,d;_.isString(a)?(b=a,d="hda",c="dataset"):(b=a.id,d={HistoryDatasetAssociation:"hda",LibraryDatasetDatasetAssociation:"ldda",HistoryDatasetCollectionAssociation:"hdca"}[a.model_class]||"hda",c="hdca"===d?"dataset_collection":"dataset");var e=this,f=jQuery.post(this.url(),{content:b,source:d,type:c}).done(function(a){e.add([a])}).fail(function(){e.trigger("error",e,f,{},"Error copying contents",{type:c,id:b,source:d})});return f},matches:function(a){return this.filter(function(b){return b.matches(a)})},set:function(b,c){b=_.isArray(b)?b:[b],_.each(b,function(b){b.type_id&&b.get&&b.get("type_id")||(b.type_id=a.typeIdStr(b.history_content_type,b.id))}),Backbone.Collection.prototype.set.call(this,b,c)},createHDCA:function(a,b,d){var e=this,f={list:c.HistoryListDatasetCollection,paired:c.HistoryPairDatasetCollection},g=new f[b]({history_id:this.historyId,name:d,element_identifiers:a});return g.save().done(function(){e.add(g)}).fail(function(a,b,c){e.trigger("error",a,b,c)})},clone:function(){var a=Backbone.Collection.prototype.clone.call(this);return a.historyId=this.historyId,a},print:function(){var a=this;a.each(function(b){a.debug(b),b.elements&&a.debug(" elements:",b.elements)})},toString:function(){return["HistoryContents(",[this.historyId,this.length].join(),")"].join("")}});return{HistoryContents:g}});
//# sourceMappingURL=../../../maps/mvc/history/history-contents.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long