You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

344 rivejä
9.9 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. wn.provide('wn.pages.doclistview');
  23. wn.provide('wn.doclistviews');
  24. wn.pages.doclistview.pages = {};
  25. wn.pages.doclistview.show = function(doctype) {
  26. var pagename = doctype + ' List';
  27. if(!wn.pages.doclistview.pages[pagename]) {
  28. var page = page_body.add_page(pagename);
  29. page.doclistview = new wn.pages.DocListView(doctype, page);
  30. wn.pages.doclistview.pages[pagename] = page;
  31. }
  32. page_body.change_to(pagename);
  33. }
  34. wn.pages.DocListView = Class.extend({
  35. init: function(doctype, page) {
  36. this.doctype = doctype;
  37. this.wrapper = page;
  38. this.label = get_doctype_label(doctype);
  39. this.label = (this.label.toLowerCase().substr(-4) == 'list') ?
  40. this.label : (this.label + ' List')
  41. this.make();
  42. this.load_doctype();
  43. },
  44. make: function() {
  45. var me = this;
  46. $(this.wrapper).html('<div class="layout-wrapper layout-wrapper-background">\
  47. <div class="layout-main-section">\
  48. <a class="close" onclick="window.history.back();">&times;</a>\
  49. <h1>List</h1>\
  50. <hr>\
  51. <div id="list-filters"></div>\
  52. <button class="btn btn-small btn-info run-btn" style="margin-top: 11px">\
  53. <i class="icon-refresh icon-white"></i> Refresh</button>\
  54. <div id="list-body"></div>\
  55. </div>\
  56. <div class="layout-side-section">\
  57. </div>\
  58. <div style="clear: both"></div>\
  59. </div>');
  60. // filter button
  61. $(this.wrapper).find('.run-btn').click(function() {
  62. me.list.run();
  63. });
  64. $(this.wrapper).find('h1').html(this.label);
  65. },
  66. load_doctype: function() {
  67. var me = this;
  68. wn.call({
  69. method: 'webnotes.widgets.form.load.getdoctype',
  70. args: {doctype: me.doctype},
  71. callback: function() {
  72. if(locals.DocType[me.doctype].__listjs) {
  73. eval(locals.DocType[me.doctype].__listjs);
  74. me.listview = wn.doclistviews[me.doctype];
  75. } else {
  76. me.listview = {}
  77. }
  78. if(!me.listview.fields)
  79. me.listview.fields = ['name', 'modified', 'owner'];
  80. if(!me.listview.render)
  81. me.listview.render = me.default_render;
  82. me.make_filters();
  83. me.make_list();
  84. }
  85. });
  86. },
  87. make_filters: function() {
  88. this.filter_list = new wn.ui.FilterList(this, $('#list-filters').get(0), this.doctype);
  89. },
  90. make_list: function() {
  91. var me = this;
  92. this.list = new wn.widgets.Listing({
  93. parent: $('#list-body').get(0),
  94. method: 'webnotes.widgets.doclistview.get',
  95. args: {
  96. doctype: this.doctype,
  97. subject: locals.DocType[this.doctype].subject,
  98. fields: JSON.stringify(me.listview.fields),
  99. },
  100. get_args: function() {
  101. return {filters: JSON.stringify(me.filter_list.get_filters())}
  102. },
  103. render_row: function(row, data) {
  104. data.fullname = wn.user_info(data.owner).fullname;
  105. data.avatar = wn.user_info(data.owner).image;
  106. data.when = dateutil.comment_when(data.modified);
  107. data.doctype = me.doctype;
  108. me.listview.render(row, data, me);
  109. },
  110. hide_refresh: true
  111. });
  112. this.list.run();
  113. },
  114. default_render: function(row, data) {
  115. $(row).html(repl('<span class="avatar-small"><img src="%(avatar)s" /></span>\
  116. <a href="#!Form/%(doctype)s/%(name)s">%(name)s</span>\
  117. <span style="float:right; font-size: 11px; color: #888">%(when)s</span>', data))
  118. .addClass('list-row');
  119. }
  120. });
  121. wn.require('lib/css/ui/filter.css');
  122. wn.ui.FilterList = Class.extend({
  123. init: function(list_obj, parent, doctype) {
  124. this.filters = [];
  125. this.list_obj = list_obj;
  126. this.doctype = doctype;
  127. this.make(parent);
  128. this.set_events();
  129. },
  130. make: function(parent) {
  131. $(parent).html('<div>\
  132. <span class="link_type set_filters">Filter this list</span>\
  133. </div>\
  134. <div class="show_filters well">\
  135. <div class="filter_area"></div>\
  136. <div>\
  137. <button class="btn btn-small add-filter-btn">\
  138. <i class="icon-plus"></i> Add Filter</button>\
  139. </div>\
  140. </div>');
  141. this.$w = $(parent);
  142. },
  143. set_events: function() {
  144. var me = this;
  145. // show filters
  146. this.$w.find('.set_filters').bind('click', function() {
  147. me.$w.find('.show_filters').slideToggle();
  148. if(!me.filters.length)
  149. me.add_filter();
  150. });
  151. // show filters
  152. this.$w.find('.add-filter-btn').bind('click', function() {
  153. me.add_filter();
  154. });
  155. },
  156. add_filter: function(fieldname, condition, value) {
  157. this.filters.push(new wn.ui.Filter(this, this.doctype, fieldname, condition, value));
  158. },
  159. get_filters: function() {
  160. // get filter values as dict
  161. var values = [];
  162. $.each(this.filters, function(i, f) {
  163. if(f.filter_field)
  164. values.push(f.get_value());
  165. })
  166. return values;
  167. }
  168. });
  169. wn.ui.Filter = Class.extend({
  170. init: function(flist, doctype, fieldname, condition, value) {
  171. flist.$w.find('.filter_area').append('<div class="list_filter">\
  172. <select class="fieldname_select"></select>\
  173. <select class="condition">\
  174. <option value="=">Equals</option>\
  175. <option value="like">Like</option>\
  176. <option value=">=">Greater or equals</option>\
  177. <option value=">=">Less or equals</option>\
  178. <option value=">">Greater than</option>\
  179. <option value="<">Less than</option>\
  180. <option value="!=">Not equals</option>\
  181. </select>\
  182. <span class="filter_field"></span>\
  183. <a class="close">&times;</a>\
  184. </div>');
  185. this.fields_by_name = {};
  186. this.flist = flist;
  187. this.$w = this.flist.$w.find('.list_filter:last-child');
  188. this.doctype = doctype;
  189. this.fieldname = fieldname;
  190. this.condition = condition;
  191. this.value = value;
  192. this.set_events();
  193. },
  194. set_events: function() {
  195. var me = this;
  196. // render fields
  197. this.render_field_select();
  198. this.$w.find('.fieldname_select').bind('change', function() {
  199. me.set_field(this.value);
  200. });
  201. this.$w.find('a.close').bind('click', function() {
  202. me.$w.css('display','none');
  203. var value = me.filter_field.get_value();
  204. me.filter_field = null;
  205. if(!me.flist.get_filters().length) {
  206. me.flist.$w.find('.set_filters').toggle(true);
  207. me.flist.$w.find('.show_filters').toggle(false);
  208. me.list_obj.list.run();
  209. }
  210. if(value) {
  211. me.list_obj.list.run();
  212. }
  213. return false;
  214. });
  215. // set the field
  216. if(me.fieldname) {
  217. // presents given (could be via tags!)
  218. me.set_field(me.fieldname);
  219. if(me.condition) me.$w.find('.condition').val(me.condition)
  220. if(me.value) me.filter_field.set_input(me.value)
  221. } else {
  222. me.set_field('name');
  223. }
  224. },
  225. render_field_select: function() {
  226. var me = this;
  227. var $fs = me.$w.find('.fieldname_select');
  228. me.table_fields = [];
  229. var std_filters = [
  230. {fieldname:'name', fieldtype:'Data', label:'ID', parent:me.doctype},
  231. {fieldname:'modified', fieldtype:'Date', label:'Last Modified', parent:me.doctype},
  232. {fieldname:'owner', fieldtype:'Data', label:'Created By', parent:me.doctype},
  233. {fieldname:'_user_tags', fieldtype:'Data', label:'Tags', parent:me.doctype}
  234. ];
  235. // main table
  236. $.each(std_filters.concat(fields_list[me.doctype]), function(i, df) {
  237. me.add_field_option(df, $fs);
  238. });
  239. // child tables
  240. $.each(me.table_fields, function(i,table_df) {
  241. if(table_df.options) {
  242. $.each(fields_list[table_df.options], function(i, df) {
  243. me.add_field_option(df, $fs);
  244. });
  245. }
  246. })
  247. },
  248. add_field_option: function(df, $fs) {
  249. var me = this;
  250. if(df.parent==me.doctype) {
  251. var label = df.label;
  252. var table = get_label_doctype(me.doctype);
  253. if(df.fieldtype=='Table') me.table_fields.push(df);
  254. } else {
  255. var label = df.label + ' (' + df.parent + ')';
  256. var table = df.parent;
  257. }
  258. if(wn.model.no_value_type.indexOf(df.fieldtype)==-1 &&
  259. !me.fields_by_name[df.fieldname]) {
  260. $fs.append($('<option>', {
  261. value: df.fieldname,
  262. table: table
  263. }).text(label));
  264. me.fields_by_name[df.fieldname] = df;
  265. }
  266. },
  267. set_field: function(fieldname) {
  268. var me = this;
  269. // set in fieldname (again)
  270. me.$w.find('.fieldname_select').val(fieldname);
  271. wn.require('lib/js/legacy/widgets/form/fields.js');
  272. var field_area = me.$w.find('.filter_field').get(0);
  273. field_area.innerHTML = '';
  274. var df = me.fields_by_name[fieldname];
  275. df.original_type = df.fieldtype;
  276. df.description = '';
  277. if(df.fieldtype=='Check') {
  278. df.fieldtype='Select';
  279. df.options='No\nYes';
  280. } else if(['Text','Text Editor','Code','Link'].indexOf(df.fieldtype)!=-1) {
  281. df.fieldtype = 'Data';
  282. }
  283. f = make_field(me.fields_by_name[fieldname], null, field_area, null, 0, 1);
  284. f.df.single_select = 1;
  285. f.not_in_form = 1;
  286. f.with_label = 0;
  287. f.refresh();
  288. me.filter_field = f;
  289. // set as "like" for data fields
  290. if(df.fieldtype=='Data') {
  291. me.$w.find('.condition').val('like');
  292. } else {
  293. me.$w.find('.condition').val('=');
  294. }
  295. },
  296. get_value: function() {
  297. var me = this;
  298. var val = me.filter_field.get_value();
  299. var cond = me.$w.find('.condition').val();
  300. if(me.filter_field.df.original_type == 'Check') {
  301. val = (val=='Yes' ? 1 :0);
  302. }
  303. if(cond=='like') {
  304. val = val + '%';
  305. }
  306. return [me.$w.find('.fieldname_select option:selected').attr('table'),
  307. me.filter_field.df.fieldname, me.$w.find('.condition').val(), val];
  308. }
  309. });