453 lines
12 KiB
JavaScript
453 lines
12 KiB
JavaScript
import BaseTimeline from "../../../public/js/frappe/form/footer/base_timeline";
|
|
frappe.provide('frappe.energy_points');
|
|
|
|
class UserProfile {
|
|
constructor(wrapper) {
|
|
this.wrapper = $(wrapper);
|
|
this.page = frappe.ui.make_app_page({
|
|
parent: wrapper,
|
|
});
|
|
this.sidebar = this.wrapper.find('.layout-side-section');
|
|
this.main_section = this.wrapper.find('.layout-main-section');
|
|
this.wrapper.bind('show', () => {
|
|
this.show();
|
|
});
|
|
}
|
|
|
|
show() {
|
|
let route = frappe.get_route();
|
|
this.user_id = route[1] || frappe.session.user;
|
|
|
|
//validate if user
|
|
if (route.length > 1) {
|
|
frappe.dom.freeze(__('Loading user profile') + '...');
|
|
frappe.db.exists('User', this.user_id).then(exists => {
|
|
frappe.dom.unfreeze();
|
|
if (exists) {
|
|
this.make_user_profile();
|
|
} else {
|
|
frappe.msgprint(__('User does not exist'));
|
|
}
|
|
});
|
|
} else {
|
|
frappe.set_route('user-profile', frappe.session.user);
|
|
}
|
|
}
|
|
|
|
make_user_profile() {
|
|
this.user = frappe.user_info(this.user_id);
|
|
this.page.set_title(this.user.fullname);
|
|
this.setup_user_search();
|
|
this.main_section.empty().append(frappe.render_template('user_profile'));
|
|
this.energy_points = 0;
|
|
this.review_points = 0;
|
|
this.rank = 0;
|
|
this.month_rank = 0;
|
|
this.render_user_details();
|
|
this.render_points_and_rank();
|
|
this.render_heatmap();
|
|
this.render_line_chart();
|
|
this.render_percentage_chart('type', 'Type Distribution');
|
|
this.create_percentage_chart_filters();
|
|
this.setup_user_activity_timeline();
|
|
}
|
|
|
|
setup_user_search() {
|
|
this.$user_search_button = this.page.set_secondary_action(
|
|
__('Change User'),
|
|
() => this.show_user_search_dialog(),
|
|
{ icon: 'change', size: 'sm' }
|
|
);
|
|
}
|
|
|
|
show_user_search_dialog() {
|
|
let dialog = new frappe.ui.Dialog({
|
|
title: __('Change User'),
|
|
fields: [
|
|
{
|
|
fieldtype: 'Link',
|
|
fieldname: 'user',
|
|
options: 'User',
|
|
label: __('User'),
|
|
}
|
|
],
|
|
primary_action_label: __('Go'),
|
|
primary_action: ({ user }) => {
|
|
dialog.hide();
|
|
this.user_id = user;
|
|
this.make_user_profile();
|
|
}
|
|
});
|
|
dialog.show();
|
|
}
|
|
|
|
render_heatmap() {
|
|
this.heatmap = new frappe.Chart('.performance-heatmap', {
|
|
type: 'heatmap',
|
|
countLabel: 'Energy Points',
|
|
data: {},
|
|
discreteDomains: 1,
|
|
radius: 3,
|
|
height: 150
|
|
});
|
|
this.update_heatmap_data();
|
|
this.create_heatmap_chart_filters();
|
|
}
|
|
|
|
update_heatmap_data(date_from) {
|
|
frappe.xcall('frappe.desk.page.user_profile.user_profile.get_energy_points_heatmap_data', {
|
|
user: this.user_id,
|
|
date: date_from || frappe.datetime.year_start(),
|
|
}).then((r) => {
|
|
this.heatmap.update({ dataPoints: r });
|
|
});
|
|
}
|
|
|
|
|
|
render_line_chart() {
|
|
this.line_chart_filters = [
|
|
['Energy Point Log', 'user', '=', this.user_id, false],
|
|
['Energy Point Log', 'type', '!=', 'Review', false]
|
|
];
|
|
|
|
this.line_chart_config = {
|
|
timespan: 'Last Month',
|
|
time_interval: 'Daily',
|
|
type: 'Line',
|
|
value_based_on: 'points',
|
|
chart_type: 'Sum',
|
|
document_type: 'Energy Point Log',
|
|
name: 'Energy Points',
|
|
width: 'half',
|
|
based_on: 'creation'
|
|
};
|
|
|
|
this.line_chart = new frappe.Chart('.performance-line-chart', {
|
|
type: 'line',
|
|
height: 200,
|
|
data: {
|
|
labels: [],
|
|
datasets: [{}]
|
|
},
|
|
colors: ['purple'],
|
|
axisOptions: {
|
|
xIsSeries: 1
|
|
}
|
|
});
|
|
this.update_line_chart_data();
|
|
this.create_line_chart_filters();
|
|
}
|
|
|
|
update_line_chart_data() {
|
|
this.line_chart_config.filters_json = JSON.stringify(this.line_chart_filters);
|
|
|
|
frappe.xcall('frappe.desk.doctype.dashboard_chart.dashboard_chart.get', {
|
|
chart: this.line_chart_config,
|
|
no_cache: 1,
|
|
}).then(chart => {
|
|
this.line_chart.update(chart);
|
|
});
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
render_percentage_chart(field, title) {
|
|
frappe.xcall('frappe.desk.page.user_profile.user_profile.get_energy_points_percentage_chart_data', {
|
|
user: this.user_id,
|
|
field: field
|
|
}).then(chart => {
|
|
if (chart.labels.length) {
|
|
this.percentage_chart = new frappe.Chart('.performance-percentage-chart', {
|
|
type: 'percentage',
|
|
data: {
|
|
labels: chart.labels,
|
|
datasets: chart.datasets
|
|
},
|
|
truncateLegends: 1,
|
|
barOptions: {
|
|
height: 11,
|
|
depth: 1
|
|
},
|
|
height: 200,
|
|
maxSlices: 8,
|
|
colors: ['purple', 'blue', 'cyan', 'teal', 'pink', 'red', 'orange', 'yellow'],
|
|
});
|
|
} else {
|
|
this.wrapper.find('.percentage-chart-container').hide();
|
|
}
|
|
});
|
|
}
|
|
|
|
create_line_chart_filters() {
|
|
let filters = [
|
|
{
|
|
label: 'All',
|
|
options: ['All', 'Auto', 'Criticism', 'Appreciation', 'Revert'],
|
|
action: (selected_item) => {
|
|
if (selected_item === 'All') {
|
|
this.line_chart_filters = [
|
|
['Energy Point Log', 'user', '=', this.user_id, false],
|
|
['Energy Point Log', 'type', '!=', 'Review', false]
|
|
];
|
|
} else {
|
|
this.line_chart_filters[1] = ['Energy Point Log', 'type', '=', selected_item, false];
|
|
}
|
|
this.update_line_chart_data();
|
|
}
|
|
},
|
|
{
|
|
label: 'Last Month',
|
|
options: ['Last Week', 'Last Month', 'Last Quarter', 'Last Year'],
|
|
action: (selected_item) => {
|
|
this.line_chart_config.timespan = selected_item;
|
|
this.update_line_chart_data();
|
|
}
|
|
},
|
|
{
|
|
label: 'Daily',
|
|
options: ['Daily', 'Weekly', 'Monthly'],
|
|
action: (selected_item) => {
|
|
this.line_chart_config.time_interval = selected_item;
|
|
this.update_line_chart_data();
|
|
}
|
|
},
|
|
];
|
|
frappe.dashboard_utils.render_chart_filters(filters, 'chart-filter', '.line-chart-options', 1);
|
|
}
|
|
|
|
create_percentage_chart_filters() {
|
|
let filters = [
|
|
{
|
|
label: 'Type',
|
|
options: ['Type', 'Reference Doctype', 'Rule'],
|
|
fieldnames: ['type', 'reference_doctype', 'rule'],
|
|
action: (selected_item, fieldname) => {
|
|
let title = selected_item + ' Distribution';
|
|
this.render_percentage_chart(fieldname, title);
|
|
}
|
|
},
|
|
];
|
|
frappe.dashboard_utils.render_chart_filters(filters, 'chart-filter', '.percentage-chart-options');
|
|
}
|
|
|
|
create_heatmap_chart_filters() {
|
|
let filters = [
|
|
{
|
|
label: frappe.dashboard_utils.get_year(frappe.datetime.now_date()),
|
|
options: frappe.dashboard_utils.get_years_since_creation(frappe.boot.user.creation),
|
|
action: (selected_item) => {
|
|
this.update_heatmap_data(frappe.datetime.obj_to_str(selected_item));
|
|
}
|
|
},
|
|
];
|
|
frappe.dashboard_utils.render_chart_filters(filters, 'chart-filter', '.heatmap-options');
|
|
}
|
|
|
|
|
|
edit_profile() {
|
|
let edit_profile_dialog = new frappe.ui.Dialog({
|
|
title: __('Edit Profile'),
|
|
fields: [
|
|
{
|
|
fieldtype: 'Attach Image',
|
|
fieldname: 'user_image',
|
|
label: 'Profile Image',
|
|
},
|
|
{
|
|
fieldtype: 'Data',
|
|
fieldname: 'interest',
|
|
label: 'Interests',
|
|
},
|
|
{
|
|
fieldtype: 'Column Break'
|
|
},
|
|
{
|
|
fieldtype: 'Data',
|
|
fieldname: 'location',
|
|
label: 'Location',
|
|
},
|
|
{
|
|
fieldtype: 'Section Break',
|
|
fieldname: 'Interest',
|
|
},
|
|
{
|
|
fieldtype: 'Small Text',
|
|
fieldname: 'bio',
|
|
label: 'Bio',
|
|
}
|
|
],
|
|
primary_action: values => {
|
|
edit_profile_dialog.disable_primary_action();
|
|
frappe.xcall('frappe.desk.page.user_profile.user_profile.update_profile_info', {
|
|
profile_info: values
|
|
}).then(user => {
|
|
user.image = user.user_image;
|
|
this.user = Object.assign(values, user);
|
|
edit_profile_dialog.hide();
|
|
this.render_user_details();
|
|
}).finally(() => {
|
|
edit_profile_dialog.enable_primary_action();
|
|
});
|
|
},
|
|
primary_action_label: __('Save')
|
|
});
|
|
|
|
edit_profile_dialog.set_values({
|
|
user_image: this.user.image,
|
|
location: this.user.location,
|
|
interest: this.user.interest,
|
|
bio: this.user.bio
|
|
});
|
|
edit_profile_dialog.show();
|
|
}
|
|
|
|
render_user_details() {
|
|
this.sidebar.empty().append(frappe.render_template('user_profile_sidebar', {
|
|
user_image: this.user.image,
|
|
user_abbr: this.user.abbr,
|
|
user_location: this.user.location,
|
|
user_interest: this.user.interest,
|
|
user_bio: this.user.bio,
|
|
}));
|
|
|
|
this.setup_user_profile_links();
|
|
}
|
|
|
|
setup_user_profile_links() {
|
|
if (this.user_id !== frappe.session.user) {
|
|
this.wrapper.find('.profile-links').hide();
|
|
} else {
|
|
this.wrapper.find('.edit-profile-link').on('click', () => {
|
|
this.edit_profile();
|
|
});
|
|
|
|
this.wrapper.find('.user-settings-link').on('click', () => {
|
|
this.go_to_user_settings();
|
|
});
|
|
}
|
|
}
|
|
|
|
get_user_rank() {
|
|
return frappe.xcall('frappe.desk.page.user_profile.user_profile.get_user_rank', {
|
|
user: this.user_id,
|
|
}).then(r => {
|
|
if (r.monthly_rank.length) this.month_rank = r.monthly_rank[0];
|
|
if (r.all_time_rank.length) this.rank = r.all_time_rank[0];
|
|
});
|
|
}
|
|
|
|
get_user_points() {
|
|
return frappe.xcall(
|
|
'frappe.social.doctype.energy_point_log.energy_point_log.get_user_energy_and_review_points',
|
|
{
|
|
user: this.user_id,
|
|
}
|
|
).then(r => {
|
|
if (r[this.user_id]) {
|
|
this.energy_points = r[this.user_id].energy_points;
|
|
this.review_points = r[this.user_id].review_points;
|
|
}
|
|
});
|
|
}
|
|
|
|
render_points_and_rank() {
|
|
let $profile_details = this.wrapper.find('.user-stats');
|
|
let $profile_details_wrapper = this.wrapper.find('.user-stats-detail');
|
|
|
|
const _get_stat_dom = (value, label, icon) => {
|
|
return `<div class="user-stats-item mt-4">
|
|
${frappe.utils.icon(icon, "lg", "no-stroke")}
|
|
<div>
|
|
<div class="stat-value">${value}</div>
|
|
<div class="stat-label">${label}</div>
|
|
</div>
|
|
</div>`;
|
|
};
|
|
|
|
this.get_user_rank().then(() => {
|
|
this.get_user_points().then(() => {
|
|
let html = $(`
|
|
${_get_stat_dom(this.energy_points, __('Energy Points'), "color-energy-points")}
|
|
${_get_stat_dom(this.review_points, __('Review Points'), "color-review-points")}
|
|
${_get_stat_dom(this.rank, __('Rank'), "color-rank")}
|
|
${_get_stat_dom(this.month_rank, __('Monthly Rank'), "color-monthly-rank")}
|
|
`);
|
|
|
|
$profile_details.append(html);
|
|
$profile_details_wrapper.removeClass("hide");
|
|
});
|
|
});
|
|
}
|
|
|
|
go_to_user_settings() {
|
|
frappe.set_route('Form', 'User', this.user_id);
|
|
}
|
|
|
|
setup_user_activity_timeline() {
|
|
this.user_activity_timeline = new UserProfileTimeline({
|
|
parent: this.wrapper.find('.recent-activity-list'),
|
|
footer: this.wrapper.find('.recent-activity-footer'),
|
|
user: this.user_id
|
|
});
|
|
|
|
this.user_activity_timeline.refresh();
|
|
}
|
|
}
|
|
|
|
class UserProfileTimeline extends BaseTimeline {
|
|
make() {
|
|
super.make();
|
|
this.activity_start = 0;
|
|
this.activity_limit = 20;
|
|
this.setup_show_more_activity();
|
|
}
|
|
prepare_timeline_contents() {
|
|
return this.get_user_activity_data().then((activities) => {
|
|
if (!activities.length) {
|
|
this.show_more_button.hide();
|
|
this.timeline_wrapper.html(`<div>${__('No activities to show')}</div>`);
|
|
return;
|
|
}
|
|
this.show_more_button.toggle(activities.length === this.activity_limit);
|
|
this.timeline_items = activities.map((activity) => this.get_activity_timeline_item(activity));
|
|
});
|
|
}
|
|
|
|
get_user_activity_data() {
|
|
return frappe.xcall('frappe.desk.page.user_profile.user_profile.get_energy_points_list', {
|
|
start: this.activity_start,
|
|
limit: this.activity_limit,
|
|
user: this.user
|
|
});
|
|
}
|
|
|
|
get_activity_timeline_item(data) {
|
|
let icon = data.type == 'Appreciation' ? 'clap': data.type == 'Criticism' ? 'criticize': null;
|
|
return {
|
|
icon: icon,
|
|
creation: data.creation,
|
|
is_card: true,
|
|
content: frappe.energy_points.format_history_log(data),
|
|
};
|
|
}
|
|
|
|
setup_show_more_activity() {
|
|
this.show_more_button = $(`<a class="show-more-activity-btn">${__('Show More Activity')}</a>`);
|
|
this.show_more_button.hide();
|
|
this.footer.append(this.show_more_button);
|
|
this.show_more_button.on('click', () => this.show_more_activity());
|
|
}
|
|
|
|
show_more_activity() {
|
|
this.activity_start += this.activity_limit;
|
|
this.get_user_activity_data().then(activities => {
|
|
if (!activities.length || activities.length < this.activity_limit) {
|
|
this.show_more_button.hide();
|
|
}
|
|
let timeline_items = activities.map((activity) => this.get_activity_timeline_item(activity));
|
|
timeline_items.map((item) => this.add_timeline_item(item, true));
|
|
});
|
|
}
|
|
}
|
|
|
|
frappe.provide('frappe.ui');
|
|
frappe.ui.UserProfile = UserProfile;
|