fix: remove leaderboard and custom timeline handling

This commit is contained in:
sokumon 2025-04-09 02:58:52 +05:30
parent d8137f342f
commit 196f76028f
9 changed files with 21 additions and 356 deletions

View file

@ -123,7 +123,6 @@ def get_docinfo(doc=None, doctype=None, name=None):
"permissions": get_doc_permissions(doc),
"shared": get_docshares(doc),
"views": get_view_logs(doc),
# "energy_point_logs": get_point_logs(doc.doctype, doc.name),
"additional_timeline_content": get_additional_timeline_content(doc.doctype, doc.name),
"milestones": get_milestones(doc.doctype, doc.name),
"is_document_followed": is_document_followed(doc.doctype, doc.name, frappe.session.user),
@ -246,19 +245,6 @@ def get_comments(doctype: str, name: str, comment_type: str | list[str] = "Comme
return comments
def get_point_logs(doctype, docname):
from frappe.social.doctype.energy_point_settings.energy_point_settings import is_energy_point_enabled
if not is_energy_point_enabled():
return []
return frappe.get_all(
"Energy Point Log",
filters={"reference_doctype": doctype, "reference_name": docname, "type": ["!=", "Review"]},
fields=["*"],
)
def _get_communications(doctype, name, start=0, limit=20):
communications = get_communication_data(doctype, name, start, limit)
for c in communications:

View file

@ -1,50 +0,0 @@
import frappe
from frappe.utils import get_fullname
def get_leaderboards():
return {
"User": {
"fields": ["points"],
"method": "frappe.desk.leaderboard.get_energy_point_leaderboard",
"company_disabled": 1,
"icon": "users",
}
}
@frappe.whitelist()
def get_energy_point_leaderboard(date_range, company=None, field=None, limit=None):
users = frappe.get_list(
"User",
filters={
"name": ["not in", ["Administrator", "Guest"]],
"enabled": 1,
"user_type": ["!=", "Website User"],
},
pluck="name",
)
filters = [["type", "!=", "Review"], ["user", "in", users]]
if date_range:
date_range = frappe.parse_json(date_range)
filters.append(["creation", "between", [date_range[0], date_range[1]]])
energy_point_users = frappe.get_all(
"Energy Point Log",
fields=["user as name", "sum(points) as value"],
filters=filters,
group_by="user",
order_by="value desc",
)
energy_point_users_list = list(map(lambda x: x["name"], energy_point_users))
for user in users:
if user not in energy_point_users_list:
energy_point_users.append({"name": user, "value": 0})
for user in energy_point_users:
user_id = user["name"]
user["name"] = get_fullname(user["name"])
user["formatted_name"] = f'<a href="/app/user-profile/{user_id}">{get_fullname(user_id)}</a>'
return energy_point_users

View file

@ -81,8 +81,6 @@ email_append_to = ["Event", "ToDo", "Communication"]
calendars = ["Event"]
leaderboards = "frappe.desk.leaderboard.get_leaderboards"
# login
on_session_creation = [

View file

@ -101,7 +101,6 @@ import "./frappe/ui/workspace_sidebar_loading_skeleton.html";
import "./frappe/desk.js";
import "./frappe/query_string.js";
import "./frappe/utils/energy_point_utils.js";
import "./frappe/utils/dashboard_utils.js";
import "./frappe/ui/chart.js";
import "./frappe/ui/datatable.js";

View file

@ -148,4 +148,5 @@ class BaseTimeline {
}
}
frappe.ui.BaseTimeline = BaseTimeline;
export default BaseTimeline;

View file

@ -161,7 +161,6 @@ class FormTimeline extends BaseTimeline {
this.timeline_items.push(...this.get_comment_timeline_contents());
if (!this.only_communication) {
this.timeline_items.push(...this.get_view_timeline_contents());
this.timeline_items.push(...this.get_energy_point_timeline_contents());
this.timeline_items.push(...this.get_version_timeline_contents());
this.timeline_items.push(...this.get_share_timeline_contents());
this.timeline_items.push(...this.get_workflow_timeline_contents());
@ -494,36 +493,30 @@ class FormTimeline extends BaseTimeline {
get_custom_timeline_contents() {
let custom_timeline_contents = [];
(this.doc_info.additional_timeline_content || []).forEach((custom_item) => {
custom_timeline_contents.push({
icon: custom_item.icon,
icon_size: "sm",
is_card: custom_item.is_card,
creation: custom_item.creation,
content:
custom_item.content ||
frappe.render_template(custom_item.template, custom_item.template_data),
});
if (custom_item.timeline_badge) {
custom_timeline_contents.push({
timeline_badge: custom_item.timeline_badge,
creation: custom_item.creation,
content: frappe.utils.eval(custom_item.method, {
custom_item: custom_item,
}),
});
} else {
custom_timeline_contents.push({
icon: custom_item.icon,
timeline_badge: custom_item.timeline_badge,
icon_size: "sm",
is_card: custom_item.is_card,
creation: custom_item.creation,
content:
custom_item.content ||
frappe.render_template(custom_item.template, custom_item.template_data),
});
}
});
return custom_timeline_contents;
}
get_energy_point_timeline_contents() {
let energy_point_timeline_contents = [];
(this.doc_info.energy_point_logs || []).forEach((log) => {
let timeline_badge = `
<div class="timeline-badge ${log.points > 0 ? "appreciation" : "criticism"} bold">
${log.points}
</div>`;
energy_point_timeline_contents.push({
timeline_badge: timeline_badge,
creation: log.creation,
content: frappe.energy_points.format_form_log(log),
});
});
return energy_point_timeline_contents;
}
setup_reply(communication_box, communication_doc) {
let actions = communication_box.find(".custom-actions");
let reply = $(`<a class="action-btn reply">${frappe.utils.icon("reply", "md")}</a>`).click(

View file

@ -1,198 +0,0 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
frappe.ui.form.Review = class Review {
constructor({ parent, frm }) {
this.parent = parent;
this.frm = frm;
this.points = frappe.boot.points;
this.reviews = this.parent.find(".reviews");
this.setup_add_review_button();
this.update_reviewers();
}
update_points() {
return frappe
.xcall("frappe.social.doctype.energy_point_log.energy_point_log.get_energy_points", {
user: frappe.session.user,
})
.then((data) => {
frappe.boot.points = data;
this.points = data;
});
}
setup_add_review_button() {
const review_button = this.reviews.find(".add-review-btn");
if (!this.points.review_points) {
review_button.click(false);
review_button.popover({
trigger: "hover",
content: () => {
return `<div class="text-medium">
${__("You do not have enough review points")}
</div>`;
},
html: true,
});
} else {
review_button.click(() => this.show_review_dialog());
}
}
show_review_dialog() {
const user_options = this.frm.get_involved_users();
const review_dialog = new frappe.ui.Dialog({
title: __("Add Review"),
fields: [
{
fieldname: "to_user",
fieldtype: "Autocomplete",
label: __("To User"),
reqd: 1,
options: user_options,
ignore_validation: 1,
description: __("Only users involved in the document are listed"),
},
{
fieldname: "review_type",
fieldtype: "Select",
label: __("Action"),
options: [
{
label: __("Appreciate"),
value: "Appreciation",
},
{
label: __("Criticize"),
value: "Criticism",
},
],
default: "Appreciation",
},
{
fieldname: "points",
fieldtype: "Int",
label: __("Points"),
reqd: 1,
description: __("Currently you have {0} review points", [
this.points.review_points,
]),
},
{
fieldtype: "Small Text",
fieldname: "reason",
reqd: 1,
label: __("Reason"),
},
],
primary_action: (values) => {
review_dialog.disable_primary_action();
if (values.points > this.points.review_points) {
return frappe.msgprint(__("You do not have enough points"));
}
frappe
.xcall("frappe.social.doctype.energy_point_log.energy_point_log.review", {
doc: {
doctype: this.frm.doc.doctype,
name: this.frm.doc.name,
},
to_user: values.to_user,
points: values.points,
review_type: values.review_type,
reason: values.reason,
})
.then((review) => {
review_dialog.hide();
review_dialog.clear();
this.frm.get_docinfo().energy_point_logs.unshift(review);
this.frm.timeline.refresh();
this.update_reviewers();
this.update_points();
})
.finally(() => {
review_dialog.enable_primary_action();
});
},
primary_action_label: __("Submit"),
});
review_dialog.show();
}
update_reviewers() {
const review_logs = this.frm
.get_docinfo()
.energy_point_logs.filter((log) => ["Appreciation", "Criticism"].includes(log.type));
this.reviews.find(".review").remove();
review_logs.forEach((log) => {
let review_pill = $(`
<div class="review ${log.points < 0 ? "criticism" : "appreciation"} cursor-pointer">
${frappe.avatar(log.owner)}
<span class="review-points">
${log.points > 0 ? "+" : ""}${log.points}
</span>
</div>
`);
this.reviews.append(review_pill);
this.setup_detail_popover(review_pill, log);
});
}
setup_detail_popover(el, data) {
let subject = "";
let fullname = frappe.user.full_name(data.user);
let timestamp = `<span class="text-muted">${frappe.datetime.comment_when(
data.creation
)}</span>`;
let message_parts = [Math.abs(data.points), fullname, timestamp];
if (data.type === "Appreciation") {
if (data.points == 1) {
subject = __("{0} appreciation point for {1}", message_parts);
} else {
subject = __("{0} appreciation points for {1}", message_parts);
}
} else {
if (data.points == -1) {
subject = __("{0} criticism point for {1}", message_parts);
} else {
subject = __("{0} criticism points for {1}", message_parts);
}
}
el.popover({
animation: true,
trigger: "hover",
delay: 500,
placement: "top",
template: `
<div class="review-popover popover" role="tooltip">
<div class="arrow"></div>
<h3 class="popover-header"></h3>
<div class="popover-body">
</div>
</div>'
`,
content: () => {
return `
<div class="text-medium">
<div class="body">
<div>${data.reason}</div>
</div>
<div class="subject">
${frappe.utils.icon("review")}
${subject}
<p class="mt-1">
<!-- ${frappe.avatar("shivam@example.com", "avatar-xs")} -->
<span>${frappe.user.full_name(data.owner)}</span> - ${timestamp}
</p>
</div>
</div>
`;
},
html: true,
container: "body",
});
return el;
}
};

View file

@ -1,63 +0,0 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
frappe.provide("frappe.energy_points");
Object.assign(frappe.energy_points, {
get_points(points) {
return `<span class="bold" style="color: ${points >= 0 ? "#45A163" : "#e42121"}">
${points > 0 ? "+" : ""}${points}
</span>`;
},
format_form_log(log) {
const separator = `<span>&nbsp;-&nbsp;</span>`;
return `<span>
<!--${this.get_points(log.points)}&nbsp;-->
<a href="/app/energy-point-log/${log.name}">${this.get_form_log_message(log)}</a>
${log.reason ? separator + log.reason : ""}
</span>`;
},
format_history_log(log) {
// redundant code to honor readability and to avoid confusion
const separator = `<span>&nbsp;-&nbsp;</span>`;
const route = frappe.utils.get_form_link(log.reference_doctype, log.reference_name);
return `<div class="flex">
<span class="${log.points >= 0 ? "green" : "red"} mr-2">
${this.get_points(log.points)}
</span>
<a href="${route}" class="text-muted">${this.get_history_log_message(log)}</a>
${log.reason ? separator + log.reason : ""}
${separator + frappe.datetime.comment_when(log.creation)}
</div>`;
},
get_history_log_message(log) {
const owner_name = frappe.user.full_name(log.owner).bold();
const ref_doc = log.reference_name;
if (log.type === "Appreciation") {
return __("{0} appreciated on {1}", [owner_name, ref_doc]);
}
if (log.type === "Criticism") {
return __("{0} criticized on {1}", [owner_name, ref_doc]);
}
if (log.type === "Revert") {
return __("{0} reverted {1}", [owner_name, log.revert_of]);
}
return __("via automatic rule {0} on {1}", [log.rule.bold(), ref_doc]);
},
get_form_log_message(log) {
// redundant code to honor readability and to avoid confusion
const owner_name = frappe.user.full_name(log.owner).bold();
const user = frappe.user.full_name(log.user).bold();
if (log.type === "Appreciation") {
return __("{0} appreciated {1}", [owner_name, user]);
}
if (log.type === "Criticism") {
return __("{0} criticized {1}", [owner_name, user]);
}
if (log.type === "Revert") {
return __("{0} reverted {1}", [owner_name, log.revert_of]);
}
return __("gained by {0} via automatic rule {1}", [user, log.rule.bold()]);
},
});

View file

@ -1 +0,0 @@
import "../../desk/page/user_profile/user_profile_controller";