feat: Organizational Chart (#26893)

* feat: Organizational Chart

* feat: org chart mobile interactions

* feat(mobile): sibling node group expansion and rendering

* fix: expanded node group interactions and visibility

* feat: connectors for mobile node cards

* fix: don't refresh connections for same node

- remove all connectors while expanding a group node

* chore: create separate files for Desktop and Mobile view and bundle assets

* refactor: add options to chart

- method to return the node data

- wrapper for showing the hierarchy

* feat: setup node edit action

* fix: revert changes in employee descendants query

* refactor: use arcs instead of bezier curves for cleaner connectors

* feat: add arc to connectors in mobile view

* fix: edit node button overflowing

* fix: sider

* fix: removing orphaned connectors

* fix: unnecessary variables

* feat: handle multiple root / orphan nodes

* perf: Optimise Rendering

- optimise get_children function

- use promises instead of callbacks

- optimise selectors

- use const wherever possible

- use pure js instead of jquery for connectors for faster rendering

* fix: do not sort by number of connections

* feat: use icon for connections on mobile view

* fix: exclude active node while fetching sibling group

* fix: sibling group expansion not working for root nodes

* fix(mobile): collapsed nodes not expanding

* fix: sider

* test: UI tests for org chart desktop

* test: UI tests for org chart mobile

fix(mobile): detach node before emptying hierarchy

fix(mobile): sibling group not rendering for first level

* fix: sider

* ci(cypress): use env variable for key

documentation ref: https://docs.cypress.io/guides/guides/command-line\#cypress-run

* fix(tests): clear filter before typing

* fix(tests): apply filters correctly

* fix: tests

* fix: tests

* fix: tests

* fix(test): increase timeout for record creation

* fix: sider

* fix: sider

* feat: Expand All nodes option in Desktop view

* feat: add html2canvas for easily exporting html to images using canvas

* feat: Export chart option in desktop view

* fix(style): longer titles overflowing

* fix: remove unnecessary imports

* fix: test

* fix: make bundled assets for hierarchy chart

* fix(style): apply svg container margin only in desktop view

* fix: Nest `.level` class style under `.hierarchy` class (#26905)

fix: Nest `.level` class style under `.hierarchy` class

* fix: add z-index to filter to avoid svg wrapper overlapping

* fix: expand all nodes not working when there are only 2 levels

- added dom freeze while expanding all nodes and exporting

* fix: test

Co-authored-by: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com>
This commit is contained in:
Rucha Mahabal
2021-08-16 20:42:23 +05:30
committed by GitHub
19 changed files with 2019 additions and 4 deletions

View File

@@ -0,0 +1,21 @@
frappe.pages['organizational-chart'].on_page_load = function(wrapper) {
frappe.ui.make_app_page({
parent: wrapper,
title: __('Organizational Chart'),
single_column: true
});
$(wrapper).bind('show', () => {
frappe.require('hierarchy-chart.bundle.js', () => {
let organizational_chart = undefined;
let method = 'erpnext.hr.page.organizational_chart.organizational_chart.get_children';
if (frappe.is_mobile()) {
organizational_chart = new erpnext.HierarchyChartMobile('Employee', wrapper, method);
} else {
organizational_chart = new erpnext.HierarchyChart('Employee', wrapper, method);
}
organizational_chart.show();
});
});
};

View File

@@ -0,0 +1,26 @@
{
"content": null,
"creation": "2021-05-25 10:53:10.107241",
"docstatus": 0,
"doctype": "Page",
"idx": 0,
"modified": "2021-05-25 10:53:18.201931",
"modified_by": "Administrator",
"module": "HR",
"name": "organizational-chart",
"owner": "Administrator",
"page_name": "Organizational Chart",
"roles": [
{
"role": "HR User"
},
{
"role": "HR Manager"
}
],
"script": null,
"standard": "Yes",
"style": null,
"system_page": 0,
"title": "Organizational Chart"
}

View File

@@ -0,0 +1,48 @@
from __future__ import unicode_literals
import frappe
@frappe.whitelist()
def get_children(parent=None, company=None, exclude_node=None):
filters = [['status', '!=', 'Left']]
if company and company != 'All Companies':
filters.append(['company', '=', company])
if parent and company and parent != company:
filters.append(['reports_to', '=', parent])
else:
filters.append(['reports_to', '=', ''])
if exclude_node:
filters.append(['name', '!=', exclude_node])
employees = frappe.get_list('Employee',
fields=['employee_name as name', 'name as id', 'reports_to', 'image', 'designation as title'],
filters=filters,
order_by='name'
)
for employee in employees:
is_expandable = frappe.db.count('Employee', filters={'reports_to': employee.get('id')})
employee.connections = get_connections(employee.id)
employee.expandable = 1 if is_expandable else 0
return employees
def get_connections(employee):
num_connections = 0
nodes_to_expand = frappe.get_list('Employee', filters=[
['reports_to', '=', employee]
])
num_connections += len(nodes_to_expand)
while nodes_to_expand:
parent = nodes_to_expand.pop(0)
descendants = frappe.get_list('Employee', filters=[
['reports_to', '=', parent.name]
])
num_connections += len(descendants)
nodes_to_expand.extend(descendants)
return num_connections