// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // MIT License. See license.txt wn.views.ReportFactory = wn.views.Factory.extend({ make: function(route) { new wn.views.ReportViewPage(route[1], route[2]); } }); wn.views.ReportViewPage = Class.extend({ init: function(doctype, docname) { if(!wn.model.can_get_report(doctype)) { wn.show_not_permitted(wn.get_route_str()); return; }; wn.require("assets/js/slickgrid.min.js"); this.doctype = doctype; this.docname = docname; this.page_name = wn.get_route_str(); this.make_page(); var me = this; wn.model.with_doctype(this.doctype, function() { me.make_report_view(); if(me.docname) { wn.model.with_doc('Report', me.docname, function(r) { me.page.reportview.set_columns_and_filters( JSON.parse(wn.model.get("Report", me.docname)[0].json)); me.page.reportview.set_route_filters(); me.page.reportview.run(); }); } else { me.page.reportview.set_route_filters(); me.page.reportview.run(); } }); }, make_page: function() { var me = this; this.page = wn.container.add_page(this.page_name); wn.ui.make_app_page({parent:this.page, single_column:true}); wn.container.change_to(this.page_name); $(this.page).on('show', function(){ if(me.page.reportview.set_route_filters()) me.page.reportview.run(); }) }, make_report_view: function() { var module = locals.DocType[this.doctype].module; this.page.appframe.set_title(wn._(this.doctype)); this.page.appframe.add_module_icon(module, this.doctype) this.page.appframe.set_views_for(this.doctype, "report"); this.page.reportview = new wn.views.ReportView({ doctype: this.doctype, docname: this.docname, page: this.page, wrapper: $(this.page).find(".layout-main") }); } }); wn.views.ReportView = wn.ui.Listing.extend({ init: function(opts) { var me = this; $(this.page).find('.layout-main').html(wn._('Loading Report')+'...'); $(this.page).find('.layout-main').empty(); $.extend(this, opts); this.can_delete = wn.model.can_delete(me.doctype); this.tab_name = '`tab'+this.doctype+'`'; this.setup(); }, set_init_columns: function() { // pre-select mandatory columns var columns = [['name'], ['owner']]; $.each(wn.meta.docfield_list[this.doctype], function(i, df) { if(df.in_filter && df.fieldname!='naming_series' && df.fieldtype!='Table') { columns.push([df.fieldname]); } }); this.columns = columns; }, setup: function() { var me = this; this.page_title = wn._('Report')+ ': ' + wn._(this.docname ? (this.doctype + ' - ' + this.docname) : this.doctype); this.page.appframe.set_title(this.page_title) this.make({ appframe: this.page.appframe, method: 'webnotes.widgets.reportview.get', get_args: this.get_args, parent: $(this.page).find('.layout-main'), start: 0, page_length: 20, show_filters: true, new_doctype: this.doctype, allow_delete: true, }); this.make_delete(); this.make_column_picker(); this.make_sorter(); this.make_export(); this.set_init_columns(); this.make_save(); this.make_user_restrictions(); this.set_tag_and_status_filter(); }, set_init_columns: function() { // pre-select mandatory columns var columns = wn.defaults.get_default("_list_settings:" + this.doctype); if(!columns) { var columns = [['name', this.doctype],]; $.each(wn.meta.docfield_list[this.doctype], function(i, df) { if(df.in_filter && df.fieldname!='naming_series' && !in_list(wn.model.no_value_type, df.fieldname)) { columns.push([df.fieldname, df.parent]); } }); } this.columns = columns; }, // preset columns and filters from saved info set_columns_and_filters: function(opts) { var me = this; if(opts.columns) this.columns = opts.columns; if(opts.filters) $.each(opts.filters, function(i, f) { // f = [doctype, fieldname, condition, value] var df = wn.meta.get_docfield(f[0], f[1]); if (df && df.fieldtype == "Check") { var value = f[3] ? "Yes" : "No"; } else { var value = f[3]; } me.filter_list.add_filter(f[0], f[1], f[2], value); }); // first sort if(opts.sort_by) this.sort_by_select.val(opts.sort_by); if(opts.sort_order) this.sort_order_select.val(opts.sort_order); // second sort if(opts.sort_by_next) this.sort_by_next_select.val(opts.sort_by_next); if(opts.sort_order_next) this.sort_order_next_select.val(opts.sort_order_next); }, set_route_filters: function() { var me = this; if(wn.route_options) { me.filter_list.clear_filters(); $.each(wn.route_options, function(key, value) { me.filter_list.add_filter(me.doctype, key, "=", value); }); wn.route_options = null; return true; } }, // build args for query get_args: function() { var me = this; return { doctype: this.doctype, fields: $.map(this.columns, function(v) { return me.get_full_column_name(v) }), order_by: this.get_order_by(), filters: this.filter_list.get_filters(), docstatus: ['0','1','2'], with_childnames: 1 } }, get_order_by: function() { // first var order_by = this.get_selected_table_and_column(this.sort_by_select) + ' ' + this.sort_order_select.val(); // second if(this.sort_by_next_select.val()) { order_by += ', ' + this.get_selected_table_and_column(this.sort_by_next_select) + ' ' + this.sort_order_next_select.val(); } return order_by; }, get_selected_table_and_column: function(select) { return select.selected_doctype ? this.get_full_column_name([select.selected_fieldname, select.selected_doctype]) : ""; }, // get table_name.column_name get_full_column_name: function(v) { if(!v) return; return (v[1] ? ('`tab' + v[1] + '`') : this.tab_name) + '.' + v[0]; }, // build columns for slickgrid build_columns: function() { var me = this; return $.map(this.columns, function(c) { var docfield = wn.meta.docfield_map[c[1] || me.doctype][c[0]]; if(!docfield) { var docfield = wn.model.get_std_field(c[0]); if(c[0]=="name") { docfield.options = me.doctype; docfield.parent = me.doctype; } } coldef = { id: c[0], field: c[0], docfield: docfield, name: wn._(docfield ? docfield.label : toTitle(c[0])), width: (docfield ? cint(docfield.width) : 120) || 120, formatter: function(row, cell, value, columnDef, dataContext) { var docfield = columnDef.docfield; if(docfield.fieldname==="_user_tags") docfield.fieldtype = "Tag"; if(docfield.fieldname==="_comments") docfield.fieldtype = "Comment"; return wn.format(value, docfield, null, dataContext); } } return coldef; }); }, // render data render_list: function() { var me = this; var columns = this.get_columns(); // add sr in data $.each(this.data, function(i, v) { // add index v._idx = i+1; v.id = v._idx; }); var options = { enableCellNavigation: true, enableColumnReorder: false, }; if(this.slickgrid_options) { $.extend(options, this.slickgrid_options); } this.col_defs = columns; this.dataView = new Slick.Data.DataView(); this.set_data(this.data); var grid_wrapper = this.$w.find('.result-list'); // set height if not auto if(!options.autoHeight) grid_wrapper.css('height', '500px'); this.grid = new Slick.Grid(grid_wrapper .css('border', '1px solid #ccc') .css('border-top', '0px') .get(0), this.dataView, columns, options); this.grid.setSelectionModel(new Slick.CellSelectionModel()); this.grid.registerPlugin(new Slick.CellExternalCopyManager({ dataItemColumnValueExtractor: function(item, columnDef, value) { return item[columnDef.field]; } })); wn.slickgrid_tools.add_property_setter_on_resize(this.grid); if(this.start!=0 && !options.autoHeight) { this.grid.scrollRowIntoView(this.data.length-1); } this.grid.onDblClick.subscribe(function(e, args) { var row = me.dataView.getItem(args.row); var cell = me.grid.getColumns()[args.cell]; me.edit_cell(row, cell.docfield); }); this.dataView.onRowsChanged.subscribe(function (e, args) { me.grid.invalidateRows(args.rows); me.grid.render(); }); this.grid.onHeaderClick.subscribe(function(e, args) { if(e.target.className === "slick-resizable-handle") return; var df = args.column.docfield, sort_by = df.parent + "." + df.fieldname; if(sort_by===me.sort_by_select.val()) { me.sort_order_select.val(me.sort_order_select.val()==="asc" ? "desc" : "asc"); } else { me.sort_by_select.val(df.parent + "." + df.fieldname); me.sort_order_select.val("asc"); } me.run(); }); }, edit_cell: function(row, docfield) { if(wn.model.std_fields_list.indexOf(docfield.fieldname)!==-1) { wn.throw(wn._("Cannot edit standard fields")); } else if(wn.boot.profile.can_write.indexOf(this.doctype)===-1) { wn.throw(wn._("No permission to edit")); } var me = this; var d = new wn.ui.Dialog({ title: wn._("Edit") + " " + wn._(docfield.label), fields: [docfield, {"fieldtype": "Button", "label": "Update"}], }); d.get_input(docfield.fieldname).val(row[docfield.fieldname]); d.get_input("update").on("click", function() { wn.call({ method: "webnotes.client.set_value", args: { doctype: docfield.parent, name: row[docfield.parent===me.doctype ? "name" : docfield.parent+":name"], fieldname: docfield.fieldname, value: d.get_value(docfield.fieldname) }, callback: function(r) { if(!r.exc) { d.hide(); var doclist = r.message; $.each(me.dataView.getItems(), function(i, item) { if (item.name === doclist[0].name) { var new_item = $.extend({}, item, doclist[0]); $.each(doclist, function(i, doc) { if(item[doc.doctype + ":name"]===doc.name) { $.each(doc, function(k, v) { if(wn.model.std_fields_list.indexOf(k)===-1) { new_item[k] = v; } }) } }); me.dataView.updateItem(item.id, new_item); } }); } } }); }); d.show(); }, set_data: function() { this.dataView.beginUpdate(); this.dataView.setItems(this.data); this.dataView.endUpdate(); }, get_columns: function() { var std_columns = [{id:'_idx', field:'_idx', name: 'Sr.', width: 40, maxWidth: 40}]; if(this.can_delete) { std_columns = std_columns.concat([{ id:'_check', field:'_check', name: "", width: 30, maxWidth: 30, formatter: function(row, cell, value, columnDef, dataContext) { return repl("", { row: row, checked: (dataContext._checked ? "checked=\"checked\"" : "") }); } }]); } return std_columns.concat(this.build_columns()); }, // setup column picker make_column_picker: function() { var me = this; this.column_picker = new wn.ui.ColumnPicker(this); this.page.appframe.add_button(wn._('Pick Columns'), function() { me.column_picker.show(me.columns); }, 'icon-th-list'); }, set_tag_and_status_filter: function() { var me = this; this.$w.find('.result-list').on("click", ".label-info", function() { if($(this).attr("data-label")) { me.set_filter("_user_tags", $(this).attr("data-label")); } }); this.$w.find('.result-list').on("click", "[data-workflow-state]", function() { if($(this).attr("data-workflow-state")) { me.set_filter(me.state_fieldname, $(this).attr("data-workflow-state")); } }); }, // setup sorter make_sorter: function() { var me = this; this.sort_dialog = new wn.ui.Dialog({title:'Sorting Preferences'}); $(this.sort_dialog.body).html('
Sort By
\ \ \'+wn._('Then By (optional)')+'
\ \