Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

360 wiersze
9.0 KiB

  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. // MIT License. See license.txt
  3. // new re-factored Listing object
  4. // removed rarely used functionality
  5. //
  6. // opts:
  7. // parent
  8. // method (method to call on server)
  9. // args (additional args to method)
  10. // get_args (method to return args as dict)
  11. // show_filters [false]
  12. // doctype
  13. // filter_fields (if given, this list is rendered, else built from doctype)
  14. // query or get_query (will be deprecated)
  15. // query_max
  16. // buttons_in_frame
  17. // no_result_message ("No result")
  18. // page_length (20)
  19. // hide_refresh (False)
  20. // no_toolbar
  21. // new_doctype
  22. // [function] render_row(parent, data)
  23. // [function] onrun
  24. // no_loading (no ajax indicator)
  25. wn.provide('wn.ui');
  26. wn.ui.Listing = Class.extend({
  27. init: function(opts) {
  28. this.opts = opts || {};
  29. this.page_length = 20;
  30. this.start = 0;
  31. this.data = [];
  32. if(opts) {
  33. this.make();
  34. }
  35. },
  36. prepare_opts: function() {
  37. if(this.opts.new_doctype) {
  38. if(wn.boot.profile.can_create.indexOf(this.opts.new_doctype)==-1) {
  39. this.opts.new_doctype = null;
  40. } else {
  41. this.opts.new_doctype = this.opts.new_doctype;
  42. }
  43. }
  44. if(!this.opts.no_result_message) {
  45. this.opts.no_result_message = wn._('Nothing to show');
  46. }
  47. this.opts._more = wn._("More");
  48. },
  49. make: function(opts) {
  50. if(opts) {
  51. this.opts = opts;
  52. }
  53. this.prepare_opts();
  54. $.extend(this, this.opts);
  55. $(this.parent).html(repl('\
  56. <div class="wnlist">\
  57. <h3 class="title hide">%(title)s</h3>\
  58. \
  59. <div class="list-filters" style="display: none;">\
  60. <div class="show_filters" style="display: none;">\
  61. <div class="filter_area"></div>\
  62. <div>\
  63. <button class="btn btn-info search-btn">\
  64. <i class="icon-refresh icon-white"></i> \
  65. <span class="hidden-phone">Search</span></button>\
  66. <button class="btn btn-default add-filter-btn">\
  67. <i class="icon-plus"></i> \
  68. <span class="hidden-phone">Add Filter</span></button>\
  69. </div>\
  70. </div>\
  71. </div>\
  72. \
  73. <div style="margin-bottom:9px" class="list-toolbar-wrapper">\
  74. <div class="list-toolbar btn-group" style="display:inline-block; margin-right: 10px;">\
  75. </div>\
  76. <div style="display: none; width: 24px; margin-left: 4px">\
  77. <img src="assets/webnotes/images/ui/button-load.gif" \
  78. class="img-load"/></div>\
  79. </div><div style="clear:both"></div>\
  80. \
  81. <div class="no-result" style="display: none;">\
  82. %(no_result_message)s\
  83. </div>\
  84. \
  85. <div class="result">\
  86. <div class="result-list"></div>\
  87. </div>\
  88. \
  89. <p class="paging-button" style="text-align: center;">\
  90. <button class="btn btn-default btn-more" style="display: none; margin: 15px 0px;">%(_more)s...</div>\
  91. </p>\
  92. </div>\
  93. ', this.opts));
  94. this.$w = $(this.parent).find('.wnlist');
  95. this.set_events();
  96. if(this.appframe) {
  97. this.$w.find('.list-toolbar-wrapper').toggle(false);
  98. }
  99. if(this.show_filters) {
  100. this.make_filters();
  101. }
  102. },
  103. add_button: function(label, click, icon) {
  104. if(this.appframe) {
  105. return this.appframe.add_button(label, click, icon)
  106. } else {
  107. $button = $('<button class="btn btn-default"></button>')
  108. .appendTo(this.$w.find('.list-toolbar'))
  109. .html((icon ? ("<i class='"+icon+"'></i> ") : "") + label)
  110. .click(click);
  111. return $button
  112. }
  113. },
  114. show_view: function($btn, $div, $btn_unsel, $div_unsel) {
  115. $btn_unsel.removeClass('btn-info');
  116. $btn_unsel.find('i').removeClass('icon-white');
  117. $div_unsel.toggle(false);
  118. $btn.addClass('btn-info');
  119. $btn.find('i').addClass('icon-white');
  120. $div.toggle(true);
  121. },
  122. set_events: function() {
  123. var me = this;
  124. // next page
  125. this.$w.find('.btn-more').click(function() {
  126. me.run({append: true });
  127. });
  128. // title
  129. if(this.title) {
  130. this.$w.find('h3').html(this.title).toggle(true);
  131. }
  132. // hide-refresh
  133. if(!(this.hide_refresh || this.no_refresh)) {
  134. this.add_button('Refresh', function() {
  135. me.run();
  136. }, 'icon-refresh');
  137. }
  138. // new
  139. if(this.new_doctype) {
  140. if(this.appframe) {
  141. this.appframe.set_title_right("<i class='icon-plus'></i> New", function() {
  142. (me.custom_new_doc || me.make_new_doc).apply(me, [me.new_doctype]); });
  143. }
  144. this.add_button(wn._('New'), function() {
  145. (me.custom_new_doc || me.make_new_doc).apply(me, [me.new_doctype]);
  146. }, 'icon-plus');
  147. }
  148. // hide-filter
  149. if(me.show_filters) {
  150. this.add_button(wn._('Filter'), function() {
  151. me.filter_list.show_filters();
  152. }, 'icon-search').addClass('btn-filter');
  153. }
  154. if(me.no_toolbar || me.hide_toolbar) {
  155. me.$w.find('.list-toolbar-wrapper').toggle(false);
  156. }
  157. },
  158. make_new_doc: function(doctype) {
  159. var me = this;
  160. wn.model.with_doctype(doctype, function() {
  161. var doc = wn.model.get_new_doc(doctype);
  162. if(me.filter_list) {
  163. $.each(me.filter_list.get_filters(), function(i, f) {
  164. if(f[0]===doctype && f[2]==="=" && f[1]!=="name")
  165. doc[f[1]]=f[3];
  166. })
  167. }
  168. wn.set_route("Form", doctype, doc.name);
  169. });
  170. },
  171. make_filters: function() {
  172. this.filter_list = new wn.ui.FilterList({
  173. listobj: this,
  174. $parent: this.$w.find('.list-filters').toggle(true),
  175. doctype: this.doctype,
  176. filter_fields: this.filter_fields
  177. });
  178. },
  179. clear: function() {
  180. this.data = [];
  181. this.$w.find('.result-list').empty();
  182. this.$w.find('.result').toggle(true);
  183. this.$w.find('.no-result').toggle(false);
  184. this.start = 0;
  185. },
  186. run: function(more) {
  187. var me = this;
  188. if(!more) {
  189. this.start = 0;
  190. if(this.onreset) this.onreset();
  191. }
  192. if(!me.opts.no_loading)
  193. me.set_working(true);
  194. return wn.call({
  195. method: this.opts.method || 'webnotes.widgets.query_builder.runquery',
  196. type: "GET",
  197. args: this.get_call_args(),
  198. callback: function(r) {
  199. if(!me.opts.no_loading)
  200. me.set_working(false);
  201. me.dirty = false;
  202. me.render_results(r);
  203. },
  204. no_spinner: this.opts.no_loading
  205. });
  206. },
  207. set_working: function(flag) {
  208. this.$w.find('.img-load').toggle(flag);
  209. },
  210. get_call_args: function() {
  211. // load query
  212. if(!this.method) {
  213. var query = this.get_query ? this.get_query() : this.query;
  214. query = this.add_limits(query);
  215. var args={
  216. query_max: this.query_max,
  217. as_dict: 1
  218. }
  219. args.simple_query = query;
  220. } else {
  221. var args = {
  222. limit_start: this.start,
  223. limit_page_length: this.page_length
  224. }
  225. }
  226. // append user-defined arguments
  227. if(this.args)
  228. $.extend(args, this.args)
  229. if(this.get_args) {
  230. $.extend(args, this.get_args());
  231. }
  232. return args;
  233. },
  234. render_results: function(r) {
  235. if(this.start===0) this.clear();
  236. this.$w.find('.btn-more').toggle(false);
  237. if(r.message) {
  238. r.values = this.get_values_from_response(r.message);
  239. }
  240. if(r.values && r.values.length) {
  241. this.data = this.data.concat(r.values);
  242. this.render_list(r.values);
  243. this.update_paging(r.values);
  244. } else {
  245. if(this.start===0) {
  246. this.$w.find('.result').toggle(false);
  247. var msg = this.get_no_result_message
  248. ? this.get_no_result_message()
  249. : (this.no_result_message
  250. ? this.no_result_message
  251. : wn._("Nothing to show"));
  252. this.$w.find('.no-result')
  253. .html(msg)
  254. .toggle(true);
  255. }
  256. }
  257. // callbacks
  258. if(this.onrun) this.onrun();
  259. if(this.callback) this.callback(r);
  260. this.$w.trigger("render-complete");
  261. },
  262. get_values_from_response: function(data) {
  263. // make dictionaries from keys and values
  264. if(data.keys) {
  265. return wn.utils.dict(data.keys, data.values);
  266. } else {
  267. return data;
  268. }
  269. },
  270. render_list: function(values) {
  271. var m = Math.min(values.length, this.page_length);
  272. this.data = values;
  273. if(this.filter_list)
  274. this.filter_values = this.filter_list.get_filters();
  275. // render the rows
  276. for(var i=0; i < m; i++) {
  277. this.render_row(this.add_row(), values[i], this, i);
  278. }
  279. },
  280. update_paging: function(values) {
  281. if(values.length >= this.page_length) {
  282. this.$w.find('.btn-more').toggle(true);
  283. this.start += this.page_length;
  284. }
  285. },
  286. add_row: function() {
  287. return $('<div class="list-row">').appendTo(this.$w.find('.result-list')).get(0);
  288. },
  289. refresh: function() {
  290. this.run();
  291. },
  292. add_limits: function(query) {
  293. query += ' LIMIT ' + this.start + ',' + (this.page_length+1);
  294. return query
  295. },
  296. set_filter: function(fieldname, label, doctype) {
  297. if(!doctype) doctype = this.doctype;
  298. var filter = this.filter_list.get_filter(fieldname);
  299. if(filter) {
  300. var v = filter.field.get_parsed_value();
  301. if(v.indexOf(label)!=-1) {
  302. // already set
  303. return false;
  304. } else {
  305. // second filter set for this field
  306. if(fieldname=='_user_tags') {
  307. // and for tags
  308. this.filter_list.add_filter(doctype, fieldname,
  309. 'like', '%' + label);
  310. } else {
  311. // or for rest using "in"
  312. filter.set_values(doctype, fieldname, 'in', v + ', ' + label);
  313. }
  314. }
  315. } else {
  316. // no filter for this item,
  317. // setup one
  318. if(['_user_tags', '_comments'].indexOf(fieldname)!==-1) {
  319. this.filter_list.add_filter(doctype, fieldname,
  320. 'like', '%' + label);
  321. } else {
  322. this.filter_list.add_filter(doctype, fieldname, '=', label);
  323. }
  324. }
  325. }
  326. });