PageRenderTime 26ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 0ms

/static/scripts/mvc/history/history-model.js

https://bitbucket.org/andreyto/mgtaxa-galaxy
JavaScript | 228 lines | 100 code | 32 blank | 96 comment | 11 complexity | 169afded25f181596411f537dcb49f78 MD5 | raw file
  1. //define([
  2. // "../mvc/base-mvc"
  3. //], function(){
  4. //==============================================================================
  5. /** @class Model for a Galaxy history resource - both a record of user
  6. * tool use and a collection of the datasets those tools produced.
  7. * @name History
  8. *
  9. * @augments BaseModel
  10. * @borrows LoggableMixin#logger as #logger
  11. * @borrows LoggableMixin#log as #log
  12. * @constructs
  13. */
  14. var History = BaseModel.extend( LoggableMixin ).extend(
  15. /** @lends History.prototype */{
  16. //TODO: bind change events from items and collection to this (itemLengths, states)
  17. ///** logger used to record this.log messages, commonly set to console */
  18. //// comment this out to suppress log output
  19. //logger : console,
  20. // values from api (may need more)
  21. defaults : {
  22. id : '',
  23. name : '',
  24. state : '',
  25. diskSize : 0,
  26. deleted : false,
  27. //tags : [],
  28. annotation : null,
  29. //TODO: message? how to get over the api?
  30. message : null
  31. },
  32. //TODO: hardcoded
  33. urlRoot: 'api/histories/',
  34. /** url for fetch */
  35. url : function(){
  36. // api location of history resource
  37. return 'api/histories/' + this.get( 'id' );
  38. },
  39. /** Set up the hdas collection
  40. * @param {Object} initialSettings model data for this History
  41. * @param {Object[]} initialHdas array of model data for this History's HDAs
  42. * @see BaseModel#initialize
  43. */
  44. initialize : function( initialSettings, initialHdas ){
  45. this.log( this + ".initialize:", initialSettings, initialHdas );
  46. /** HDACollection of the HDAs contained in this history. */
  47. this.hdas = new HDACollection();
  48. // if we've got hdas passed in the constructor, load them and set up updates if needed
  49. if( initialHdas && initialHdas.length ){
  50. this.hdas.reset( initialHdas );
  51. this.checkForUpdates();
  52. }
  53. // events
  54. //this.on( 'change', function( currModel, changedList ){
  55. // this.log( this + ' has changed:', currModel, changedList );
  56. //});
  57. //this.bind( 'all', function( event ){
  58. // //this.log( this + '', arguments );
  59. // console.info( this + '', arguments );
  60. //});
  61. },
  62. /** get data via the api (alternative to sending options, hdas to initialize)
  63. * @param {String} historyId encoded id
  64. * @param {Object[]} success
  65. * @see BaseModel#initialize
  66. */
  67. //TODO: this needs work - move to more straightforward deferred
  68. // events: loaded, loaded:user, loaded:hdas
  69. loadFromApi : function( historyId, success ){
  70. var history = this;
  71. // fetch the history AND the user (mainly to see if they're logged in at this point)
  72. history.attributes.id = historyId;
  73. //TODO:?? really? fetch user here?
  74. jQuery.when(
  75. jQuery.ajax( 'api/users/current' ),
  76. history.fetch()
  77. ).then( function( userResponse, historyResponse ){
  78. //console.warn( 'fetched user: ', userResponse[0] );
  79. //console.warn( 'fetched history: ', historyResponse[0] );
  80. history.attributes.user = userResponse[0]; //? meh.
  81. history.trigger( 'loaded:user', userResponse[0] );
  82. history.trigger( 'loaded', historyResponse[0] );
  83. }).then( function(){
  84. // ...then the hdas (using contents?ids=...)
  85. jQuery.ajax( history.url() + '/contents?' + jQuery.param({
  86. ids : history.hdaIdsFromStateIds().join( ',' )
  87. // reset the collection to the hdas returned
  88. })).success( function( hdas ){
  89. //console.warn( 'fetched hdas', hdas );
  90. history.hdas.reset( hdas );
  91. history.checkForUpdates();
  92. history.trigger( 'loaded:hdas', hdas );
  93. if( success ){ callback( history ); }
  94. });
  95. });
  96. },
  97. // reduce the state_ids map of hda id lists -> a single list of ids
  98. //...ugh - seems roundabout; necessary because the history doesn't have a straightforward list of ids
  99. // (and history_contents/index curr returns a summary only)
  100. hdaIdsFromStateIds : function(){
  101. return _.reduce( _.values( this.get( 'state_ids' ) ), function( reduction, currIdList ){
  102. return reduction.concat( currIdList );
  103. });
  104. },
  105. // get the history's state from it's cummulative ds states, delay + update if needed
  106. // events: ready
  107. checkForUpdates : function( datasets ){
  108. // get overall History state from collection, run updater if History has running/queued hdas
  109. // boiling it down on the client to running/not
  110. if( this.hdas.running().length ){
  111. this.stateUpdater();
  112. } else {
  113. this.trigger( 'ready' );
  114. }
  115. return this;
  116. },
  117. // update this history, find any hda's running/queued, update ONLY those that have changed states,
  118. // set up to run this again in some interval of time
  119. // events: ready
  120. stateUpdater : function(){
  121. var history = this,
  122. oldState = this.get( 'state' ),
  123. // state ids is a map of every possible hda state, each containing a list of ids for hdas in that state
  124. oldStateIds = this.get( 'state_ids' );
  125. // pull from the history api
  126. //TODO: fetch?
  127. jQuery.ajax( 'api/histories/' + this.get( 'id' )
  128. ).success( function( response ){
  129. //this.log( 'historyApiRequest, response:', response );
  130. history.set( response );
  131. history.log( 'current history state:', history.get( 'state' ),
  132. '(was)', oldState,
  133. 'new size:', history.get( 'nice_size' ) );
  134. //TODO: revisit this - seems too elaborate, need something straightforward
  135. // for each state, check for the difference between old dataset states and new
  136. // the goal here is to check ONLY those datasets that have changed states (not all datasets)
  137. var changedIds = [];
  138. _.each( _.keys( response.state_ids ), function( state ){
  139. var diffIds = _.difference( response.state_ids[ state ], oldStateIds[ state ] );
  140. // aggregate those changed ids
  141. changedIds = changedIds.concat( diffIds );
  142. });
  143. // send the changed ids (if any) to dataset collection to have them fetch their own model changes
  144. if( changedIds.length ){
  145. history.hdas.update( changedIds );
  146. }
  147. // set up to keep pulling if this history in run/queue state
  148. //TODO: magic number here
  149. if( ( history.get( 'state' ) === HistoryDatasetAssociation.STATES.RUNNING )
  150. || ( history.get( 'state' ) === HistoryDatasetAssociation.STATES.QUEUED ) ){
  151. setTimeout( function(){
  152. history.stateUpdater();
  153. }, 4000 );
  154. // otherwise, we're now in a 'ready' state (no hdas running)
  155. } else {
  156. history.trigger( 'ready' );
  157. }
  158. }).error( function( xhr, status, error ){
  159. // if not interruption by iframe reload
  160. //TODO: remove when iframes are removed
  161. if( !( ( xhr.readyState === 0 ) && ( xhr.status === 0 ) ) ){
  162. //if( console && console.warn ){
  163. // console.warn( 'Error getting history updates from the server:', xhr, status, error );
  164. //}
  165. alert( _l( 'Error getting history updates from the server.' ) + '\n' + error );
  166. }
  167. });
  168. },
  169. toString : function(){
  170. var nameString = ( this.get( 'name' ) )?
  171. ( ',' + this.get( 'name' ) ) : ( '' );
  172. return 'History(' + this.get( 'id' ) + nameString + ')';
  173. }
  174. });
  175. //==============================================================================
  176. /** @class A collection of histories (per user).
  177. * (stub) currently unused.
  178. * @name HistoryCollection
  179. *
  180. * @borrows LoggableMixin#logger as #logger
  181. * @borrows LoggableMixin#log as #log
  182. * @constructs
  183. */
  184. var HistoryCollection = Backbone.Collection.extend( LoggableMixin ).extend(
  185. /** @lends HistoryCollection.prototype */{
  186. model : History,
  187. urlRoot : 'api/histories'
  188. ///** logger used to record this.log messages, commonly set to console */
  189. //// comment this out to suppress log output
  190. //logger : console,
  191. });
  192. //==============================================================================
  193. //return {
  194. // History : History,
  195. // HistoryCollection : HistoryCollection,
  196. //};});