blob: eed9bd1865770be131183d0561006694b09d83ff [file] [log] [blame]
Ayush Shuklaa111f782017-06-20 13:04:45 +05301
2frappe.Leaderboard = Class.extend({
3
4 init: function (parent) {
5 this.page = frappe.ui.make_app_page({
6 parent: parent,
7 title: "Leaderboard",
8 single_column: true
9 });
10
11 // const list of doctypes
12 this.doctypes = ["Customer", "Item", "Supplier", "Sales Partner"];
13 this.timelines = ["Week", "Month", "Quarter", "Year"];
14 this.desc_fields = ["total_amount", "total_request", "annual_billing", "commission_rate"];
15 this.filters = {
16 "Customer": this.map_array(["title", "total_amount", "total_item_purchased", "modified"]),
17 "Item": this.map_array(["title", "total_request", "total_purchase", "avg_price", "modified"]),
18 "Supplier": this.map_array(["title", "annual_billing", "total_unpaid", "modified"]),
19 "Sales Partner": this.map_array(["title", "commission_rate", "target_qty", "target_amount", "modified"]),
20 };
21
22 // for saving current selected filters
23 const _selected_filter = this.filters[this.doctypes[0]];
24 this.options = {
25 selected_doctype: this.doctypes[0],
26 selected_filter: _selected_filter,
27 selected_filter_item: _selected_filter[1],
28 selected_timeline: this.timelines[0],
29 };
30
31 this.message = null;
32 this.make();
33 },
34
35
36
37 make: function () {
38 var me = this;
39
40 var $leaderboard = $(frappe.render_template("leaderboard", this)).appendTo(this.page.main);
41
42 // events
43 $leaderboard.find(".select-doctype")
44 .on("change", function () {
45 me.options.selected_doctype = this.value;
46 me.options.selected_filter = me.filters[this.value];
47 me.options.selected_filter_item = me.filters[this.value][1];
48 me.make_request($leaderboard);
49 });
50
51 $leaderboard.find(".select-time")
52 .on("change", function () {
53 me.options.selected_timeline = this.value;
54 me.make_request($leaderboard);
55 });
56
57 // now get leaderboard
58 me.make_request($leaderboard);
59 },
60
61 make_request: function ($leaderboard) {
62 var me = this;
63
64 frappe.model.with_doctype(me.options.selected_doctype, function () {
65 me.get_leaderboard(me.get_leaderboard_data, $leaderboard);
66 });
67 },
68
69 get_leaderboard: function (notify, $leaderboard) {
70 var me = this;
71
72 frappe.call({
73 method: "erpnext.utilities.page.leaderboard.leaderboard.get_leaderboard",
74 args: {
75 obj: JSON.stringify(me.options)
76 },
77 callback: function (res) {
78 console.log(res)
79 notify(me, res, $leaderboard);
80 }
81 });
82 },
83
84 get_leaderboard_data: function (me, res, $leaderboard) {
85 if (res && res.message) {
86 me.message = null;
87 $leaderboard.find(".leaderboard").html(me.render_list_view(res.message));
88
89 // event to change arrow
90 $leaderboard.find(".leaderboard-item")
91 .click(function () {
92 const field = this.innerText.trim().toLowerCase().replace(new RegExp(" ", "g"), "_");
93 if (field && field !== "title") {
94 const _selected_filter_item = me.options.selected_filter
95 .filter(i => i.field === field);
96 if (_selected_filter_item.length > 0) {
97 me.options.selected_filter_item = _selected_filter_item[0];
98 me.options.selected_filter_item.value = _selected_filter_item[0].value === "ASC" ? "DESC" : "ASC";
99
100 const new_class_name = `icon-${me.options.selected_filter_item.field} fa fa-chevron-${me.options.selected_filter_item.value === "ASC" ? "up" : "down"}`;
101 $leaderboard.find(`.icon-${me.options.selected_filter_item.field}`)
102 .attr("class", new_class_name);
103
104 // now make request to web
105 me.make_request($leaderboard);
106 }
107 }
108 });
109 } else {
110 me.message = "No items found.";
111 $leaderboard.find(".leaderboard").html(me.render_list_view());
112 }
113 },
114
115 render_list_view: function (items = []) {
116 var me = this;
117
118 var html =
119 `${me.render_message()}
120 <div class="result" style="${me.message ? "display:none;" : ""}">
121 ${me.render_result(items)}
122 </div>`;
123
124 return $(html);
125 },
126
127 render_result: function (items) {
128 var me = this;
129
130 var html =
131 `${me.render_list_header()}
132 ${me.render_list_result(items)}`;
133
134 return html;
135 },
136
137 render_list_header: function () {
138 var me = this;
139 const _selected_filter = me.options.selected_filter
140 .map(i => me.map_field(i.field)).slice(1);
141
142 const html =
143 `<div class="list-headers">
144 <div class="list-item list-item--head" data-list-renderer="${"List"}">
145 ${
146 me.options.selected_filter
147 .map(filter => {
148 const col = me.map_field(filter.field);
149 return (
150 `<div class="leaderboard-item list-item_content ellipsis text-muted list-item__content--flex-2
151 header-btn-base ${(col !== "Title" && col !== "Modified") ? "hidden-xs" : ""}
152 ${(col && _selected_filter.indexOf(col) !== -1) ? "text-right" : ""}">
153 <span class="list-col-title ellipsis">
154 ${col}
155 <i class="${"icon-" + filter.field} fa ${filter.value === "ASC" ? "fa-chevron-up" : "fa-chevron-down"}"
156 style="${col === "Title" ? "display:none;" : ""}"></i>
157 </span>
158 </div>`);
159 }).join("")
160 }
161 </div>
162 </div>`;
163 return html;
164 },
165
166 render_list_result: function (items) {
167 var me = this;
168
169 let _html = items.map((item) => {
170 const $value = $(me.get_item_html(item));
171 const $item_container = $(`<div class="list-item-container">`).append($value);
172 return $item_container[0].outerHTML;
173 }).join("");
174
175 let html =
176 `<div class="result-list">
177 <div class="list-items">
178 ${_html}
179 </div>
180 </div>`;
181
182 return html;
183 },
184
185 render_message: function () {
186 var me = this;
187
188 let html =
189 `<div class="no-result text-center" style="${me.message ? "" : "display:none;"}">
190 <div class="msg-box no-border">
191 <p>No Item found</p>
192 </div>
193 </div>`;
194
195 return html;
196 },
197
198 get_item_html: function (item) {
199 var me = this;
200 const _selected_filter = me.options.selected_filter
201 .map(i => me.map_field(i.field)).slice(1);
202
203 const html =
204 `<div class="list-item">
205 ${
206 me.options.selected_filter
207 .map(filter => {
208 const col = me.map_field(filter.field);
209 let val = item[filter.field];
210 if (col === "Modified") {
211 val = comment_when(val);
212 }
213 return (
214 `<div class="list-item_content ellipsis list-item__content--flex-2
215 ${(col !== "Title" && col !== "Modified") ? "hidden-xs" : ""}
216 ${(col && _selected_filter.indexOf(col) !== -1) ? "text-right" : ""}">
217 ${
218 col === "Title"
219 ? `<a class="grey list-id ellipsis" href="${item["href"]}"> ${val} </a>`
220 : `<span class="text-muted ellipsis"> ${val}</span>`
221 }
222 </div>`);
223 }).join("")
224 }
225 </div>`;
226
227 return html;
228 },
229
230 map_field: function (field) {
231 return field.replace(new RegExp("_", "g"), " ").replace(/(^|\s)[a-z]/g, f => f.toUpperCase())
232 },
233
234 map_array: function (_array) {
235 var me = this;
236 return _array.map((str) => {
237 let value = me.desc_fields.indexOf(str) > -1 ? "DESC" : "ASC";
238 return {
239 field: str,
240 value: value
241 };
242 });
243 }
244});
245
246frappe.pages["leaderboard"].on_page_load = function (wrapper) {
247 frappe.leaderboard = new frappe.Leaderboard(wrapper);
248}