PageRenderTime 49ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/static/scripts/mvc/library/library-folderlist-view.js

https://bitbucket.org/remy_d1/galaxy-central-manageapi
JavaScript | 340 lines | 250 code | 39 blank | 51 comment | 36 complexity | d9c762873fdea5a7f838d1d6c02a07fa MD5 | raw file
Possible License(s): CC-BY-3.0
  1. define([
  2. "galaxy.masthead",
  3. "utils/utils",
  4. "libs/toastr",
  5. "mvc/library/library-model",
  6. "mvc/library/library-folderrow-view",
  7. "mvc/library/library-dataset-view"
  8. ],
  9. function(mod_masthead,
  10. mod_utils,
  11. mod_toastr,
  12. mod_library_model,
  13. mod_library_folderrow_view,
  14. mod_library_dataset_view
  15. ) {
  16. var FolderListView = Backbone.View.extend({
  17. el : '#folder_items_element',
  18. defaults: {
  19. 'include_deleted' : false
  20. },
  21. // progress percentage
  22. progress: 0,
  23. // progress rate per one item
  24. progressStep: 1,
  25. // self modal
  26. modal : null,
  27. folderContainer: null,
  28. sort: 'asc',
  29. events: {
  30. 'click #select-all-checkboxes' : 'selectAll',
  31. 'click .dataset_row' : 'selectClickedRow',
  32. 'click .sort-folder-link' : 'sortColumnClicked'
  33. },
  34. // cache of rendered views
  35. rowViews: {},
  36. initialize : function(options){
  37. this.options = _.defaults(this.options || {}, options);
  38. this.fetchFolder();
  39. },
  40. fetchFolder: function(options){
  41. var options = options || {};
  42. this.options.include_deleted = options.include_deleted;
  43. var that = this;
  44. this.collection = new mod_library_model.Folder();
  45. // start to listen if someone modifies collection
  46. this.listenTo(this.collection, 'add', this.renderOne);
  47. this.listenTo(this.collection, 'remove', this.removeOne);
  48. this.folderContainer = new mod_library_model.FolderContainer({id: this.options.id});
  49. this.folderContainer.url = this.folderContainer.attributes.urlRoot + this.options.id + '/contents';
  50. if (this.options.include_deleted){
  51. this.folderContainer.url = this.folderContainer.url + '?include_deleted=true';
  52. }
  53. this.folderContainer.fetch({
  54. success: function(folder_container) {
  55. that.folder_container = folder_container;
  56. that.render();
  57. that.addAll(folder_container.get('folder').models);
  58. if (that.options.dataset_id){
  59. row = _.findWhere(that.rowViews, {id: that.options.dataset_id});
  60. if (row) {
  61. row.showDatasetDetails();
  62. } else {
  63. mod_toastr.error('Dataset not found. Showing folder instead.');
  64. }
  65. }
  66. },
  67. error: function(model, response){
  68. if (typeof response.responseJSON !== "undefined"){
  69. mod_toastr.error(response.responseJSON.err_msg + ' Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
  70. } else {
  71. mod_toastr.error('An error ocurred. Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
  72. }
  73. }
  74. });
  75. },
  76. render: function (options) {
  77. this.options = _.defaults(this.options, options);
  78. var template = this.templateFolder();
  79. $(".tooltip").hide();
  80. // TODO move to server
  81. // find the upper id in the full path
  82. var path = this.folderContainer.attributes.metadata.full_path;
  83. var upper_folder_id;
  84. if (path.length === 1){ // the library is above us
  85. upper_folder_id = 0;
  86. } else {
  87. upper_folder_id = path[path.length-2][0];
  88. }
  89. this.$el.html(template({ path: this.folderContainer.attributes.metadata.full_path, parent_library_id: this.folderContainer.attributes.metadata.parent_library_id, id: this.options.id, upper_folder_id: upper_folder_id, order: this.sort}));
  90. // initialize the library tooltips
  91. $("#center [data-toggle]").tooltip();
  92. //hack to show scrollbars
  93. $("#center").css('overflow','auto');
  94. },
  95. /**
  96. * Call this after all models are added to the collection
  97. * to ensure that the folder toolbar will show proper options
  98. * and that event will be bound on all subviews.
  99. */
  100. postRender: function(){
  101. var fetched_metadata = this.folderContainer.attributes.metadata;
  102. fetched_metadata.contains_file = typeof this.collection.findWhere({type: 'file'}) !== 'undefined';
  103. Galaxy.libraries.folderToolbarView.configureElements(fetched_metadata);
  104. $('.library-row').hover(function() {
  105. $(this).find('.show_on_hover').show();
  106. }, function () {
  107. $(this).find('.show_on_hover').hide();
  108. });
  109. },
  110. /**
  111. * Adds all given models to the collection.
  112. * @param {array of Item or FolderAsModel} array of models that should
  113. * be added to the view's collection.
  114. */
  115. addAll: function(models){
  116. _.each(models.reverse(), function(model) {
  117. Galaxy.libraries.folderListView.collection.add(model);
  118. });
  119. $("#center [data-toggle]").tooltip();
  120. this.checkEmptiness();
  121. this.postRender();
  122. },
  123. /**
  124. * Iterates this view's collection and calls the render
  125. * function for each. Also binds the hover behavior.
  126. */
  127. renderAll: function(){
  128. var that = this;
  129. _.each(this.collection.models.reverse(), function(model) {
  130. that.renderOne(model);
  131. });
  132. this.postRender();
  133. },
  134. /**
  135. * Creates a view for the given model and adds it to the folder view.
  136. * @param {Item or FolderAsModel} model of the view that will be rendered
  137. */
  138. renderOne: function(model){
  139. if (model.get('type') !== 'folder'){
  140. this.options.contains_file = true;
  141. // model.set('readable_size', this.size_to_string(model.get('file_size')));
  142. }
  143. model.set('folder_id', this.id);
  144. var rowView = new mod_library_folderrow_view.FolderRowView(model);
  145. // save new rowView to cache
  146. this.rowViews[model.get('id')] = rowView;
  147. this.$el.find('#first_folder_item').after(rowView.el);
  148. $('.library-row').hover(function() {
  149. $(this).find('.show_on_hover').show();
  150. }, function () {
  151. $(this).find('.show_on_hover').hide();
  152. });
  153. },
  154. /**
  155. * removes the view of the given model from the DOM
  156. * @param {Item or FolderAsModel} model of the view that will be removed
  157. */
  158. removeOne: function(model){
  159. this.$el.find('#' + model.id).remove();
  160. },
  161. /** Checks whether the list is empty and adds/removes the message */
  162. checkEmptiness : function(){
  163. if ((this.$el.find('.dataset_row').length === 0) && (this.$el.find('.folder_row').length === 0)){
  164. this.$el.find('.empty-folder-message').show();
  165. } else {
  166. this.$el.find('.empty-folder-message').hide();
  167. }
  168. },
  169. /** User clicked the table heading = he wants to sort stuff */
  170. sortColumnClicked : function(event){
  171. event.preventDefault();
  172. if (this.sort === 'asc'){
  173. this.sortFolder('name','desc');
  174. this.sort = 'desc';
  175. } else {
  176. this.sortFolder('name','asc');
  177. this.sort = 'asc';
  178. }
  179. this.render();
  180. this.renderAll();
  181. this.checkEmptiness();
  182. },
  183. /**
  184. * Sorts the underlying collection according to the parameters received.
  185. * Currently supports only sorting by name.
  186. */
  187. sortFolder: function(sort_by, order){
  188. if (sort_by === 'name'){
  189. if (order === 'asc'){
  190. return this.collection.sortByNameAsc();
  191. } else if (order === 'desc'){
  192. return this.collection.sortByNameDesc();
  193. }
  194. }
  195. },
  196. /**
  197. * User clicked the checkbox in the table heading
  198. * @param {context} event
  199. */
  200. selectAll : function (event) {
  201. var selected = event.target.checked;
  202. that = this;
  203. // Iterate each checkbox
  204. $(':checkbox', '#folder_list_body').each(function() {
  205. this.checked = selected;
  206. $row = $(this.parentElement.parentElement);
  207. // Change color of selected/unselected
  208. if (selected) {
  209. that.makeDarkRow($row);
  210. } else {
  211. that.makeWhiteRow($row);
  212. }
  213. });
  214. },
  215. /**
  216. * Check checkbox if user clicks on the whole row or
  217. * on the checkbox itself
  218. */
  219. selectClickedRow : function (event) {
  220. var checkbox = '';
  221. var $row;
  222. var source;
  223. if (event.target.localName === 'input'){
  224. checkbox = event.target;
  225. $row = $(event.target.parentElement.parentElement);
  226. source = 'input';
  227. } else if (event.target.localName === 'td') {
  228. checkbox = $("#" + event.target.parentElement.id).find(':checkbox')[0];
  229. $row = $(event.target.parentElement);
  230. source = 'td';
  231. }
  232. if (checkbox.checked){
  233. if (source==='td'){
  234. checkbox.checked = '';
  235. this.makeWhiteRow($row);
  236. } else if (source==='input') {
  237. this.makeDarkRow($row);
  238. }
  239. } else {
  240. if (source==='td'){
  241. checkbox.checked = 'selected';
  242. this.makeDarkRow($row);
  243. } else if (source==='input') {
  244. this.makeWhiteRow($row);
  245. }
  246. }
  247. },
  248. makeDarkRow: function($row){
  249. $row.removeClass('light').addClass('dark');
  250. $row.find('a').removeClass('light').addClass('dark');
  251. $row.find('.fa-file-o').removeClass('fa-file-o').addClass('fa-file');
  252. },
  253. makeWhiteRow: function($row){
  254. $row.removeClass('dark').addClass('light');
  255. $row.find('a').removeClass('dark').addClass('light');
  256. $row.find('.fa-file').removeClass('fa-file').addClass('fa-file-o');
  257. },
  258. templateFolder : function (){
  259. var tmpl_array = [];
  260. // BREADCRUMBS
  261. tmpl_array.push('<ol class="breadcrumb">');
  262. tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
  263. tmpl_array.push(' <% _.each(path, function(path_item) { %>');
  264. tmpl_array.push(' <% if (path_item[0] != id) { %>');
  265. tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a> </li> ');
  266. tmpl_array.push( '<% } else { %>');
  267. tmpl_array.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');
  268. tmpl_array.push(' <% } %>');
  269. tmpl_array.push(' <% }); %>');
  270. tmpl_array.push('</ol>');
  271. // FOLDER CONTENT
  272. tmpl_array.push('<table data-library-id="<%- parent_library_id %>" id="folder_table" class="grid table table-condensed">');
  273. tmpl_array.push(' <thead>');
  274. tmpl_array.push(' <th class="button_heading"></th>');
  275. tmpl_array.push(' <th style="text-align: center; width: 20px; " title="Check to select all datasets"><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');
  276. tmpl_array.push(' <th><a class="sort-folder-link" title="Click to reverse order" href="#">name</a> <span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');
  277. tmpl_array.push(' <th style="width:5%;">data type</th>');
  278. tmpl_array.push(' <th style="width:10%;">size</th>');
  279. tmpl_array.push(' <th style="width:160px;">time updated (UTC)</th>');
  280. tmpl_array.push(' <th style="width:10%;"></th> ');
  281. tmpl_array.push(' </thead>');
  282. tmpl_array.push(' <tbody id="folder_list_body">');
  283. tmpl_array.push(' <tr id="first_folder_item">');
  284. tmpl_array.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');
  285. tmpl_array.push(' <td></td>');
  286. tmpl_array.push(' <td></td>');
  287. tmpl_array.push(' <td></td>');
  288. tmpl_array.push(' <td></td>');
  289. tmpl_array.push(' <td></td>');
  290. tmpl_array.push(' <td></td>');
  291. tmpl_array.push(' </tr>');
  292. tmpl_array.push(' </tbody>');
  293. tmpl_array.push('</table>');
  294. tmpl_array.push('<div class="empty-folder-message" style="display:none;">This folder is either empty or you do not have proper access permissions to see the contents. If you expected something to show up please consult the <a href="https://wiki.galaxyproject.org/Admin/DataLibraries/LibrarySecurity" target="_blank">library security wikipage</a> or visit the <a href="https://biostar.usegalaxy.org/" target="_blank">Galaxy support site</a>.</div>');
  295. return _.template(tmpl_array.join(''));
  296. }
  297. });
  298. return {
  299. FolderListView: FolderListView
  300. };
  301. });