feat: Expand All nodes option in Desktop view
This commit is contained in:
parent
951b3a4313
commit
6f799d17ce
@ -36,7 +36,11 @@ erpnext.HierarchyChart = class {
|
|||||||
|
|
||||||
me.nodes[this.id] = this;
|
me.nodes[this.id] = this;
|
||||||
me.make_node_element(this);
|
me.make_node_element(this);
|
||||||
me.setup_node_click_action(this);
|
|
||||||
|
if (!me.all_nodes_expanded) {
|
||||||
|
me.setup_node_click_action(this);
|
||||||
|
}
|
||||||
|
|
||||||
me.setup_edit_node_action(this);
|
me.setup_edit_node_action(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -60,8 +64,9 @@ erpnext.HierarchyChart = class {
|
|||||||
show() {
|
show() {
|
||||||
frappe.breadcrumbs.add('HR');
|
frappe.breadcrumbs.add('HR');
|
||||||
|
|
||||||
let me = this;
|
this.setup_actions();
|
||||||
if ($(`[data-fieldname="company"]`).length) return;
|
if ($(`[data-fieldname="company"]`).length) return;
|
||||||
|
let me = this;
|
||||||
|
|
||||||
let company = this.page.add_field({
|
let company = this.page.add_field({
|
||||||
fieldtype: 'Link',
|
fieldtype: 'Link',
|
||||||
@ -79,20 +84,9 @@ erpnext.HierarchyChart = class {
|
|||||||
|
|
||||||
// svg for connectors
|
// svg for connectors
|
||||||
me.make_svg_markers();
|
me.make_svg_markers();
|
||||||
|
me.setup_hierarchy()
|
||||||
if (me.$hierarchy)
|
|
||||||
me.$hierarchy.remove();
|
|
||||||
|
|
||||||
// setup hierarchy
|
|
||||||
me.$hierarchy = $(
|
|
||||||
`<ul class="hierarchy">
|
|
||||||
<li class="root-level level">
|
|
||||||
<ul class="node-children"></ul>
|
|
||||||
</li>
|
|
||||||
</ul>`);
|
|
||||||
|
|
||||||
me.page.main.append(me.$hierarchy);
|
|
||||||
me.render_root_nodes();
|
me.render_root_nodes();
|
||||||
|
me.all_nodes_expanded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -101,6 +95,42 @@ erpnext.HierarchyChart = class {
|
|||||||
$(`[data-fieldname="company"]`).trigger('change');
|
$(`[data-fieldname="company"]`).trigger('change');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup_actions() {
|
||||||
|
let me = this;
|
||||||
|
this.page.add_inner_button(__('Expand All'), function() {
|
||||||
|
me.load_children(me.root_node, true);
|
||||||
|
me.all_nodes_expanded = true;
|
||||||
|
|
||||||
|
me.page.remove_inner_button(__('Expand All'));
|
||||||
|
me.page.add_inner_button(__('Collapse All'), function() {
|
||||||
|
me.setup_hierarchy();
|
||||||
|
me.render_root_nodes();
|
||||||
|
me.all_nodes_expanded = false;
|
||||||
|
|
||||||
|
me.page.remove_inner_button(__('Collapse All'));
|
||||||
|
me.setup_actions();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_hierarchy() {
|
||||||
|
if (this.$hierarchy)
|
||||||
|
this.$hierarchy.remove();
|
||||||
|
|
||||||
|
$(`#connectors`).empty();
|
||||||
|
|
||||||
|
// setup hierarchy
|
||||||
|
this.$hierarchy = $(
|
||||||
|
`<ul class="hierarchy">
|
||||||
|
<li class="root-level level">
|
||||||
|
<ul class="node-children"></ul>
|
||||||
|
</li>
|
||||||
|
</ul>`);
|
||||||
|
|
||||||
|
this.page.main.append(this.$hierarchy);
|
||||||
|
this.nodes = {};
|
||||||
|
}
|
||||||
|
|
||||||
make_svg_markers() {
|
make_svg_markers() {
|
||||||
$('#arrows').remove();
|
$('#arrows').remove();
|
||||||
|
|
||||||
@ -126,7 +156,7 @@ erpnext.HierarchyChart = class {
|
|||||||
</svg>`);
|
</svg>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_root_nodes() {
|
render_root_nodes(expanded_view=false) {
|
||||||
let me = this;
|
let me = this;
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
@ -156,7 +186,10 @@ erpnext.HierarchyChart = class {
|
|||||||
expand_node = node;
|
expand_node = node;
|
||||||
});
|
});
|
||||||
|
|
||||||
me.expand_node(expand_node);
|
if (!expanded_view) {
|
||||||
|
me.root_node = expand_node;
|
||||||
|
me.expand_node(expand_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -196,11 +229,20 @@ erpnext.HierarchyChart = class {
|
|||||||
$(`#${node.parent_id}`).addClass('active-path');
|
$(`#${node.parent_id}`).addClass('active-path');
|
||||||
}
|
}
|
||||||
|
|
||||||
load_children(node) {
|
load_children(node, deep=false) {
|
||||||
frappe.run_serially([
|
if (!deep) {
|
||||||
() => this.get_child_nodes(node.id),
|
frappe.run_serially([
|
||||||
(child_nodes) => this.render_child_nodes(node, child_nodes)
|
() => this.get_child_nodes(node.id),
|
||||||
]);
|
(child_nodes) => this.render_child_nodes(node, child_nodes)
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
frappe.run_serially([
|
||||||
|
() => this.setup_hierarchy(),
|
||||||
|
() => this.render_root_nodes(true),
|
||||||
|
() => this.get_all_nodes(node.id, node.name),
|
||||||
|
(data_list) => this.render_children_of_all_nodes(data_list)
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_child_nodes(node_id) {
|
get_child_nodes(node_id) {
|
||||||
@ -247,6 +289,70 @@ erpnext.HierarchyChart = class {
|
|||||||
node.expanded = true;
|
node.expanded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_all_nodes(node_id, node_name) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.utilities.hierarchy_chart.get_all_nodes',
|
||||||
|
args: {
|
||||||
|
method: this.method,
|
||||||
|
company: this.company,
|
||||||
|
parent: node_id,
|
||||||
|
parent_name: node_name
|
||||||
|
},
|
||||||
|
callback: (r) => {
|
||||||
|
resolve(r.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render_children_of_all_nodes(data_list) {
|
||||||
|
let entry = undefined;
|
||||||
|
let node = undefined;
|
||||||
|
|
||||||
|
while(data_list.length) {
|
||||||
|
// to avoid overlapping connectors
|
||||||
|
entry = data_list.shift();
|
||||||
|
node = this.nodes[entry.parent];
|
||||||
|
if (node) {
|
||||||
|
this.render_child_nodes_for_expanded_view(node, entry.data);
|
||||||
|
} else {
|
||||||
|
data_list.push(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_child_nodes_for_expanded_view(node, child_nodes) {
|
||||||
|
node.$children = $('<ul class="node-children"></ul>')
|
||||||
|
|
||||||
|
const last_level = this.$hierarchy.find('.level:last').index();
|
||||||
|
const node_level = $(`#${node.id}`).parent().parent().parent().index();
|
||||||
|
|
||||||
|
if (last_level === node_level) {
|
||||||
|
this.$hierarchy.append(`
|
||||||
|
<li class="level"></li>
|
||||||
|
`);
|
||||||
|
node.$children.appendTo(this.$hierarchy.find('.level:last'));
|
||||||
|
} else {
|
||||||
|
node.$children.appendTo(this.$hierarchy.find('.level:eq(' + (node_level + 1) + ')'));
|
||||||
|
}
|
||||||
|
|
||||||
|
node.$children.hide().empty();
|
||||||
|
|
||||||
|
if (child_nodes) {
|
||||||
|
$.each(child_nodes, (_i, data) => {
|
||||||
|
this.add_node(node, data);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.add_connector(node.id, data.id);
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
node.$children.show();
|
||||||
|
$(`path[data-parent="${node.id}"]`).show();
|
||||||
|
node.expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
add_node(node, data) {
|
add_node(node, data) {
|
||||||
return new this.Node({
|
return new this.Node({
|
||||||
id: data.id,
|
id: data.id,
|
||||||
@ -333,7 +439,7 @@ erpnext.HierarchyChart = class {
|
|||||||
path.setAttribute("class", "active-connector");
|
path.setAttribute("class", "active-connector");
|
||||||
path.setAttribute("marker-start", "url(#arrowstart-active)");
|
path.setAttribute("marker-start", "url(#arrowstart-active)");
|
||||||
path.setAttribute("marker-end", "url(#arrowhead-active)");
|
path.setAttribute("marker-end", "url(#arrowhead-active)");
|
||||||
} else if (parent.hasClass('active-path')) {
|
} else {
|
||||||
path.setAttribute("class", "collapsed-connector");
|
path.setAttribute("class", "collapsed-connector");
|
||||||
path.setAttribute("marker-start", "url(#arrowstart-collapsed)");
|
path.setAttribute("marker-start", "url(#arrowstart-collapsed)");
|
||||||
path.setAttribute("marker-end", "url(#arrowhead-collapsed)");
|
path.setAttribute("marker-end", "url(#arrowhead-collapsed)");
|
||||||
|
@ -194,6 +194,7 @@
|
|||||||
.level {
|
.level {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
#arrows {
|
#arrows {
|
||||||
|
29
erpnext/utilities/hierarchy_chart.py
Normal file
29
erpnext/utilities/hierarchy_chart.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# MIT License. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_all_nodes(parent, parent_name, method, company):
|
||||||
|
'''Recursively gets all data from nodes'''
|
||||||
|
method = frappe.get_attr(method)
|
||||||
|
|
||||||
|
if not method in frappe.whitelisted:
|
||||||
|
frappe.throw(_('Not Permitted'), frappe.PermissionError)
|
||||||
|
|
||||||
|
data = method(parent, company)
|
||||||
|
result = [dict(parent=parent, parent_name=parent_name, data=data)]
|
||||||
|
|
||||||
|
nodes_to_expand = [{'id': d.get('id'), 'name': d.get('name')} for d in data if d.get('expandable')]
|
||||||
|
|
||||||
|
while nodes_to_expand:
|
||||||
|
parent = nodes_to_expand.pop(0)
|
||||||
|
data = method(parent.get('id'), company)
|
||||||
|
result.append(dict(parent=parent.get('id'), parent_name=parent.get('name'), data=data))
|
||||||
|
for d in data:
|
||||||
|
if d.get('expandable'):
|
||||||
|
nodes_to_expand.append({'id': d.get('id'), 'name': d.get('name')})
|
||||||
|
|
||||||
|
return result
|
Loading…
x
Reference in New Issue
Block a user