您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

doclistview.js 10 KiB

13 年前
11 年前
13 年前
13 年前
13 年前
13 年前
13 年前
13 年前
13 年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. // MIT License. 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.tags_shown = false;
  29. this.label = (this.label.toLowerCase().substr(-4) == 'list') ?
  30. wn._(this.label) : (wn._(this.label) + ' ' + wn._('List'));
  31. this.make_page();
  32. this.setup();
  33. var me = this;
  34. $(this.page).on("show", function() {
  35. me.refresh();
  36. });
  37. },
  38. make_page: function() {
  39. var me = this;
  40. this.page.doclistview = this;
  41. this.$page = $(this.page).css({"min-height": "400px"});
  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 side-panel">\
  46. <h5 class="text-muted">Show</h5>\
  47. <div class="side-panel-body">\
  48. <div class="text-muted small"><input data-docstatus="0" type="checkbox" \
  49. checked="checked" /> '+wn._('Drafts')+'</div>\
  50. <div class="text-muted small"><input data-docstatus="1" type="checkbox" \
  51. checked="checked" /> '+wn._('Submitted')+'</div>\
  52. <div class="text-muted small"><input data-docstatus="2" type="checkbox" \
  53. /> '+wn._('Cancelled')+'</div></div>\
  54. </div>')
  55. .appendTo(this.$page.find(".layout-side-section"));
  56. this.$page.find(".layout-main-section")
  57. .css({"border-right":"1px solid #d7d7d7"})
  58. .parent().css({"margin-top":"-15px"});
  59. this.appframe = this.page.appframe;
  60. var module = locals.DocType[this.doctype].module;
  61. this.appframe.set_title(wn._(this.doctype) + " " + wn._("List"));
  62. this.appframe.add_module_icon(module, this.doctype, null, true);
  63. this.appframe.set_views_for(this.doctype, "list");
  64. },
  65. setup: function() {
  66. this.can_delete = wn.model.can_delete(this.doctype);
  67. this.meta = locals.DocType[this.doctype];
  68. this.$page.find('.wnlist-area').empty(),
  69. this.setup_listview();
  70. this.setup_docstatus_filter();
  71. this.init_list();
  72. this.init_stats();
  73. this.init_minbar();
  74. this.show_match_help();
  75. if(this.listview.settings.onload) {
  76. this.listview.settings.onload(this);
  77. }
  78. this.make_help();
  79. this.$page.find(".show_filters").css({"padding":"15px", "margin":"0px -15px"});
  80. var me = this;
  81. // this.$w.on("render-complete", function() {
  82. // me.set_sidebar_height();
  83. // });
  84. },
  85. set_sidebar_height: function() {
  86. var h_main = this.$page.find(".layout-main-section").height();
  87. var h_side = this.$page.find(".layout-side-section").height();
  88. if(h_side > h_main)
  89. this.$page.find(".layout-main-section").css({"min-height": h_side});
  90. },
  91. show_match_help: function() {
  92. var me = this;
  93. var match_rules = wn.perm.get_match_rules(this.doctype);
  94. if(keys(match_rules).length) {
  95. var match_text = []
  96. $.each(match_rules, function(key, values) {
  97. if(values.length==0) {
  98. match_text.push(wn._(key) + wn._(" is not set"));
  99. } else if(values.length) {
  100. match_text.push(wn._(key) + " = " + wn.utils.comma_or(values));
  101. }
  102. });
  103. wn.utils.set_footnote(this, this.$page.find(".layout-main-section"),
  104. "<p>" + wn._("Showing only for") + ":</p><ul>"
  105. + $.map(match_text, function(txt) { return "<li>"+txt+"</li>" }).join("")) + "</ul>";
  106. $(this.footnote_area).css({"margin-top":"0px", "margin-bottom":"20px"});
  107. }
  108. },
  109. make_help: function() {
  110. // Help
  111. if(this.meta.description) {
  112. this.appframe.add_help_button(this.meta.description);
  113. }
  114. },
  115. setup_docstatus_filter: function() {
  116. var me = this;
  117. this.can_submit = $.map(locals.DocPerm || [], function(d) {
  118. if(d.parent==me.meta.name && d.submit) return 1
  119. else return null;
  120. }).length;
  121. if(this.can_submit) {
  122. this.$page.find('.show-docstatus').removeClass('hide');
  123. this.$page.find('.show-docstatus input').click(function() {
  124. me.run();
  125. })
  126. }
  127. },
  128. setup_listview: function() {
  129. this.listview = wn.views.get_listview(this.doctype, this);
  130. this.wrapper = this.$page.find('.wnlist-area');
  131. this.page_length = 20;
  132. this.allow_delete = true;
  133. },
  134. init_list: function(auto_run) {
  135. var me = this;
  136. // init list
  137. this.make({
  138. method: 'webnotes.widgets.reportview.get',
  139. get_args: this.get_args,
  140. parent: this.wrapper,
  141. freeze: true,
  142. start: 0,
  143. page_length: this.page_length,
  144. show_filters: true,
  145. show_grid: true,
  146. new_doctype: this.doctype,
  147. allow_delete: this.allow_delete,
  148. no_result_message: this.make_no_result(),
  149. custom_new_doc: me.listview.make_new_doc || undefined,
  150. });
  151. // make_new_doc can be overridden so that default values can be prefilled
  152. // for example - communication list in customer
  153. $(this.wrapper).on("click", 'button[list_view_doc="'+me.doctype+'"]', function(){
  154. (me.listview.make_new_doc || me.make_new_doc).apply(me, [me.doctype]);
  155. });
  156. if((auto_run !== false) && (auto_run !== 0))
  157. this.refresh();
  158. },
  159. refresh: function() {
  160. var me = this;
  161. if(wn.route_options) {
  162. me.filter_list.clear_filters();
  163. $.each(wn.route_options, function(key, value) {
  164. me.filter_list.add_filter(me.doctype, key, "=", value);
  165. });
  166. wn.route_options = null;
  167. me.run();
  168. } else if(me.dirty) {
  169. me.run();
  170. } else {
  171. if(new Date() - (me.last_updated_on || 0) > 30000) {
  172. // older than 5 mins, refresh
  173. me.run();
  174. }
  175. }
  176. },
  177. run: function(more) {
  178. // set filter from route
  179. var route = wn.get_route();
  180. var me = this;
  181. if(route[2]) {
  182. $.each(wn.utils.get_args_dict_from_url(route[2]), function(key, val) {
  183. me.set_filter(key, val, true);
  184. });
  185. }
  186. this.last_updated_on = new Date();
  187. this._super(more);
  188. },
  189. make_no_result: function() {
  190. var new_button = wn.boot.profile.can_create.indexOf(this.doctype)!=-1
  191. ? ('<hr><p><button class="btn btn-primary" \
  192. list_view_doc="%(doctype)s">'+
  193. wn._('Make a new') + ' %(doctype_label)s</button></p>')
  194. : '';
  195. var no_result_message = repl('<div class="well" style="margin-top: 20px;">\
  196. <p>' + wn._("No") + ' %(doctype_label)s ' + wn._("found") + '</p>' + new_button + '</div>', {
  197. doctype_label: wn._(this.doctype),
  198. doctype: this.doctype,
  199. });
  200. return no_result_message;
  201. },
  202. render_row: function(row, data) {
  203. data.doctype = this.doctype;
  204. this.listview.render(row, data, this);
  205. },
  206. get_args: function() {
  207. var docstatus_list = this.can_submit ? $.map(this.$page.find('.show-docstatus :checked'),
  208. function(inp) {
  209. return $(inp).attr('data-docstatus');
  210. }) : []
  211. var args = {
  212. doctype: this.doctype,
  213. fields: this.listview.fields,
  214. filters: this.filter_list.get_filters(),
  215. docstatus: docstatus_list,
  216. order_by: this.listview.order_by || undefined,
  217. group_by: this.listview.group_by || undefined,
  218. }
  219. // apply default filters, if specified for a listing
  220. $.each((this.listview.default_filters || []), function(i, f) {
  221. args.filters.push(f);
  222. });
  223. return args;
  224. },
  225. init_minbar: function() {
  226. var me = this;
  227. this.appframe.add_icon_btn("2", 'icon-tag', wn._('Show Tags'), function() { me.toggle_tags(); });
  228. this.wrapper.on("click", ".list-tag-preview", function() { me.toggle_tags(); });
  229. if(this.can_delete || this.listview.settings.selectable) {
  230. this.appframe.add_icon_btn("2", 'icon-remove', wn._('Delete'), function() { me.delete_items(); });
  231. this.appframe.add_icon_btn("2", 'icon-ok', wn._('Select All'), function() {
  232. me.$page.find('.list-delete').prop("checked",
  233. me.$page.find('.list-delete:checked').length ? false : true);
  234. });
  235. }
  236. if(wn.model.can_import(this.doctype)) {
  237. this.appframe.add_icon_btn("2", "icon-upload", wn._("Import"), function() {
  238. wn.set_route("data-import-tool", {
  239. doctype: me.doctype
  240. })
  241. });
  242. }
  243. if(in_list(user_roles, "System Manager")) {
  244. this.appframe.add_icon_btn("2", "icon-glass", wn._("Customize"), function() {
  245. wn.set_route("Form", "Customize Form", {
  246. doctype: me.doctype
  247. })
  248. });
  249. }
  250. },
  251. toggle_tags: function() {
  252. if(this.tags_shown) {
  253. $(".tag-row").addClass("hide");
  254. this.tags_shown=false;
  255. } else {
  256. $(".tag-row").removeClass("hide");
  257. this.tags_shown=true;
  258. }
  259. },
  260. get_checked_items: function() {
  261. return $.map(this.$page.find('.list-delete:checked'), function(e) {
  262. return $(e).data('data');
  263. });
  264. },
  265. delete_items: function() {
  266. var me = this;
  267. var dl = this.get_checked_items();
  268. if(!dl.length)
  269. return;
  270. wn.confirm(wn._('This is permanent action and you cannot undo. Continue?'),
  271. function() {
  272. me.set_working(true);
  273. return wn.call({
  274. method: 'webnotes.widgets.reportview.delete_items',
  275. args: {
  276. items: $.map(dl, function(d, i) { return d.name }),
  277. doctype: me.doctype
  278. },
  279. callback: function() {
  280. me.set_working(false);
  281. me.dirty = true;
  282. me.refresh();
  283. }
  284. })
  285. }
  286. );
  287. },
  288. init_stats: function() {
  289. var me = this;
  290. this.sidebar_stats = new wn.views.SidebarStats({
  291. doctype: this.doctype,
  292. stats: this.listview.stats,
  293. parent: this.$page.find('.layout-side-section'),
  294. set_filter: function(fieldname, label) {
  295. me.set_filter(fieldname, label);
  296. },
  297. doclistview: this
  298. })
  299. },
  300. set_filter: function(fieldname, label, no_run) {
  301. var filter = this.filter_list.get_filter(fieldname);
  302. if(filter) {
  303. var v = cstr(filter.field.get_parsed_value());
  304. if(v.indexOf(label)!=-1) {
  305. // already set
  306. return false;
  307. } else {
  308. // second filter set for this field
  309. if(fieldname=='_user_tags') {
  310. // and for tags
  311. this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label);
  312. } else {
  313. // or for rest using "in"
  314. filter.set_values(this.doctype, fieldname, 'in', v + ', ' + label);
  315. }
  316. }
  317. } else {
  318. // no filter for this item,
  319. // setup one
  320. if(fieldname=='_user_tags') {
  321. this.filter_list.add_filter(this.doctype, fieldname, 'like', '%' + label);
  322. } else {
  323. this.filter_list.add_filter(this.doctype, fieldname, '=', label);
  324. }
  325. }
  326. if(!no_run)
  327. this.run();
  328. }
  329. });