feat: Expand All nodes option in Desktop view
diff --git a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
index fe4d17c..694c265 100644
--- a/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
+++ b/erpnext/public/js/hierarchy_chart/hierarchy_chart_desktop.js
@@ -36,7 +36,11 @@
 
 				me.nodes[this.id] = 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);
 			}
 		};
@@ -60,8 +64,9 @@
 	show() {
 		frappe.breadcrumbs.add('HR');
 
-		let me = this;
+		this.setup_actions();
 		if ($(`[data-fieldname="company"]`).length) return;
+		let me = this;
 
 		let company = this.page.add_field({
 			fieldtype: 'Link',
@@ -79,20 +84,9 @@
 
 					// svg for connectors
 					me.make_svg_markers();
-
-					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.setup_hierarchy()
 					me.render_root_nodes();
+					me.all_nodes_expanded = false;
 				}
 			}
 		});
@@ -101,6 +95,42 @@
 		$(`[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() {
 		$('#arrows').remove();
 
@@ -126,7 +156,7 @@
 			</svg>`);
 	}
 
-	render_root_nodes() {
+	render_root_nodes(expanded_view=false) {
 		let me = this;
 
 		frappe.call({
@@ -156,7 +186,10 @@
 						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 @@
 		$(`#${node.parent_id}`).addClass('active-path');
 	}
 
-	load_children(node) {
-		frappe.run_serially([
-			() => this.get_child_nodes(node.id),
-			(child_nodes) => this.render_child_nodes(node, child_nodes)
-		]);
+	load_children(node, deep=false) {
+		if (!deep) {
+			frappe.run_serially([
+				() => 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) {
@@ -247,6 +289,70 @@
 		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) {
 		return new this.Node({
 			id: data.id,
@@ -333,7 +439,7 @@
 			path.setAttribute("class", "active-connector");
 			path.setAttribute("marker-start", "url(#arrowstart-active)");
 			path.setAttribute("marker-end", "url(#arrowhead-active)");
-		} else if (parent.hasClass('active-path')) {
+		} else {
 			path.setAttribute("class", "collapsed-connector");
 			path.setAttribute("marker-start", "url(#arrowstart-collapsed)");
 			path.setAttribute("marker-end", "url(#arrowhead-collapsed)");
diff --git a/erpnext/public/scss/hierarchy_chart.scss b/erpnext/public/scss/hierarchy_chart.scss
index dd523c3..1c2f942 100644
--- a/erpnext/public/scss/hierarchy_chart.scss
+++ b/erpnext/public/scss/hierarchy_chart.scss
@@ -194,6 +194,7 @@
 .level {
 	margin-right: 8px;
 	align-items: flex-start;
+	flex-direction: column;
 }
 
 #arrows {
diff --git a/erpnext/utilities/hierarchy_chart.py b/erpnext/utilities/hierarchy_chart.py
new file mode 100644
index 0000000..9b02793
--- /dev/null
+++ b/erpnext/utilities/hierarchy_chart.py
@@ -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
\ No newline at end of file