Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 1 | frappe.pages["leaderboard"].on_page_load = function (wrapper) { |
| 2 | frappe.leaderboard = new frappe.Leaderboard(wrapper); |
| 3 | } |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 4 | |
| 5 | frappe.Leaderboard = Class.extend({ |
| 6 | |
| 7 | init: function (parent) { |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 8 | frappe.ui.make_app_page({ |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 9 | parent: parent, |
| 10 | title: "Leaderboard", |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 11 | single_column: false |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 12 | }); |
| 13 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 14 | this.parent = parent; |
| 15 | this.page = this.parent.page; |
| 16 | this.page.sidebar.html(`<ul class="module-sidebar-nav overlay-sidebar nav nav-pills nav-stacked"></ul>`); |
| 17 | this.$sidebar_list = this.page.sidebar.find('ul'); |
| 18 | |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 19 | // const list of doctypes |
vishdha | 09acb77 | 2018-02-20 12:44:11 +0530 | [diff] [blame] | 20 | this.doctypes = ["Customer", "Item", "Supplier", "Sales Partner","Sales Person"]; |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 21 | this.timespans = ["Week", "Month", "Quarter", "Year"]; |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 22 | this.filters = { |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 23 | "Customer": ["total_sales_amount", "total_qty_sold", "outstanding_amount", ], |
| 24 | "Item": ["total_sales_amount", "total_qty_sold", "total_purchase_amount", |
| 25 | "total_qty_purchased", "available_stock_qty", "available_stock_value"], |
| 26 | "Supplier": ["total_purchase_amount", "total_qty_purchased", "outstanding_amount"], |
Zlash65 | fa5ecb0 | 2018-04-22 12:11:01 +0530 | [diff] [blame] | 27 | "Sales Partner": ["total_sales_amount", "total_commission"], |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 28 | "Sales Person": ["total_sales_amount"], |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 29 | }; |
| 30 | |
| 31 | // for saving current selected filters |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 32 | // TODO: revert to 0 index for doctype and timespan, and remove preset down |
| 33 | const _initial_doctype = this.doctypes[0]; |
| 34 | const _initial_timespan = this.timespans[0]; |
| 35 | const _initial_filter = this.filters[_initial_doctype]; |
| 36 | |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 37 | this.options = { |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 38 | selected_doctype: _initial_doctype, |
| 39 | selected_filter: _initial_filter, |
| 40 | selected_filter_item: _initial_filter[0], |
| 41 | selected_timespan: _initial_timespan, |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 42 | }; |
| 43 | |
| 44 | this.message = null; |
| 45 | this.make(); |
| 46 | }, |
| 47 | |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 48 | make: function () { |
| 49 | var me = this; |
| 50 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 51 | var $container = $(`<div class="leaderboard page-main-content"> |
| 52 | <div class="leaderboard-graph"></div> |
| 53 | <div class="leaderboard-list"></div> |
| 54 | </div>`).appendTo(this.page.main); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 55 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 56 | this.$graph_area = $container.find('.leaderboard-graph'); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 57 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 58 | this.doctypes.map(doctype => { |
| 59 | this.get_sidebar_item(doctype).appendTo(this.$sidebar_list); |
| 60 | }); |
| 61 | |
vishdha | d4491d3 | 2018-02-21 09:33:35 +0530 | [diff] [blame] | 62 | this.company_select = this.page.add_field({ |
| 63 | fieldname: 'company', |
| 64 | label: __('Company'), |
| 65 | fieldtype:'Link', |
| 66 | options:'Company', |
| 67 | default:frappe.defaults.get_default('company'), |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 68 | reqd: 1, |
vishdha | 9a64d43 | 2018-02-21 11:26:58 +0530 | [diff] [blame] | 69 | change: function() { |
vishdha | d4491d3 | 2018-02-21 09:33:35 +0530 | [diff] [blame] | 70 | me.options.selected_company = this.value; |
| 71 | me.make_request($container); |
| 72 | } |
vishdha | d4491d3 | 2018-02-21 09:33:35 +0530 | [diff] [blame] | 73 | }); |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 74 | this.timespan_select = this.page.add_select(__("Timespan"), |
| 75 | this.timespans.map(d => { |
| 76 | return {"label": __(d), value: d } |
| 77 | }) |
| 78 | ); |
| 79 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 80 | this.type_select = this.page.add_select(__("Type"), |
| 81 | me.options.selected_filter.map(d => { |
| 82 | return {"label": __(frappe.model.unscrub(d)), value: d } |
| 83 | }) |
| 84 | ); |
| 85 | |
| 86 | this.$sidebar_list.on('click', 'li', function(e) { |
| 87 | let $li = $(this); |
Rohit Waghchaure | 06f91e2 | 2018-05-28 14:43:17 +0530 | [diff] [blame] | 88 | let doctype = $li.find('span').attr("doctype-value"); |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 89 | |
vishdha | 9a64d43 | 2018-02-21 11:26:58 +0530 | [diff] [blame] | 90 | me.options.selected_company = frappe.defaults.get_default('company'); |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 91 | me.options.selected_doctype = doctype; |
| 92 | me.options.selected_filter = me.filters[doctype]; |
| 93 | me.options.selected_filter_item = me.filters[doctype][0]; |
| 94 | |
| 95 | me.type_select.empty().add_options( |
| 96 | me.options.selected_filter.map(d => { |
| 97 | return {"label": __(frappe.model.unscrub(d)), value: d } |
| 98 | }) |
| 99 | ); |
| 100 | |
| 101 | me.$sidebar_list.find('li').removeClass('active'); |
| 102 | $li.addClass('active'); |
| 103 | |
| 104 | me.make_request($container); |
| 105 | }); |
| 106 | |
| 107 | this.timespan_select.on("change", function() { |
| 108 | me.options.selected_timespan = this.value; |
| 109 | me.make_request($container); |
| 110 | }); |
| 111 | |
| 112 | this.type_select.on("change", function() { |
| 113 | me.options.selected_filter_item = this.value |
| 114 | me.make_request($container); |
| 115 | }); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 116 | |
| 117 | // now get leaderboard |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 118 | this.$sidebar_list.find('li:first').trigger('click'); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 119 | }, |
| 120 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 121 | make_request: function ($container) { |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 122 | var me = this; |
| 123 | |
| 124 | frappe.model.with_doctype(me.options.selected_doctype, function () { |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 125 | me.get_leaderboard(me.get_leaderboard_data, $container); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 126 | }); |
| 127 | }, |
| 128 | |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 129 | get_leaderboard: function (notify, $container) { |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 130 | var me = this; |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 131 | if(!me.options.selected_company) { |
| 132 | frappe.throw(__("Please select Company")); |
| 133 | } |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 134 | frappe.call({ |
| 135 | method: "erpnext.utilities.page.leaderboard.leaderboard.get_leaderboard", |
| 136 | args: { |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 137 | doctype: me.options.selected_doctype, |
| 138 | timespan: me.options.selected_timespan, |
vishdha | d4491d3 | 2018-02-21 09:33:35 +0530 | [diff] [blame] | 139 | company: me.options.selected_company, |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 140 | field: me.options.selected_filter_item, |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 141 | }, |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 142 | callback: function (r) { |
| 143 | let results = r.message || []; |
| 144 | |
| 145 | let graph_items = results.slice(0, 10); |
| 146 | |
| 147 | me.$graph_area.show().empty(); |
| 148 | let args = { |
Prateeksha Singh | 04c4ce3 | 2017-12-20 10:51:25 +0530 | [diff] [blame] | 149 | data: { |
| 150 | datasets: [ |
| 151 | { |
| 152 | values: graph_items.map(d=>d.value) |
| 153 | } |
| 154 | ], |
| 155 | labels: graph_items.map(d=>d.name) |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 156 | }, |
Prateeksha Singh | 04c4ce3 | 2017-12-20 10:51:25 +0530 | [diff] [blame] | 157 | colors: ['light-green'], |
| 158 | format_tooltip_x: d=>d[me.options.selected_filter_item], |
| 159 | type: 'bar', |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 160 | height: 140 |
| 161 | }; |
Prateeksha Singh | 9362cf3 | 2018-03-12 09:54:56 +0530 | [diff] [blame] | 162 | new Chart('.leaderboard-graph', args); |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 163 | |
| 164 | notify(me, r, $container); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 165 | } |
| 166 | }); |
| 167 | }, |
| 168 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 169 | get_leaderboard_data: function (me, res, $container) { |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 170 | if (res && res.message) { |
| 171 | me.message = null; |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 172 | $container.find(".leaderboard-list").html(me.render_list_view(res.message)); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 173 | } else { |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 174 | me.$graph_area.hide(); |
Rohit Waghchaure | 06f91e2 | 2018-05-28 14:43:17 +0530 | [diff] [blame] | 175 | me.message = __("No items found."); |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 176 | $container.find(".leaderboard-list").html(me.render_list_view()); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 177 | } |
| 178 | }, |
| 179 | |
| 180 | render_list_view: function (items = []) { |
| 181 | var me = this; |
| 182 | |
| 183 | var html = |
| 184 | `${me.render_message()} |
| 185 | <div class="result" style="${me.message ? "display:none;" : ""}"> |
| 186 | ${me.render_result(items)} |
| 187 | </div>`; |
| 188 | |
| 189 | return $(html); |
| 190 | }, |
| 191 | |
| 192 | render_result: function (items) { |
| 193 | var me = this; |
| 194 | |
| 195 | var html = |
| 196 | `${me.render_list_header()} |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 197 | ${me.render_list_result(items)}`; |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 198 | |
| 199 | return html; |
| 200 | }, |
| 201 | |
| 202 | render_list_header: function () { |
| 203 | var me = this; |
| 204 | const _selected_filter = me.options.selected_filter |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 205 | .map(i => frappe.model.unscrub(i)); |
| 206 | const fields = ['name', me.options.selected_filter_item]; |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 207 | |
| 208 | const html = |
| 209 | `<div class="list-headers"> |
| 210 | <div class="list-item list-item--head" data-list-renderer="${"List"}"> |
| 211 | ${ |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 212 | fields.map(filter => { |
| 213 | const col = frappe.model.unscrub(filter); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 214 | return ( |
| 215 | `<div class="leaderboard-item list-item_content ellipsis text-muted list-item__content--flex-2 |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 216 | header-btn-base |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 217 | ${(col && _selected_filter.indexOf(col) !== -1) ? "text-right" : ""}"> |
| 218 | <span class="list-col-title ellipsis"> |
| 219 | ${col} |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 220 | </span> |
| 221 | </div>`); |
| 222 | }).join("") |
| 223 | } |
| 224 | </div> |
| 225 | </div>`; |
| 226 | return html; |
| 227 | }, |
| 228 | |
| 229 | render_list_result: function (items) { |
| 230 | var me = this; |
| 231 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 232 | let _html = items.map((item, index) => { |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 233 | const $value = $(me.get_item_html(item)); |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 234 | |
| 235 | let item_class = ""; |
| 236 | if(index == 0) { |
| 237 | item_class = "first"; |
| 238 | } else if (index == 1) { |
| 239 | item_class = "second"; |
| 240 | } else if(index == 2) { |
| 241 | item_class = "third"; |
| 242 | } |
| 243 | const $item_container = $(`<div class="list-item-container ${item_class}">`).append($value); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 244 | return $item_container[0].outerHTML; |
| 245 | }).join(""); |
| 246 | |
| 247 | let html = |
| 248 | `<div class="result-list"> |
| 249 | <div class="list-items"> |
| 250 | ${_html} |
| 251 | </div> |
| 252 | </div>`; |
| 253 | |
| 254 | return html; |
| 255 | }, |
| 256 | |
| 257 | render_message: function () { |
| 258 | var me = this; |
| 259 | |
| 260 | let html = |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 261 | `<div class="no-result text-center" style="${me.message ? "" : "display:none;"}"> |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 262 | <div class="msg-box no-border"> |
| 263 | <p>No Item found</p> |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 264 | </div> |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 265 | </div>`; |
| 266 | |
| 267 | return html; |
| 268 | }, |
| 269 | |
| 270 | get_item_html: function (item) { |
| 271 | var me = this; |
vishdha | 09d5675 | 2018-02-21 16:10:09 +0530 | [diff] [blame] | 272 | const company = me.options.selected_company; |
vishdha | 9a64d43 | 2018-02-21 11:26:58 +0530 | [diff] [blame] | 273 | const currency = frappe.get_doc(":Company", company).default_currency; |
vishdha | d4491d3 | 2018-02-21 09:33:35 +0530 | [diff] [blame] | 274 | const fields = ['name','value']; |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 275 | |
| 276 | const html = |
| 277 | `<div class="list-item"> |
| 278 | ${ |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 279 | fields.map(col => { |
| 280 | let val = item[col]; |
| 281 | if(col=="name") { |
Prateeksha Singh | 9362cf3 | 2018-03-12 09:54:56 +0530 | [diff] [blame] | 282 | var formatted_value = `<a class="grey list-id ellipsis" |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 283 | href="#Form/${me.options.selected_doctype}/${item["name"]}"> ${val} </a>` |
| 284 | } else { |
| 285 | var formatted_value = `<span class="text-muted ellipsis"> |
| 286 | ${(me.options.selected_filter_item.indexOf('qty') == -1) ? format_currency(val, currency) : val}</span>` |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 287 | } |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 288 | |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 289 | return ( |
| 290 | `<div class="list-item_content ellipsis list-item__content--flex-2 |
Nabin Hait | 7d86227 | 2018-02-22 13:59:41 +0530 | [diff] [blame] | 291 | ${(col == "value") ? "text-right" : ""}"> |
| 292 | ${formatted_value} |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 293 | </div>`); |
| 294 | }).join("") |
| 295 | } |
| 296 | </div>`; |
| 297 | |
| 298 | return html; |
| 299 | }, |
| 300 | |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 301 | get_sidebar_item: function(item) { |
| 302 | return $(`<li class="strong module-sidebar-item"> |
| 303 | <a class="module-link"> |
Rohit Waghchaure | 06f91e2 | 2018-05-28 14:43:17 +0530 | [diff] [blame] | 304 | <span doctype-value="${item}">${ __(item) }</span></a> |
Prateeksha Singh | 9b4f3cf | 2017-09-18 16:41:04 +0530 | [diff] [blame] | 305 | </li>`); |
Ayush Shukla | a111f78 | 2017-06-20 13:04:45 +0530 | [diff] [blame] | 306 | } |
| 307 | }); |