Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

313 righe
8.1 KiB

  1. // Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. //
  3. // MIT License (MIT)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a
  6. // copy of this software and associated documentation files (the "Software"),
  7. // to deal in the Software without restriction, including without limitation
  8. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. // and/or sell copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. //
  22. // new re-factored Listing object
  23. // uses FieldGroup for rendering filters
  24. // removed rarely used functionality
  25. //
  26. // opts:
  27. // parent
  28. // method (method to call on server)
  29. // args (additional args to method)
  30. // get_args (method to return args as dict)
  31. // show_filters [false]
  32. // doctype
  33. // filter_fields (if given, this list is rendered, else built from doctype)
  34. // query or get_query (will be deprecated)
  35. // query_max
  36. // buttons_in_frame
  37. // no_result_message ("No result")
  38. // page_length (20)
  39. // hide_refresh (False)
  40. // no_toolbar
  41. // new_doctype
  42. // [function] render_row(parent, data)
  43. // [function] onrun
  44. // no_loading (no ajax indicator)
  45. wn.provide('wn.ui');
  46. wn.ui.Listing = Class.extend({
  47. init: function(opts) {
  48. this.opts = opts || {};
  49. this.page_length = 20;
  50. this.start = 0;
  51. this.data = [];
  52. if(opts) {
  53. this.make();
  54. }
  55. },
  56. prepare_opts: function() {
  57. if(this.opts.new_doctype) {
  58. if(wn.boot.profile.can_create.indexOf(this.opts.new_doctype)==-1) {
  59. this.opts.new_doctype = null;
  60. } else {
  61. this.opts.new_doctype = get_doctype_label(this.opts.new_doctype);
  62. }
  63. }
  64. if(!this.opts.no_result_message) {
  65. this.opts.no_result_message = 'Nothing to show'
  66. }
  67. },
  68. make: function(opts) {
  69. if(opts) {
  70. this.opts = opts;
  71. }
  72. this.prepare_opts();
  73. $.extend(this, this.opts);
  74. $(this.parent).html(repl('\
  75. <div class="wnlist">\
  76. <h3 class="title hide">%(title)s</h3>\
  77. \
  78. <div class="list-filters hide">\
  79. <div class="show_filters well">\
  80. <div class="filter_area"></div>\
  81. <div>\
  82. <button class="btn btn-small btn-info search-btn">\
  83. <i class="icon-refresh icon-white"></i> Search</button>\
  84. <button class="btn btn-small add-filter-btn">\
  85. <i class="icon-plus"></i> Add Filter</button>\
  86. </div>\
  87. </div>\
  88. </div>\
  89. \
  90. <div style="margin-bottom:9px" class="list-toolbar-wrapper">\
  91. <div class="list-toolbar" style="display:inline-block; margin-right: 10px;">\
  92. </div>\
  93. <div style="display:inline-block; width: 24px; margin-left: 4px">\
  94. <img src="lib/images/ui/button-load.gif" \
  95. class="img-load"/></div>\
  96. </div><div style="clear:both"></div>\
  97. \
  98. <div class="no-result help hide">\
  99. %(no_result_message)s\
  100. </div>\
  101. \
  102. <div class="result">\
  103. <div class="result-list"></div>\
  104. </div>\
  105. \
  106. <div class="paging-button">\
  107. <button class="btn btn-small btn-more hide">More...</div>\
  108. </div>\
  109. </div>\
  110. ', this.opts));
  111. this.$w = $(this.parent).find('.wnlist');
  112. this.set_events();
  113. if(this.appframe) {
  114. this.$w.find('.list-toolbar-wrapper').toggle(false);
  115. }
  116. if(this.show_filters) {
  117. this.make_filters();
  118. }
  119. },
  120. add_button: function(label, click, icon) {
  121. if(this.appframe) {
  122. return this.appframe.add_button(label, click, icon)
  123. } else {
  124. $button = $('<button class="btn btn-small"></button>')
  125. .appendTo(this.$w.find('.list-toolbar'))
  126. if(icon) {
  127. $('<i>').addClass(icon).appendTo($button);
  128. }
  129. $button.html(label).click(click);
  130. return $button
  131. }
  132. },
  133. show_view: function($btn, $div, $btn_unsel, $div_unsel) {
  134. $btn_unsel.removeClass('btn-info');
  135. $btn_unsel.find('i').removeClass('icon-white');
  136. $div_unsel.toggle(false);
  137. $btn.addClass('btn-info');
  138. $btn.find('i').addClass('icon-white');
  139. $div.toggle(true);
  140. },
  141. set_events: function() {
  142. var me = this;
  143. // next page
  144. this.$w.find('.btn-more').click(function() {
  145. me.run({append: true });
  146. });
  147. // title
  148. if(this.title) {
  149. this.$w.find('h3').html(this.title).toggle(true);
  150. }
  151. // hide-refresh
  152. if(!(this.hide_refresh || this.no_refresh)) {
  153. this.add_button('Refresh', function() {
  154. me.run();
  155. }, 'icon-refresh');
  156. }
  157. // new
  158. if(this.new_doctype) {
  159. this.add_button('New ' + this.new_doctype, function() {
  160. (me.custom_new_doc || me.make_new_doc)(me.new_doctype);
  161. }, 'icon-plus');
  162. }
  163. // hide-filter
  164. if(me.show_filters) {
  165. this.add_button('Show Filters', function() {
  166. me.filter_list.show_filters();
  167. }, 'icon-search').addClass('btn-filter');
  168. }
  169. if(me.no_toolbar || me.hide_toolbar) {
  170. me.$w.find('.list-toolbar-wrapper').toggle(false);
  171. }
  172. },
  173. make_new_doc: function(new_doctype) {
  174. new_doc(new_doctype);
  175. },
  176. make_filters: function() {
  177. this.filter_list = new wn.ui.FilterList({
  178. listobj: this,
  179. $parent: this.$w.find('.list-filters').toggle(true),
  180. doctype: this.doctype,
  181. filter_fields: this.filter_fields
  182. });
  183. },
  184. clear: function() {
  185. this.data = [];
  186. this.$w.find('.result-list').empty();
  187. this.$w.find('.result').toggle(true);
  188. this.$w.find('.no-result').toggle(false);
  189. this.start = 0;
  190. },
  191. run: function() {
  192. // in old - arguments: 0 = callback, 1 = append
  193. var me = this;
  194. var a0 = arguments[0]; var a1 = arguments[1];
  195. if(a0 && typeof a0=='function')
  196. this.onrun = a0;
  197. if(a0 && a0.callback)
  198. this.onrun = a0.callback;
  199. if(!a1 && !(a0 && a0.append))
  200. this.start = 0;
  201. if(!me.opts.no_loading)
  202. me.set_working(true);
  203. wn.call({
  204. method: this.opts.method || 'webnotes.widgets.query_builder.runquery',
  205. args: this.get_call_args(a0),
  206. callback: function(r) {
  207. if(!me.opts.no_loading)me.set_working(false);
  208. me.render_results(r)
  209. },
  210. no_spinner: this.opts.no_loading
  211. });
  212. },
  213. set_working: function(flag) {
  214. this.$w.find('.img-load').toggle(flag);
  215. },
  216. get_call_args: function(opts) {
  217. // load query
  218. if(!this.method) {
  219. var query = this.get_query ? this.get_query() : this.query;
  220. query = this.add_limits(query);
  221. var args={
  222. query_max: this.query_max,
  223. as_dict: 1
  224. }
  225. args.simple_query = query;
  226. } else {
  227. var args = {
  228. limit_start: this.start,
  229. limit_page_length: this.page_length
  230. }
  231. }
  232. // append user-defined arguments
  233. if(this.args)
  234. $.extend(args, this.args)
  235. if(this.get_args) {
  236. $.extend(args, this.get_args(opts));
  237. }
  238. return args;
  239. },
  240. render_results: function(r) {
  241. if(this.start==0) this.clear();
  242. this.$w.find('.btn-more').toggle(false);
  243. if(r.message) r.values = r.message;
  244. if(r.values && r.values.length) {
  245. this.data = this.data.concat(r.values);
  246. this.render_list(r.values);
  247. this.update_paging(r.values);
  248. } else {
  249. if(this.start==0) {
  250. this.$w.find('.result').toggle(false);
  251. this.$w.find('.no-result').toggle(true);
  252. }
  253. }
  254. // callbacks
  255. if(this.onrun) this.onrun();
  256. if(this.callback) this.callback(r);
  257. },
  258. render_list: function(values) {
  259. var m = Math.min(values.length, this.page_length);
  260. this.data = values;
  261. // render the rows
  262. for(var i=0; i < m; i++) {
  263. this.render_row(this.add_row(), values[i], this, i);
  264. }
  265. },
  266. update_paging: function(values) {
  267. if(values.length >= this.page_length) {
  268. this.$w.find('.btn-more').toggle(true);
  269. this.start += this.page_length;
  270. }
  271. },
  272. add_row: function() {
  273. return $('<div class="list-row">').appendTo(this.$w.find('.result-list')).get(0);
  274. },
  275. refresh: function() {
  276. this.run();
  277. },
  278. add_limits: function(query) {
  279. query += ' LIMIT ' + this.start + ',' + (this.page_length+1);
  280. return query
  281. }
  282. });