Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

288 рядки
8.2 KiB

  1. // Copyright 2013 Web Notes Technologies Pvt Ltd
  2. // License: MIT. See license.txt
  3. wn.provide('wn.views.doclistview');
  4. wn.provide('wn.doclistviews');
  5. wn.views.ListFactory = wn.views.Factory.extend({
  6. make: function(route) {
  7. var me = this;
  8. wn.model.with_doctype(route[1], function() {
  9. new wn.views.DocListView({
  10. doctype: route[1],
  11. page: me.make_page(true)
  12. });
  13. });
  14. }
  15. });
  16. $(document).on("save", function(event, doc) {
  17. var list_page = "List/" + doc.doctype;
  18. if(wn.pages[list_page]) {
  19. if(wn.pages[list_page].doclistview)
  20. wn.pages[list_page].doclistview.dirty = true;
  21. }
  22. })
  23. wn.views.DocListView = wn.ui.Listing.extend({
  24. init: function(opts) {
  25. $.extend(this, opts)
  26. this.label = wn._(this.doctype);
  27. this.dirty = true;
  28. this.label = (this.label.toLowerCase().substr(-4) == 'list') ?
  29. wn._(this.label) : (wn._(this.label) + ' ' + wn._('List'));
  30. this.make_page();
  31. this.setup();
  32. var me = this;
  33. $(this.page).on("show", function() {
  34. me.dirty && me.run();
  35. });
  36. },
  37. make_page: function() {
  38. var me = this;
  39. this.page.doclistview = this;
  40. this.$page = $(this.page).css({"min-height": "400px"});
  41. wn.dom.set_style(".show-docstatus div { font-size: 90%; }");
  42. $('<div class="wnlist-area" style="margin-bottom: 25px;">\
  43. <div class="help">'+wn._('Loading')+'...</div></div>')
  44. .appendTo(this.$page.find(".layout-main-section"));
  45. $('<div class="show-docstatus hide section">\
  46. <div class="section-head">Show</div>\
  47. <div><input data-docstatus="0" type="checkbox" \
  48. checked="checked" /> '+wn._('Drafts')+'</div>\
  49. <div><input data-docstatus="1" type="checkbox" \
  50. checked="checked" /> '+wn._('Submitted')+'</div>\
  51. <div><input data-docstatus="2" type="checkbox" \
  52. /> '+wn._('Cancelled')+'</div>\
  53. </div>')
  54. .appendTo(this.$page.find(".layout-side-section"));
  55. this.appframe = this.page.appframe;
  56. var module = locals.DocType[this.doctype].module;
  57. this.appframe.set_title(wn._(this.doctype) + " " + wn._("List"));
  58. this.appframe.add_module_icon(module);
  59. this.appframe.set_views_for(this.doctype, "list");
  60. },
  61. setup: function() {
  62. var me = this;
  63. me.can_delete = wn.model.can_delete(me.doctype);
  64. me.meta = locals.DocType[me.doctype];
  65. me.$page.find('.wnlist-area').empty(),
  66. me.setup_listview();
  67. me.setup_docstatus_filter();
  68. me.init_list();
  69. me.init_stats();
  70. me.add_delete_option();
  71. me.show_match_help();
  72. if(me.listview.settings.onload) {
  73. me.listview.settings.onload(me);
  74. }
  75. me.make_help();
  76. },
  77. show_match_help: function() {
  78. var me = this;
  79. var match_rules = wn.perm.get_match_rule(this.doctype);
  80. if(keys(match_rules).length) {
  81. var match_text = []
  82. $.each(match_rules, function(key, values) {
  83. if(values.length==0) {
  84. match_text.push(wn._(wn.meta.get_label(me.doctype, key)) + wn._(" is not set"));
  85. } else if(values.length) {
  86. match_text.push(wn._(wn.meta.get_label(me.doctype, key)) + " = " + wn.utils.comma_or(values));
  87. }
  88. });
  89. wn.utils.set_footnote(this, this.$page.find(".layout-main-section"),
  90. wn._("Showing only for") + ": " + match_text.join(" & "));
  91. $(this.footnote_area).css({"margin-top":"0px", "margin-bottom":"20px"});
  92. }
  93. },
  94. make_help: function() {
  95. // Help
  96. if(this.meta.description) {
  97. this.appframe.add_help_button(this.meta.description);
  98. }
  99. },
  100. setup_docstatus_filter: function() {
  101. var me = this;
  102. this.can_submit = $.map(locals.DocPerm || [], function(d) {
  103. if(d.parent==me.meta.name && d.submit) return 1
  104. else return null;
  105. }).length;
  106. if(this.can_submit) {
  107. this.$page.find('.show-docstatus').removeClass('hide');
  108. this.$page.find('.show-docstatus input').click(function() {
  109. me.run();
  110. })
  111. }
  112. },
  113. setup_listview: function() {
  114. this.listview = wn.views.get_listview(this.doctype, this);
  115. this.wrapper = this.$page.find('.wnlist-area');
  116. this.page_length = 20;
  117. this.allow_delete = true;
  118. },
  119. init_list: function(auto_run) {
  120. var me = this;
  121. // init list
  122. this.make({
  123. method: 'webnotes.widgets.reportview.get',
  124. get_args: this.get_args,
  125. parent: this.wrapper,
  126. freeze: true,
  127. start: 0,
  128. page_length: this.page_length,
  129. show_filters: true,
  130. show_grid: true,
  131. new_doctype: this.doctype,
  132. allow_delete: this.allow_delete,
  133. no_result_message: this.make_no_result(),
  134. custom_new_doc: me.listview.make_new_doc || undefined,
  135. });
  136. // make_new_doc can be overridden so that default values can be prefilled
  137. // for example - communication list in customer
  138. $(this.wrapper).on("click", 'button[list_view_doc="'+me.doctype+'"]', function(){
  139. (me.listview.make_new_doc || me.make_new_doc)(me.doctype);
  140. });
  141. if((auto_run !== false) && (auto_run !== 0)) this.run();
  142. },
  143. run: function(more) {
  144. // set filter from route
  145. var route = wn.get_route();
  146. var me = this;
  147. if(route[2]) {
  148. $.each(wn.utils.get_args_dict_from_url(route[2]), function(key, val) {
  149. me.set_filter(key, val, true);
  150. });
  151. }
  152. this._super(more);
  153. },
  154. make_no_result: function() {
  155. var new_button = wn.boot.profile.can_create.indexOf(this.doctype)!=-1
  156. ? ('<hr><p><button class="btn btn-default btn-info" \
  157. list_view_doc="%(doctype)s">'+
  158. wn._('Make a new') + ' %(doctype_label)s</button></p>')
  159. : '';
  160. var no_result_message = repl('<div class="well">\
  161. <p>No %(doctype_label)s found</p>' + new_button + '</div>', {
  162. doctype_label: wn._(this.doctype),
  163. doctype: this.doctype,
  164. });
  165. return no_result_message;
  166. },
  167. render_row: function(row, data) {
  168. data.doctype = this.doctype;
  169. this.listview.render(row, data, this);
  170. },
  171. get_args: function() {
  172. var docstatus_list = this.can_submit ? $.map(this.$page.find('.show-docstatus :checked'),
  173. function(inp) {
  174. return $(inp).attr('data-docstatus');
  175. }) : []
  176. var args = {
  177. doctype: this.doctype,
  178. fields: this.listview.fields,
  179. filters: this.filter_list.get_filters(),
  180. docstatus: docstatus_list,
  181. order_by: this.listview.order_by || undefined,
  182. group_by: this.listview.group_by || undefined,
  183. }
  184. // apply default filters, if specified for a listing
  185. $.each((this.listview.default_filters || []), function(i, f) {
  186. args.filters.push(f);
  187. });
  188. return args;
  189. },
  190. add_delete_option: function() {
  191. var me = this;
  192. if(this.can_delete || this.listview.settings.selectable) {
  193. this.add_button(wn._('Delete'), function() { me.delete_items(); }, 'icon-remove');
  194. this.add_button(wn._('Select All'), function() {
  195. var checks = me.$page.find('.list-delete');
  196. checks.attr('checked', $(checks.get(0)).attr('checked') ? false : "checked");
  197. }, 'icon-ok');
  198. }
  199. },
  200. get_checked_items: function() {
  201. return $.map(this.$page.find('.list-delete:checked'), function(e) {
  202. return $(e).data('data');
  203. });
  204. },
  205. delete_items: function() {
  206. var me = this;
  207. var dl = this.get_checked_items();
  208. if(!dl.length)
  209. return;
  210. wn.confirm(wn._('This is permanent action and you cannot undo. Continue?'),
  211. function() {
  212. me.set_working(true);
  213. wn.call({
  214. method: 'webnotes.widgets.reportview.delete_items',
  215. args: {
  216. items: $.map(dl, function(d, i) { return d.name }),
  217. doctype: me.doctype
  218. },
  219. callback: function() {
  220. me.set_working(false);
  221. me.refresh();
  222. }
  223. })
  224. }
  225. );
  226. },
  227. init_stats: function() {
  228. var me = this;
  229. this.sidebar_stats = new wn.views.SidebarStats({
  230. doctype: this.doctype,
  231. stats: this.listview.stats,
  232. parent: me.$page.find('.layout-side-section'),
  233. set_filter: function(fieldname, label) {
  234. me.set_filter(fieldname, label);
  235. }
  236. })
  237. },
  238. set_filter: function(fieldname, label, no_run) {
  239. var filter = this.filter_list.get_filter(fieldname);
  240. if(filter) {
  241. var v = cstr(filter.field.get_parsed_value());
  242. if(v.indexOf(label)!=-1) {
  243. // already set
  244. return false;
  245. } else {
  246. // second filter set for this field
  247. if(fieldname=='_user_tags') {
  248. // and for tags
  249. this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label);
  250. } else {
  251. // or for rest using "in"
  252. filter.set_values(this.doctype, fieldname, 'in', v + ', ' + label);
  253. }
  254. }
  255. } else {
  256. // no filter for this item,
  257. // setup one
  258. if(fieldname=='_user_tags') {
  259. this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label);
  260. } else {
  261. this.filter_list.add_filter(this.doctype, fieldname, '=', label);
  262. }
  263. }
  264. if(!no_run)
  265. this.run();
  266. }
  267. });