Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

352 řádky
10 KiB

  1. wn.views.ReportViewPage = Class.extend({
  2. init: function(doctype, docname) {
  3. this.doctype = doctype;
  4. this.docname = docname;
  5. this.page_name = wn.get_route_str();
  6. this.make_page();
  7. var me = this;
  8. wn.model.with_doctype(doctype, function() {
  9. me.make_report_view();
  10. if(docname) {
  11. wn.model.with_doc('Report', docname, function(r) {
  12. me.reportview.set_columns_and_filters(JSON.parse(locals['Report'][docname].json));
  13. me.reportview.run();
  14. });
  15. } else {
  16. me.reportview.run();
  17. }
  18. });
  19. },
  20. make_page: function() {
  21. this.page = wn.container.add_page(this.page_name);
  22. wn.ui.make_app_page({parent:this.page,
  23. single_column:true});
  24. wn.container.change_to(this.page_name);
  25. },
  26. make_report_view: function() {
  27. this.page.appframe.add_module_tab(locals.DocType[this.doctype].module);
  28. this.reportview = new wn.views.ReportView(this.doctype, this.docname, this.page)
  29. }
  30. })
  31. wn.views.ReportView = wn.ui.Listing.extend({
  32. init: function(doctype, docname, page) {
  33. var me = this;
  34. $(page).find('.layout-main').html('Loading Report...');
  35. $(page).find('.layout-main').empty();
  36. this.doctype = doctype;
  37. this.docname = docname;
  38. this.page = page;
  39. this.tab_name = '`tab'+doctype+'`';
  40. this.setup();
  41. },
  42. set_init_columns: function() {
  43. // pre-select mandatory columns
  44. var columns = [['name'], ['owner']];
  45. $.each(wn.meta.docfield_list[this.doctype], function(i, df) {
  46. if(df.in_filter && df.fieldname!='naming_series' && df.fieldtype!='Table') {
  47. columns.push([df.fieldname]);
  48. }
  49. });
  50. this.columns = columns;
  51. },
  52. setup: function() {
  53. var me = this;
  54. this.page_title = 'Report: ' + (this.docname ? (this.doctype + ' - ' + this.docname) : this.doctype);
  55. this.page.appframe.set_title(this.page_title)
  56. this.make({
  57. appframe: this.page.appframe,
  58. method: 'webnotes.widgets.doclistview.get',
  59. get_args: this.get_args,
  60. parent: $(this.page).find('.layout-main'),
  61. start: 0,
  62. page_length: 20,
  63. show_filters: true,
  64. new_doctype: this.doctype,
  65. allow_delete: true,
  66. });
  67. this.make_column_picker();
  68. this.make_sorter();
  69. this.make_export();
  70. this.set_init_columns();
  71. this.make_save();
  72. },
  73. // preset columns and filters from saved info
  74. set_columns_and_filters: function(opts) {
  75. var me = this;
  76. if(opts.columns) this.columns = opts.columns;
  77. if(opts.filters) $.each(opts.filters, function(i, f) {
  78. // fieldname, condition, value
  79. me.filter_list.add_filter(f[0], f[1], f[2], f[3]);
  80. });
  81. // first sort
  82. if(opts.sort_by) this.sort_by_select.val(opts.sort_by);
  83. if(opts.sort_order) this.sort_order_select.val(opts.sort_order);
  84. // second sort
  85. if(opts.sort_by_next) this.sort_by_next_select.val(opts.sort_by_next);
  86. if(opts.sort_order_next) this.sort_order_next_select.val(opts.sort_order_next);
  87. },
  88. // build args for query
  89. get_args: function() {
  90. var me = this;
  91. return {
  92. doctype: this.doctype,
  93. fields: $.map(this.columns, function(v) { return me.get_full_column_name(v) }),
  94. order_by: this.get_order_by(),
  95. filters: this.filter_list.get_filters(),
  96. docstatus: ['0','1','2']
  97. }
  98. },
  99. get_order_by: function() {
  100. // first
  101. var order_by = this.get_selected_table_and_column(this.sort_by_select)
  102. + ' ' + this.sort_order_select.val();
  103. // second
  104. if(this.sort_by_next_select.val()) {
  105. order_by += ', ' + this.get_selected_table_and_column(this.sort_by_next_select)
  106. + ' ' + this.sort_order_next_select.val();
  107. }
  108. return order_by;
  109. },
  110. get_selected_table_and_column: function($select) {
  111. return this.get_full_column_name([$select.find('option:selected').attr('fieldname'),
  112. $select.find('option:selected').attr('table')])
  113. },
  114. // get table_name.column_name
  115. get_full_column_name: function(v) {
  116. return (v[1] ? ('`tab' + v[1] + '`') : this.tab_name) + '.' + v[0];
  117. },
  118. // build columns for slickgrid
  119. build_columns: function() {
  120. var me = this;
  121. return $.map(this.columns, function(c) {
  122. var docfield = wn.meta.docfield_map[c[1] || me.doctype][c[0]];
  123. if(!docfield) {
  124. var docfield = wn.model.get_std_field(c[0]);
  125. if(c[0]=="name") {
  126. docfield.options = me.doctype;
  127. }
  128. }
  129. coldef = {
  130. id: c[0],
  131. field: c[0],
  132. docfield: docfield,
  133. name: (docfield ? docfield.label : toTitle(c[0])),
  134. width: (docfield ? cint(docfield.width) : 120) || 120,
  135. formatter: function(row, cell, value, columnDef, dataContext) {
  136. var docfield = columnDef.docfield;
  137. return wn.form.get_formatter(docfield ? docfield.fieldtype : "Data")(value, docfield);
  138. }
  139. }
  140. return coldef;
  141. });
  142. },
  143. // render data
  144. render_list: function() {
  145. var me = this;
  146. //this.gridid = wn.dom.set_unique_id()
  147. var columns = [{id:'_idx', field:'_idx', name: 'Sr.', width: 40}].concat(this.build_columns());
  148. // add sr in data
  149. $.each(this.data, function(i, v) {
  150. // add index
  151. v._idx = i+1;
  152. });
  153. var options = {
  154. enableCellNavigation: true,
  155. enableColumnReorder: false
  156. };
  157. var grid = new Slick.Grid(this.$w.find('.result-list')
  158. .css('border', '1px solid grey')
  159. .css('height', '500px')
  160. .get(0), this.data,
  161. columns, options);
  162. },
  163. // setup column picker
  164. make_column_picker: function() {
  165. var me = this;
  166. this.column_picker = new wn.ui.ColumnPicker(this);
  167. this.page.appframe.add_button('Pick Columns', function() {
  168. me.column_picker.show(me.columns);
  169. }, 'icon-th-list');
  170. },
  171. // setup sorter
  172. make_sorter: function() {
  173. var me = this;
  174. this.sort_dialog = new wn.ui.Dialog({title:'Sorting Preferences'});
  175. $(this.sort_dialog.body).html('<p class="help">Sort By</p>\
  176. <div class="sort-column"></div>\
  177. <div><select class="sort-order" style="margin-top: 10px; width: 60%;">\
  178. <option value="asc">Ascending</option>\
  179. <option value="desc">Descending</option>\
  180. </select></div>\
  181. <hr><p class="help">Then By (optional)</p>\
  182. <div class="sort-column-1"></div>\
  183. <div><select class="sort-order-1" style="margin-top: 10px; width: 60%;">\
  184. <option value="asc">Ascending</option>\
  185. <option value="desc">Descending</option>\
  186. </select></div><hr>\
  187. <div><button class="btn btn-small btn-info">Update</div>');
  188. // first
  189. this.sort_by_select = new wn.ui.FieldSelect($(this.sort_dialog.body).find('.sort-column'),
  190. this.doctype).$select;
  191. this.sort_by_select.css('width', '60%');
  192. this.sort_order_select = $(this.sort_dialog.body).find('.sort-order');
  193. // second
  194. this.sort_by_next_select = new wn.ui.FieldSelect($(this.sort_dialog.body).find('.sort-column-1'),
  195. this.doctype, null, true).$select;
  196. this.sort_by_next_select.css('width', '60%');
  197. this.sort_order_next_select = $(this.sort_dialog.body).find('.sort-order-1');
  198. // initial values
  199. this.sort_by_select.val('modified');
  200. this.sort_order_select.val('desc');
  201. this.sort_by_next_select.val('');
  202. this.sort_order_next_select.val('desc');
  203. // button actions
  204. this.page.appframe.add_button('Sort By', function() {
  205. me.sort_dialog.show();
  206. }, 'icon-arrow-down');
  207. $(this.sort_dialog.body).find('.btn-info').click(function() {
  208. me.sort_dialog.hide();
  209. me.run();
  210. });
  211. },
  212. // setup export
  213. make_export: function() {
  214. var me = this;
  215. if(wn.user.is_report_manager()) {
  216. this.page.appframe.add_button('Export', function() {
  217. var args = me.get_args();
  218. args.cmd = 'webnotes.widgets.doclistview.export_query'
  219. open_url_post(wn.request.url, args);
  220. }, 'icon-download-alt');
  221. }
  222. },
  223. // save
  224. make_save: function() {
  225. var me = this;
  226. if(wn.user.is_report_manager()) {
  227. this.page.appframe.add_button('Save', function() {
  228. // name
  229. if(me.docname) {
  230. var name = me.docname
  231. } else {
  232. var name = prompt('Select Report Name');
  233. if(!name) {
  234. return;
  235. }
  236. }
  237. // callback
  238. wn.call({
  239. method: 'webnotes.widgets.doclistview.save_report',
  240. args: {
  241. name: name,
  242. doctype: me.doctype,
  243. json: JSON.stringify({
  244. filters: me.filter_list.get_filters(),
  245. columns: me.columns,
  246. sort_by: me.sort_by_select.val(),
  247. sort_order: me.sort_order_select.val(),
  248. sort_by_next: me.sort_by_next_select.val(),
  249. sort_order_next: me.sort_order_next_select.val()
  250. })
  251. },
  252. callback: function(r) {
  253. if(r.exc) return;
  254. if(r.message != me.docname)
  255. wn.set_route('Report2', me.doctype, r.message);
  256. }
  257. });
  258. }, 'icon-upload');
  259. }
  260. }
  261. });
  262. wn.ui.ColumnPicker = Class.extend({
  263. init: function(list) {
  264. this.list = list;
  265. this.doctype = list.doctype;
  266. this.selects = {};
  267. },
  268. show: function(columns) {
  269. wn.require('lib/js/lib/jquery/jquery.ui.sortable.js');
  270. var me = this;
  271. if(!this.dialog) {
  272. this.dialog = new wn.ui.Dialog({
  273. title: 'Pick Columns',
  274. width: '400'
  275. });
  276. }
  277. $(this.dialog.body).html('<div class="help">Drag to sort columns</div>\
  278. <div class="column-list"></div>\
  279. <div><button class="btn btn-small btn-add"><i class="icon-plus"></i>\
  280. Add Column</button></div>\
  281. <hr>\
  282. <div><button class="btn btn-small btn-info">Update</div>');
  283. // show existing
  284. $.each(columns, function(i, c) {
  285. me.add_column(c);
  286. });
  287. $(this.dialog.body).find('.column-list').sortable();
  288. // add column
  289. $(this.dialog.body).find('.btn-add').click(function() {
  290. me.add_column(['name']);
  291. });
  292. // update
  293. $(this.dialog.body).find('.btn-info').click(function() {
  294. me.dialog.hide();
  295. // selected columns as list of [column_name, table_name]
  296. me.list.columns = [];
  297. $(me.dialog.body).find('select').each(function() {
  298. var $selected = $(this).find('option:selected');
  299. me.list.columns.push([$selected.attr('fieldname'),
  300. $selected.attr('table')]);
  301. })
  302. me.list.run();
  303. });
  304. this.dialog.show();
  305. },
  306. add_column: function(c) {
  307. var w = $('<div style="padding: 5px 5px 5px 35px; background-color: #eee; width: 70%; \
  308. margin-bottom: 10px; border-radius: 3px; cursor: move;">\
  309. <a class="close" style="margin-top: 5px;">&times</a>\
  310. </div>')
  311. .appendTo($(this.dialog.body).find('.column-list'));
  312. var fieldselect = new wn.ui.FieldSelect(w, this.doctype);
  313. fieldselect.$select.css('width', '90%').val((c[1] || this.doctype) + "." + c[0]);
  314. w.find('.close').click(function() {
  315. $(this).parent().remove();
  316. });
  317. }
  318. });