PageRenderTime 64ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/static/scripts/mvc/history/history-content-base.js

https://bitbucket.org/hbc/galaxy-central-hbc/
JavaScript | 286 lines | 173 code | 31 blank | 82 comment | 18 complexity | 584610f2c71d5224c3e394dc72765ce4 MD5 | raw file
Possible License(s): CC-BY-3.0
  1. define([
  2. "mvc/dataset/states",
  3. "mvc/base-mvc",
  4. "utils/localization"
  5. ], function( STATES, BASE_MVC, _l ){
  6. //==============================================================================
  7. /** how the type_id attribute is built for the history's mixed contents collection */
  8. var typeIdStr = function _typeIdStr( type, id ){
  9. return [ type, id ].join( '-' );
  10. };
  11. //==============================================================================
  12. /** @class base model for content items contained in a history or hdca.
  13. */
  14. var HistoryContentMixin = {
  15. //TODO:?? into true Backbone.Model?
  16. /** default attributes for a model */
  17. defaults : {
  18. // parent (containing) history
  19. history_id : null,
  20. history_content_type: 'dataset_collection',
  21. hid : 0,
  22. name : '(unnamed content)',
  23. // one of HistoryDatasetAssociation.STATES
  24. state : 'new',
  25. deleted : false,
  26. visible : true,
  27. //TODO: update to false when this is correctly passed from the API (when we have a security model for this)
  28. accessible : true,
  29. purged : false
  30. },
  31. // ........................................................................ mixed content element
  32. // in order to be part of a MIXED bbone collection, we can't rely on the id
  33. // (which may collide btwn models of different classes)
  34. // build a new id (type_id) that prefixes the history_content_type so the bbone collection can differentiate
  35. idAttribute : 'type_id',
  36. constructor : function( attrs, options ){
  37. this.info( 'HistoryContentMixin.constructor:', this, attrs, options );
  38. attrs.type_id = typeIdStr( attrs.history_content_type, attrs.id );
  39. Backbone.Model.apply( this, arguments );
  40. },
  41. _typeIdStr : function(){
  42. return typeIdStr( this.get( 'history_content_type' ), this.get( 'id' ) );
  43. },
  44. initialize : function( attrs, options ){
  45. this.debug( 'HistoryContentMixin.initialize', attrs, options );
  46. // assumes type won't change
  47. //TODO: not sure this covers all the bases...
  48. this.on( 'change:id', this._createTypeId );
  49. this._setUpListeners();
  50. },
  51. /** set up any event listeners
  52. */
  53. _setUpListeners : function(){
  54. },
  55. _createTypeId : function(){
  56. this.set( 'type_id', this._typeIdStr() );
  57. },
  58. // ........................................................................ common queries
  59. /** the more common alias of visible */
  60. hidden : function(){
  61. return !this.get( 'visible' );
  62. },
  63. /** based on show_deleted, show_hidden (gen. from the container control),
  64. * would this ds show in the list of ds's?
  65. * @param {Boolean} show_deleted are we showing deleted hdas?
  66. * @param {Boolean} show_hidden are we showing hidden hdas?
  67. */
  68. isVisible : function( show_deleted, show_hidden ){
  69. var isVisible = true;
  70. if( ( !show_deleted )
  71. && ( this.get( 'deleted' ) || this.get( 'purged' ) ) ){
  72. isVisible = false;
  73. }
  74. if( ( !show_hidden )
  75. && ( !this.get( 'visible' ) ) ){
  76. isVisible = false;
  77. }
  78. return isVisible;
  79. },
  80. /** Is this hda deleted or purged? */
  81. isDeletedOrPurged : function(){
  82. return ( this.get( 'deleted' ) || this.get( 'purged' ) );
  83. },
  84. /** Is this HDA in a 'ready' state; where 'Ready' states are states where no
  85. * processing (for the ds) is left to do on the server.
  86. */
  87. inReadyState : function(){
  88. var ready = _.contains( STATES.READY_STATES, this.get( 'state' ) );
  89. return ( this.isDeletedOrPurged() || ready );
  90. },
  91. /** Does this model already contain detailed data (as opposed to just summary level data)? */
  92. hasDetails : function(){
  93. // override
  94. return true;
  95. },
  96. /** Convenience function to match hda.has_data. */
  97. hasData : function(){
  98. // override
  99. return true;
  100. },
  101. // ........................................................................ ajax
  102. /** */
  103. urlRoot: galaxy_config.root + 'api/histories/',
  104. /** full url spec. for this HDA */
  105. url : function(){
  106. var url = this.urlRoot + this.get( 'history_id' ) + '/contents/'
  107. + this.get('history_content_type') + 's/' + this.get( 'id' );
  108. //console.debug( this + '.url:', url );
  109. return url;
  110. },
  111. /** returns misc. web urls for rendering things like re-run, display, etc. */
  112. urls : function(){
  113. //TODO: would be nice if the API did this
  114. // override
  115. return {};
  116. },
  117. /** save this HDA, _Mark_ing it as deleted (just a flag) */
  118. 'delete' : function( options ){
  119. if( this.get( 'deleted' ) ){ return jQuery.when(); }
  120. return this.save( { deleted: true }, options );
  121. },
  122. /** save this HDA, _Mark_ing it as undeleted */
  123. undelete : function( options ){
  124. if( !this.get( 'deleted' ) || this.get( 'purged' ) ){ return jQuery.when(); }
  125. return this.save( { deleted: false }, options );
  126. },
  127. /** save this HDA as not visible */
  128. hide : function( options ){
  129. if( !this.get( 'visible' ) ){ return jQuery.when(); }
  130. return this.save( { visible: false }, options );
  131. },
  132. /** save this HDA as visible */
  133. unhide : function( options ){
  134. if( this.get( 'visible' ) ){ return jQuery.when(); }
  135. return this.save( { visible: true }, options );
  136. },
  137. /** purge this HDA and remove the underlying dataset file from the server's fs */
  138. purge : function _purge( options ){
  139. //TODO: use, override model.destroy, HDA.delete({ purge: true })
  140. // override
  141. return jQuery.when();
  142. },
  143. // ........................................................................ searching
  144. /** what attributes of the content will be used in a text search */
  145. searchAttributes : [
  146. 'name'
  147. ],
  148. /** our attr keys don't often match the labels we display to the user - so, when using
  149. * attribute specifiers ('name="bler"') in a term, allow passing in aliases for the
  150. * following attr keys.
  151. */
  152. searchAliases : {
  153. title : 'name'
  154. },
  155. /** search the attribute with key attrKey for the string searchFor; T/F if found */
  156. searchAttribute : function( attrKey, searchFor ){
  157. var attrVal = this.get( attrKey );
  158. //console.debug( 'searchAttribute', attrKey, attrVal, searchFor );
  159. // bail if empty searchFor or unsearchable values
  160. if( !searchFor
  161. || ( attrVal === undefined || attrVal === null ) ){
  162. return false;
  163. }
  164. // pass to sep. fn for deep search of array attributes
  165. if( _.isArray( attrVal ) ){ return this._searchArrayAttribute( attrVal, searchFor ); }
  166. return ( attrVal.toString().toLowerCase().indexOf( searchFor.toLowerCase() ) !== -1 );
  167. },
  168. /** deep(er) search for array attributes; T/F if found */
  169. _searchArrayAttribute : function( array, searchFor ){
  170. //console.debug( '_searchArrayAttribute', array, searchFor );
  171. searchFor = searchFor.toLowerCase();
  172. //precondition: searchFor has already been validated as non-empty string
  173. //precondition: assumes only 1 level array
  174. //TODO: could possibly break up searchFor more (CSV...)
  175. return _.any( array, function( elem ){
  176. return ( elem.toString().toLowerCase().indexOf( searchFor.toLowerCase() ) !== -1 );
  177. });
  178. },
  179. /** search all searchAttributes for the string searchFor,
  180. * returning a list of keys of attributes that contain searchFor
  181. */
  182. search : function( searchFor ){
  183. var model = this;
  184. return _.filter( this.searchAttributes, function( key ){
  185. return model.searchAttribute( key, searchFor );
  186. });
  187. },
  188. /** alias of search, but returns a boolean; accepts attribute specifiers where
  189. * the attributes searched can be narrowed to a single attribute using
  190. * the form: matches( 'genome_build=hg19' )
  191. * (the attribute keys allowed can also be aliases to the true attribute key;
  192. * see searchAliases above)
  193. * @param {String} term plain text or ATTR_SPECIFIER sep. key=val pair
  194. * @returns {Boolean} was term found in (any) attribute(s)
  195. */
  196. matches : function( term ){
  197. var ATTR_SPECIFIER = '=',
  198. split = term.split( ATTR_SPECIFIER );
  199. // attribute is specified - search only that
  200. if( split.length >= 2 ){
  201. var attrKey = split[0];
  202. attrKey = this.searchAliases[ attrKey ] || attrKey;
  203. return this.searchAttribute( attrKey, split[1] );
  204. }
  205. // no attribute is specified - search all attributes in searchAttributes
  206. return !!this.search( term ).length;
  207. },
  208. /** an implicit AND search for all terms; IOW, an hda must match all terms given
  209. * where terms is a whitespace separated value string.
  210. * e.g. given terms of: 'blah bler database=hg19'
  211. * an HDA would have to have attributes containing blah AND bler AND a genome_build == hg19
  212. * To include whitespace in terms: wrap the term in double quotations.
  213. */
  214. matchesAll : function( terms ){
  215. var model = this;
  216. // break the terms up by whitespace and filter out the empty strings
  217. terms = terms.match( /(".*"|\w*=".*"|\S*)/g ).filter( function( s ){ return !!s; });
  218. return _.all( terms, function( term ){
  219. term = term.replace( /"/g, '' );
  220. return model.matches( term );
  221. });
  222. },
  223. // ........................................................................ misc
  224. /** String representation */
  225. toString : function(){
  226. var nameAndId = this.get( 'id' ) || '';
  227. if( this.get( 'name' ) ){
  228. nameAndId = this.get( 'hid' ) + ' :"' + this.get( 'name' ) + '",' + nameAndId;
  229. }
  230. return 'HistoryContent(' + nameAndId + ')';
  231. }
  232. };
  233. //==============================================================================
  234. /** @class base model for content items contained in a history or hdca.
  235. * @name HistoryContent
  236. *
  237. * @augments Backbone.Model
  238. * @borrows LoggableMixin#logger as #logger
  239. * @borrows LoggableMixin#log as #log
  240. * @constructs
  241. */
  242. var HistoryContent = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend( HistoryContentMixin );
  243. //TODO:?? here or return as module fn?
  244. HistoryContent.typeIdStr = typeIdStr;
  245. //==============================================================================
  246. return {
  247. HistoryContentMixin : HistoryContentMixin,
  248. HistoryContent : HistoryContent
  249. };
  250. });