summaryrefslogtreecommitdiff
path: root/hr_organizational_chart/static
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 17:14:58 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 17:14:58 +0700
commit1ca3b3df3421961caec3b747a364071c80f5c7da (patch)
tree6778a1f0f3f9b4c6e26d6d87ccde16e24da6c9d6 /hr_organizational_chart/static
parentb57188be371d36d96caac4b8d65a40745c0e972c (diff)
initial commit
Diffstat (limited to 'hr_organizational_chart/static')
-rw-r--r--hr_organizational_chart/static/description/assets/icons/chevron.pngbin0 -> 310 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/cogs.pngbin0 -> 1377 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/consultation.pngbin0 -> 1458 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/ecom-black.pngbin0 -> 576 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/education-black.pngbin0 -> 733 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/hotel-black.pngbin0 -> 911 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/license.pngbin0 -> 1095 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/lifebuoy.pngbin0 -> 1199 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/manufacturing-black.pngbin0 -> 673 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/pos-black.pngbin0 -> 878 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/puzzle.pngbin0 -> 653 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/restaurant-black.pngbin0 -> 905 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/service-black.pngbin0 -> 839 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/trading-black.pngbin0 -> 427 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/training.pngbin0 -> 627 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/update.pngbin0 -> 1225 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/user.pngbin0 -> 988 bytes
-rw-r--r--hr_organizational_chart/static/description/assets/icons/wrench.pngbin0 -> 1205 bytes
-rw-r--r--hr_organizational_chart/static/description/banner.pngbin0 -> 75622 bytes
-rw-r--r--hr_organizational_chart/static/description/icon.pngbin0 -> 21371 bytes
-rw-r--r--hr_organizational_chart/static/description/images/bio_image.pngbin0 -> 162841 bytes
-rw-r--r--hr_organizational_chart/static/description/images/chart_expand.pngbin0 -> 130156 bytes
-rw-r--r--hr_organizational_chart/static/description/images/chart_shrink.pngbin0 -> 63272 bytes
-rw-r--r--hr_organizational_chart/static/description/images/chart_view.pngbin0 -> 131638 bytes
-rw-r--r--hr_organizational_chart/static/description/images/checked.pngbin0 -> 21786 bytes
-rw-r--r--hr_organizational_chart/static/description/images/core_image.gifbin0 -> 90859 bytes
-rw-r--r--hr_organizational_chart/static/description/images/custody_image.pngbin0 -> 72933 bytes
-rw-r--r--hr_organizational_chart/static/description/images/dash_image.gifbin0 -> 417726 bytes
-rw-r--r--hr_organizational_chart/static/description/images/hero.pngbin0 -> 187495 bytes
-rw-r--r--hr_organizational_chart/static/description/images/loan_image.pngbin0 -> 63784 bytes
-rw-r--r--hr_organizational_chart/static/description/images/menu_item_click.pngbin0 -> 470250 bytes
-rw-r--r--hr_organizational_chart/static/description/images/openhrms.pngbin0 -> 31962 bytes
-rw-r--r--hr_organizational_chart/static/description/images/org_chart.gifbin0 -> 117149 bytes
-rw-r--r--hr_organizational_chart/static/description/images/profile_view.pngbin0 -> 124956 bytes
-rw-r--r--hr_organizational_chart/static/description/images/salary_image.pngbin0 -> 117368 bytes
-rw-r--r--hr_organizational_chart/static/description/index.html550
-rw-r--r--hr_organizational_chart/static/js/hr_org_chart.js89
-rw-r--r--hr_organizational_chart/static/js/jquery_hr_orgchart.js1047
-rw-r--r--hr_organizational_chart/static/src/css/hr_orgchart.css474
-rw-r--r--hr_organizational_chart/static/src/css/style.css42
-rw-r--r--hr_organizational_chart/static/src/img/default_image.pngbin0 -> 2723 bytes
-rw-r--r--hr_organizational_chart/static/src/js/organizational_view.js100
-rw-r--r--hr_organizational_chart/static/src/scss/chart_view.scss73
-rw-r--r--hr_organizational_chart/static/src/xml/chart_view.xml20
-rw-r--r--hr_organizational_chart/static/src/xml/hr_org_chart_template.xml20
45 files changed, 2415 insertions, 0 deletions
diff --git a/hr_organizational_chart/static/description/assets/icons/chevron.png b/hr_organizational_chart/static/description/assets/icons/chevron.png
new file mode 100644
index 0000000..2089293
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/chevron.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/cogs.png b/hr_organizational_chart/static/description/assets/icons/cogs.png
new file mode 100644
index 0000000..95d0bad
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/cogs.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/consultation.png b/hr_organizational_chart/static/description/assets/icons/consultation.png
new file mode 100644
index 0000000..8319d4b
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/consultation.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/ecom-black.png b/hr_organizational_chart/static/description/assets/icons/ecom-black.png
new file mode 100644
index 0000000..a9385ff
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/ecom-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/education-black.png b/hr_organizational_chart/static/description/assets/icons/education-black.png
new file mode 100644
index 0000000..3eb09b2
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/education-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/hotel-black.png b/hr_organizational_chart/static/description/assets/icons/hotel-black.png
new file mode 100644
index 0000000..130f613
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/hotel-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/license.png b/hr_organizational_chart/static/description/assets/icons/license.png
new file mode 100644
index 0000000..a586979
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/license.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/lifebuoy.png b/hr_organizational_chart/static/description/assets/icons/lifebuoy.png
new file mode 100644
index 0000000..658d56c
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/lifebuoy.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/manufacturing-black.png b/hr_organizational_chart/static/description/assets/icons/manufacturing-black.png
new file mode 100644
index 0000000..697eb0e
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/manufacturing-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/pos-black.png b/hr_organizational_chart/static/description/assets/icons/pos-black.png
new file mode 100644
index 0000000..97c0f90
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/pos-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/puzzle.png b/hr_organizational_chart/static/description/assets/icons/puzzle.png
new file mode 100644
index 0000000..65cf854
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/puzzle.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/restaurant-black.png b/hr_organizational_chart/static/description/assets/icons/restaurant-black.png
new file mode 100644
index 0000000..4a35eb9
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/restaurant-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/service-black.png b/hr_organizational_chart/static/description/assets/icons/service-black.png
new file mode 100644
index 0000000..301ab51
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/service-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/trading-black.png b/hr_organizational_chart/static/description/assets/icons/trading-black.png
new file mode 100644
index 0000000..9398ba2
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/trading-black.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/training.png b/hr_organizational_chart/static/description/assets/icons/training.png
new file mode 100644
index 0000000..884ca02
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/training.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/update.png b/hr_organizational_chart/static/description/assets/icons/update.png
new file mode 100644
index 0000000..ecbc5a0
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/update.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/user.png b/hr_organizational_chart/static/description/assets/icons/user.png
new file mode 100644
index 0000000..6ffb23d
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/user.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/assets/icons/wrench.png b/hr_organizational_chart/static/description/assets/icons/wrench.png
new file mode 100644
index 0000000..6c04dea
--- /dev/null
+++ b/hr_organizational_chart/static/description/assets/icons/wrench.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/banner.png b/hr_organizational_chart/static/description/banner.png
new file mode 100644
index 0000000..8416aa6
--- /dev/null
+++ b/hr_organizational_chart/static/description/banner.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/icon.png b/hr_organizational_chart/static/description/icon.png
new file mode 100644
index 0000000..4967efd
--- /dev/null
+++ b/hr_organizational_chart/static/description/icon.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/bio_image.png b/hr_organizational_chart/static/description/images/bio_image.png
new file mode 100644
index 0000000..acc34b2
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/bio_image.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/chart_expand.png b/hr_organizational_chart/static/description/images/chart_expand.png
new file mode 100644
index 0000000..3250a95
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/chart_expand.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/chart_shrink.png b/hr_organizational_chart/static/description/images/chart_shrink.png
new file mode 100644
index 0000000..1a995e1
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/chart_shrink.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/chart_view.png b/hr_organizational_chart/static/description/images/chart_view.png
new file mode 100644
index 0000000..5bfb5d2
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/chart_view.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/checked.png b/hr_organizational_chart/static/description/images/checked.png
new file mode 100644
index 0000000..c8e371f
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/checked.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/core_image.gif b/hr_organizational_chart/static/description/images/core_image.gif
new file mode 100644
index 0000000..e303923
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/core_image.gif
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/custody_image.png b/hr_organizational_chart/static/description/images/custody_image.png
new file mode 100644
index 0000000..439a5ef
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/custody_image.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/dash_image.gif b/hr_organizational_chart/static/description/images/dash_image.gif
new file mode 100644
index 0000000..f5cac4e
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/dash_image.gif
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/hero.png b/hr_organizational_chart/static/description/images/hero.png
new file mode 100644
index 0000000..87b52bc
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/hero.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/loan_image.png b/hr_organizational_chart/static/description/images/loan_image.png
new file mode 100644
index 0000000..76c7ce5
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/loan_image.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/menu_item_click.png b/hr_organizational_chart/static/description/images/menu_item_click.png
new file mode 100644
index 0000000..0b5712e
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/menu_item_click.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/openhrms.png b/hr_organizational_chart/static/description/images/openhrms.png
new file mode 100644
index 0000000..a462223
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/openhrms.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/org_chart.gif b/hr_organizational_chart/static/description/images/org_chart.gif
new file mode 100644
index 0000000..4d0b9e6
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/org_chart.gif
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/profile_view.png b/hr_organizational_chart/static/description/images/profile_view.png
new file mode 100644
index 0000000..728a868
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/profile_view.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/images/salary_image.png b/hr_organizational_chart/static/description/images/salary_image.png
new file mode 100644
index 0000000..127ea73
--- /dev/null
+++ b/hr_organizational_chart/static/description/images/salary_image.png
Binary files differ
diff --git a/hr_organizational_chart/static/description/index.html b/hr_organizational_chart/static/description/index.html
new file mode 100644
index 0000000..c8b2d9c
--- /dev/null
+++ b/hr_organizational_chart/static/description/index.html
@@ -0,0 +1,550 @@
+<div style="padding: 3.5rem 1.5rem !important; background-color: #ffffff !important;">
+ <div class="container">
+ <!-- HERO -->
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center"
+ style="text-align: center; padding: 1rem !important;">
+ <h1 class="text-center" style="color: #00438B !important; font-size: 3rem !important;"><span
+ style="font-weight: 700 !important;">OpenHRMS</span><span style="font-weight: 300 !important;">
+ HR ORGANIZATIONAL CHART</span></h1>
+ <p class="text-center"
+ style="color: #212529 !important; font-size: 1.5rem !important; letter-spacing: 2px !important;">
+ Company Hierarchy At A Glance</p>
+ <img src="./images/hero.png" class="img-responsive">
+ </div>
+ </div>
+ <!-- END OF HERO -->
+
+ <!-- OVERVIEW -->
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center"
+ style="text-align: center; padding: 2.5rem 1rem !important;">
+ <h2 style="color: #212529 !important;">Overview</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+ <p class="text-center" style="color: #212529 !important; font-size: 1.5rem !important;">
+ This module give the overall department based HR Organizational Chart.
+ </p>
+ </div>
+ </div>
+ <!-- END OF OVERVIEW -->
+
+
+ <!-- KEY FEATURES -->
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center" style="padding: 2.5rem 1rem !important;">
+ <h2 class="text-center" style="color: #212529 !important;">Key Features</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+ <div class="row">
+ <div class="col-lg-6">
+
+ <div class="d-flex deep-2"
+ style="height: 60px !important; padding: 1rem 1.5rem !important; border-radius: 0 !important; margin: 1.5rem 0">
+ <img src="./images/checked.png" style="height: 24px !important; width: 24px !important;"
+ class="mt-1 mr-2" height="24px" width="24px">
+ <p style="color: #212529 !important; font-size: 1.3rem !important;">
+ View overall hierarchy of the HR department.
+ </p>
+ </div>
+
+ <div class="d-flex deep-2"
+ style="height: 60px !important; padding: 1rem 1.5rem !important; border-radius: 0 !important; margin: 1.5rem 0">
+ <img src="./images/checked.png" style="height: 24px !important; width: 24px !important;"
+ class="mt-1 mr-2" height="24px" width="24px">
+ <p style="color: #212529 !important; font-size: 1.3rem !important;">
+ Easly get employee form by a click
+ </p>
+ </div>
+ </div>
+ <div class="col-lg-6">
+ <div class="d-flex deep-2"
+ style="height: 60px !important; padding: 1rem 1.5rem !important; border-radius: 0 !important; margin: 1.5rem 0">
+ <img src="./images/checked.png" style="height: 24px !important; width: 24px !important;"
+ class="mt-1 mr-2" height="24px" width="24px">
+ <p style="color: #212529 !important; font-size: 1.3rem !important;">
+ Get child hierarchy by click on image
+ </p>
+ </div>
+
+ <div class="d-flex deep-2"
+ style="height: 60px !important; padding: 1rem 1.5rem !important; border-radius: 0 !important; margin: 1.5rem 0">
+ <img src="./images/checked.png" style="height: 24px !important; width: 24px !important;"
+ class="mt-1 mr-2" height="24px" width="24px">
+ <p style="color: #212529 !important; font-size: 1.3rem !important;">
+ Department included Profile view in this chart
+ </p>
+ </div>
+
+ </div>
+
+
+ </div>
+
+ </div>
+ </div>
+
+ <!-- END OF KEY FEATURES -->
+
+ <!-- SCREENSHOTS -->
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center" style="padding: 2.5rem 1rem !important;">
+ <h2 style="text-align: center; color: #212529 !important;">Screenshots</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+
+ <!-- img -->
+ <div class="d-flex m-0">
+ <div class="mr-3">
+ <h3
+ style="font-size: 2rem !important; font-weight: 800 !important; color: #ffffff !important; background-color: #00438B !important; padding: 1rem !important; width: 70px !important; height: 80px !important;">
+ 01</h3>
+ </div>
+ <div>
+ <h3 style="font-size: 1.7rem !important; font-weight: 600 !important;"> Chart view in menu item
+ click.
+ </h3>
+ </div>
+ </div>
+ <img src="./images/menu_item_click.png" class="img-responsive"
+ style="margin-top: -15px !important; border-top: 5px solid #00438B !important; margin-bottom: 4rem !important;">
+ <!-- endo of img -->
+
+ <!-- img -->
+ <div class="d-flex m-0">
+ <div class="mr-3">
+ <h3
+ style="font-size: 2rem !important; font-weight: 800 !important; color: #ffffff !important; background-color: #00438B !important; padding: 1rem !important; width: 70px !important; height: 80px !important;">
+ 02</h3>
+ </div>
+ <div>
+ <h3 style="font-size: 1.7rem !important; font-weight: 600 !important;">Easily expandable chart
+ </h3>
+
+ </div>
+ </div>
+ <img src="./images/chart_expand.png" class="img-responsive"
+ style="margin-top: -15px !important; border-top: 5px solid #00438B !important; margin-bottom: 4rem !important;">
+ <!-- endo of img -->
+
+ <!-- img -->
+ <div class="d-flex m-0">
+ <div class="mr-3">
+ <h3
+ style="font-size: 2rem !important; font-weight: 800 !important; color: #ffffff !important; background-color: #00438B !important; padding: 1rem !important; width: 70px !important; height: 80px !important;">
+ 03</h3>
+ </div>
+ <div>
+ <h3 style="font-size: 1.7rem !important; font-weight: 600 !important;">Easily shrinkable chart
+ </h3>
+ </div>
+ </div>
+ <img src="./images/chart_shrink.png" class="img-responsive"
+ style="margin-top: -15px !important; border-top: 5px solid #00438B !important; margin-bottom: 4rem !important;">
+ <!-- endo of img -->
+
+ <!-- img -->
+ <div class="d-flex m-0">
+ <div class="mr-3">
+ <h3
+ style="font-size: 2rem !important; font-weight: 800 !important; color: #ffffff !important; background-color: #00438B !important; padding: 1rem !important; width: 70px !important; height: 80px !important;">
+ 04</h3>
+ </div>
+ <div>
+ <h3 style="font-size: 1.7rem !important; font-weight: 600 !important;">Complete chart view
+ </h3>
+ </div>
+ </div>
+ <img src="./images/chart_view.png" class="img-responsive"
+ style="margin-top: -15px !important; border-top: 5px solid #00438B !important; margin-bottom: 4rem !important;">
+ <!-- endo of img -->
+ </div>
+ </div>
+ <!-- END OF SCREENSHOTS -->
+
+
+ <!-- SUGGESTED PRODUCTS -->
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center"
+ style="text-align: center; padding: 2.5rem 1rem !important;">
+ <h2 style="color: #212529 !important;">Suggested Products</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+
+ <div id="demo1" class="row carousel slide" data-ride="carousel">
+ <!-- The slideshow -->
+ <div class="carousel-inner">
+ <div class="carousel-item active" style="min-height:0px">
+ <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
+ <a href="https://apps.odoo.com/apps/modules/14.0/ohrms_core/" target="_blank">
+ <div style="border-radius:10px">
+ <img class="img img-responsive center-block"
+ style="border-top-left-radius:10px; border-top-right-radius:10px"
+ src="./images/core_image.gif">
+ </div>
+ </a>
+ </div>
+ <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
+ <a href="https://apps.odoo.com/apps/modules/14.0/ohrms_salary_advance/" target="_blank">
+ <div style="border-radius:10px">
+ <img class="img img-responsive center-block"
+ style="border-top-left-radius:10px; border-top-right-radius:10px"
+ src="./images/advance_image.png">
+ </div>
+ </a>
+ </div>
+ <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
+ <a href="https://apps.odoo.com/apps/modules/13.0/oh_hr_zk_attendance/" target="_blank">
+ <div style="border-radius:10px">
+ <img class="img img-responsive center-block"
+ style="border-top-left-radius:10px; border-top-right-radius:10px"
+ src="./images/bio_image.png">
+ </div>
+ </a>
+ </div>
+ </div>
+ <div class="carousel-item" style="min-height:0px">
+ <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
+ <a href="https://apps.odoo.com/apps/modules/14.0/ohrms_loan/" target="_blank">
+ <div style="border-radius:10px">
+ <img class="img img-responsive center-block"
+ style="border-top-left-radius:10px; border-top-right-radius:10px"
+ src="./images/loan_image.png">
+ </div>
+ </a>
+ </div>
+ <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
+ <a href="https://apps.odoo.com/apps/modules/14.0/hr_custody/" target="_blank">
+ <div style="border-radius:10px">
+ <img class="img img-responsive center-block"
+ style="border-top-left-radius:10px; border-top-right-radius:10px"
+ src="./images/custody_image.png">
+ </div>
+ </a>
+ </div>
+ <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
+ <a href="https://apps.odoo.com/apps/modules/13.0/ohrms_salary_advance/" target="_blank">
+ <div style="border-radius:10px">
+ <img class="img img-responsive center-block"
+ style="border-top-left-radius:10px; border-top-right-radius:10px"
+ src="./images/salary_image.png">
+ </div>
+ </a>
+ </div>
+ </div>
+ </div>
+ <!-- Left and right controls -->
+ <a class="carousel-control-prev" href="#demo1" data-slide="prev"
+ style="left:-25px;width: 35px;color: #000;"> <span class="carousel-control-prev-icon"><i
+ class="fa fa-chevron-left" style="font-size:24px"></i></span> </a> <a
+ class="carousel-control-next" href="#demo1" data-slide="next"
+ style="right:-25px;width: 35px;color: #000;">
+ <span class="carousel-control-next-icon"><i class="fa fa-chevron-right"
+ style="font-size:24px"></i></span>
+ </a>
+ </div>
+ </div>
+ </div>
+ <!-- END OF SUGGESTED PRODUCTS -->
+
+ <!-- OUR SERVICES -->
+ <section class="container" style="margin-top: 6rem !important;">
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center">
+ <h2 style="color: #212529 !important;">Our Services</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Customization</h6>
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Implementation</h6>
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Support</h6>
+ </div>
+
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Hire
+ Odoo
+ Developer</h6>
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Integration</h6>
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Migration</h6>
+ </div>
+
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Consultancy</h6>
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Implementation</h6>
+ </div>
+
+ <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
+ <div class="d-flex justify-content-center align-items-center mx-3 my-3"
+ style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
+ <img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px">
+ </div>
+ <h6 class="text-center"
+ style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">Odoo
+ Licensing Consultancy</h6>
+ </div>
+ </div>
+ </section>
+ <!-- END OF END OF OUR SERVICES -->
+
+ <!-- OUR INDUSTRIES -->
+ <section class="container" style="margin-top: 6rem !important;">
+ <div class="row">
+ <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center">
+ <h2 style="color: #212529 !important;">Our Industries</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/trading-black.png" class="img-responsive mb-3" height="48px"
+ width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ Trading
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ Easily procure
+ and
+ sell your products</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ POS
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ Easy
+ configuration
+ and convivial experience</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/education-black.png" class="img-responsive mb-3" height="48px"
+ width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ Education
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ A platform for
+ educational management</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px"
+ width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ Manufacturing
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ Plan, track and
+ schedule your operations</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ E-commerce &amp; Website
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ Mobile
+ friendly,
+ awe-inspiring product pages</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/service-black.png" class="img-responsive mb-3" height="48px"
+ width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ Service Management
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ Keep track of
+ services and invoice</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px"
+ width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ Restaurant
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ Run your bar or
+ restaurant methodically</p>
+ </div>
+ </div>
+
+ <div class="col-lg-3">
+ <div class="my-4 d-flex flex-column justify-content-center"
+ style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;">
+ <img src="./assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px"
+ width="48px">
+ <h5
+ style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
+ Hotel Management
+ </h5>
+ <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
+ An
+ all-inclusive
+ hotel management application</p>
+ </div>
+ </div>
+
+ </div>
+ </section>
+
+ <!-- END OF END OF OUR INDUSTRIES -->
+
+ <!-- FOOTER -->
+ <!-- Footer Section -->
+ <section class="container" style="margin: 5rem auto 2rem;">
+ <div class="row" style="max-width:1540px;">
+ <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center">
+ <h2 style="color: #212529 !important;">Need Help?</h2>
+ <hr
+ style="border: 3px solid #00438B !important; background-color: #00438B !important; width: 80px !important; margin-bottom: 2rem !important;" />
+ </div>
+ </div>
+
+ <!-- Contact Cards -->
+ <div class="row d-flex justify-content-center align-items-center"
+ style="max-width:1540px; margin: 0 auto 2rem auto;">
+
+ <div class="col-lg-12" style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; ">
+
+ <div class="row mt-4">
+ <div class="col-lg-4">
+ <a href="mailto:odoo@cybrosys.com" target="_blank" class="btn btn-block mb-2 deep_hover"
+ style="text-decoration: none; background-color: #4d4d4d; color: #FFF; border-radius: 4px;"><i
+ class="fa fa-envelope mr-2"></i>odoo@cybrosys.com</a>
+ </div>
+ <div class="col-lg-4">
+ <a href="https://api.whatsapp.com/send?phone=918606827707" target="_blank"
+ class="btn btn-block mb-2 deep_hover"
+ style="text-decoration: none; background-color: #25D366; color: #FFF; border-radius: 4px;"><i
+ class="fa fa-whatsapp mr-2"></i>WhatsApp</a>
+ </div>
+ <div class="col-lg-4">
+ <a href="mailto:info@cybrosys.com" target="_blank" class="btn btn-block deep_hover"
+ style="text-decoration: none; background-color: #4d4d4d; color: #FFF; border-radius: 4px;"><i
+ class="fa fa-envelope mr-2"></i>info@cybrosys.com</a>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <!-- End of Contact Cards -->
+ </section>
+ <!-- Footer -->
+ <section class="oe_container" style="padding: 2rem 3rem 1rem;">
+ <div class="row" style="max-width:1540px; margin: 0 auto; margin-right: 3rem; ">
+ <!-- Logo -->
+ <div class="col-lg-12 d-flex justify-content-center align-items-center" style="margin-top: 3rem;">
+ <img src="https://www.cybrosys.com/images/logo.png" width="200px" height="auto" />
+ </div>
+ <!-- End of Logo -->
+ <div class="col-lg-12">
+ <hr
+ style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;">
+ <!-- End of Footer Section -->
+ </div>
+ </div>
+ </section>
+ <!-- END OF FOOTER -->
+
+
+ </div>
+</div> \ No newline at end of file
diff --git a/hr_organizational_chart/static/js/hr_org_chart.js b/hr_organizational_chart/static/js/hr_org_chart.js
new file mode 100644
index 0000000..58bc15a
--- /dev/null
+++ b/hr_organizational_chart/static/js/hr_org_chart.js
@@ -0,0 +1,89 @@
+var employee_data = [];
+
+var nodeTemplate = function(data) {
+ return `
+ <span class="office">${data.office}</span>
+ <div class="title">${data.name}</div>
+ <div class="content">${data.title}</div>
+ `;
+ };
+
+odoo.define("hr_org_chart_employee.hr_org_chart", function (require) {
+ "use strict";
+
+ var core = require('web.core');
+ var session = require('web.session');
+ var ajax = require('web.ajax');
+ var Widget = require('web.Widget');
+ var QWeb = core.qweb;
+ var _t = core._t;
+ var AbstractAction = require('web.AbstractAction');
+ var _lt = core._lt;
+
+ var OrgChartDepartment = AbstractAction.extend({
+ events: {
+ 'click .nodes,.node': 'view_employee',
+ },
+ init: function(parent, context){
+ this._super(parent, context);
+ var self = this;
+ if (context.tag == 'employee_organization_chart') {
+ this._rpc({
+ route: '/get/employees',
+ }).then(function (result) {
+ self._rpc({
+ model: 'hr.organizational.chart',
+ method: 'get_employee_data',
+ args: [result],
+ }, []).then(function(values){
+ employee_data = values;
+ self.render();
+ self.href = window.location.href;
+ });
+ });
+ }
+ },
+ willStart: function() {
+ return $.when(ajax.loadLibs(this), this._super());
+ },
+ start: function() {
+ var self = this;
+ return this._super();
+ },
+ render: function() {
+ var super_render = this._super;
+ var self = this;
+ var org_chart = QWeb.render('hr_organizational_chart.org_chart_template', {
+ widget: self,
+ });
+ $(".o_control_panel").addClass("o_hidden");
+ $(org_chart).prependTo(self.$el);
+ return org_chart;
+ },
+ reload: function () {
+ window.location.href = this.href;
+ },
+ view_employee: function(ev){
+ if (ev.target.attributes[1]){
+ var id = parseInt(ev.target.attributes[1].nodeValue)
+ this.do_action({
+ name: _t("Employee"),
+ type: 'ir.actions.act_window',
+ res_model: 'hr.employee',
+ res_id: id,
+ view_mode: 'form',
+ views: [[false, 'form']],
+ })
+ }
+ },
+ });
+
+
+
+ core.action_registry.add('employee_organization_chart', OrgChartDepartment);
+ window.reload()
+
+ return OrgChartDepartment;
+
+
+}); \ No newline at end of file
diff --git a/hr_organizational_chart/static/js/jquery_hr_orgchart.js b/hr_organizational_chart/static/js/jquery_hr_orgchart.js
new file mode 100644
index 0000000..f074951
--- /dev/null
+++ b/hr_organizational_chart/static/js/jquery_hr_orgchart.js
@@ -0,0 +1,1047 @@
+/*
+ * jQuery OrgChart Plugin
+ * https://github.com/dabeng/OrgChart
+ *
+ * Copyright 2016, dabeng
+ * https://github.com/dabeng
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+'use strict';
+
+(function (factory) {
+ if (typeof module === 'object' && typeof module.exports === 'object') {
+ factory(require('jquery'), window, document);
+ } else {
+ factory(jQuery, window, document);
+ }
+}(function ($, window, document, undefined) {
+ var OrgChart = function (elem, opts) {
+ this.$chartContainer = $(elem);
+ this.opts = opts;
+ this.defaultOptions = {
+ 'nodeTitle': 'name',
+ 'nodeId': 'id',
+ 'toggleSiblingsResp': false,
+ 'visibleLevel': 999,
+ 'chartClass': '',
+ 'exportButton': false,
+ 'exportFilename': 'OrgChart',
+ 'exportFileextension': 'png',
+ 'draggable': false,
+ 'direction': 't2b',
+ 'pan': false,
+ 'zoom': false,
+ 'zoominLimit': 7,
+ 'zoomoutLimit': 0.5
+ };
+ };
+ //
+ OrgChart.prototype = {
+ //
+ init: function (opts) {
+ var that = this;
+ this.options = $.extend({}, this.defaultOptions, this.opts, opts);
+ // build the org-chart
+ var $chartContainer = this.$chartContainer;
+ if (this.$chart) {
+ this.$chart.remove();
+ }
+ var data = this.options.data;
+ var $chart = this.$chart = $('<div>', {
+ 'data': { 'options': this.options },
+ 'class': 'orgchart' + (this.options.chartClass !== '' ? ' ' + this.options.chartClass : '') + (this.options.direction !== 't2b' ? ' ' + this.options.direction : ''),
+ });
+ if (typeof MutationObserver !== 'undefined') {
+ this.triggerInitEvent();
+ }
+ if ($.type(data) === 'object') {
+ if (data instanceof $) { // ul datasource
+ this.buildHierarchy($chart, this.buildJsonDS(data.children()), 0, this.options);
+ } else { // local json datasource
+ this.buildHierarchy($chart, this.options.ajaxURL ? data : this.attachRel(data, '00'));
+ }
+ } else {
+ $chart.append('<i class="fa fa-circle-o-notch fa-spin spinner"></i>');
+ $.ajax({
+ 'url': data,
+ 'dataType': 'json'
+ })
+ .done(function(data, textStatus, jqXHR) {
+ that.buildHierarchy($chart, that.options.ajaxURL ? data : that.attachRel(data, '00'), 0, that.options);
+ })
+ .fail(function(jqXHR, textStatus, errorThrown) {
+ console.log(errorThrown);
+ })
+ .always(function() {
+ $chart.children('.spinner').remove();
+ });
+ }
+ $chartContainer.append($chart);
+
+ if (this.options.pan) {
+ this.bindPan();
+ }
+
+ if (this.options.zoom) {
+ this.bindZoom();
+ }
+
+ return this;
+ },
+ //
+ triggerInitEvent: function () {
+ var that = this;
+ var mo = new MutationObserver(function (mutations) {
+ mo.disconnect();
+ initTime:
+ for (var i = 0; i < mutations.length; i++) {
+ for (var j = 0; j < mutations[i].addedNodes.length; j++) {
+ if (mutations[i].addedNodes[j].classList.contains('orgchart')) {
+ if (that.options.initCompleted && typeof that.options.initCompleted === 'function') {
+ that.options.initCompleted(that.$chart);
+ var initEvent = $.Event('init.orgchart');
+ that.$chart.trigger(initEvent);
+ break initTime;
+ }
+ }
+ }
+ }
+ });
+ mo.observe(this.$chartContainer[0], { childList: true });
+ },
+ //
+ panStartHandler: function (e) {
+ var $chart = $(e.delegateTarget);
+ if ($(e.target).closest('.node').length || (e.touches && e.touches.length > 1)) {
+ $chart.data('panning', false);
+ return;
+ } else {
+ $chart.css('cursor', 'move').data('panning', true);
+ }
+ var lastX = 0;
+ var lastY = 0;
+ var lastTf = $chart.css('transform');
+ if (lastTf !== 'none') {
+ var temp = lastTf.split(',');
+ if (lastTf.indexOf('3d') === -1) {
+ lastX = parseInt(temp[4]);
+ lastY = parseInt(temp[5]);
+ } else {
+ lastX = parseInt(temp[12]);
+ lastY = parseInt(temp[13]);
+ }
+ }
+ var startX = 0;
+ var startY = 0;
+ if (!e.targetTouches) { // pand on desktop
+ startX = e.pageX - lastX;
+ startY = e.pageY - lastY;
+ } else if (e.targetTouches.length === 1) { // pan on mobile device
+ startX = e.targetTouches[0].pageX - lastX;
+ startY = e.targetTouches[0].pageY - lastY;
+ } else if (e.targetTouches.length > 1) {
+ return;
+ }
+ $chart.on('mousemove touchmove',function(e) {
+ if (!$chart.data('panning')) {
+ return;
+ }
+ var newX = 0;
+ var newY = 0;
+ if (!e.targetTouches) { // pand on desktop
+ newX = e.pageX - startX;
+ newY = e.pageY - startY;
+ } else if (e.targetTouches.length === 1) { // pan on mobile device
+ newX = e.targetTouches[0].pageX - startX;
+ newY = e.targetTouches[0].pageY - startY;
+ } else if (e.targetTouches.length > 1) {
+ return;
+ }
+ var lastTf = $chart.css('transform');
+ if (lastTf === 'none') {
+ if (lastTf.indexOf('3d') === -1) {
+ $chart.css('transform', 'matrix(1, 0, 0, 1, ' + newX + ', ' + newY + ')');
+ } else {
+ $chart.css('transform', 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + newX + ', ' + newY + ', 0, 1)');
+ }
+ } else {
+ var matrix = lastTf.split(',');
+ if (lastTf.indexOf('3d') === -1) {
+ matrix[4] = ' ' + newX;
+ matrix[5] = ' ' + newY + ')';
+ } else {
+ matrix[12] = ' ' + newX;
+ matrix[13] = ' ' + newY;
+ }
+ $chart.css('transform', matrix.join(','));
+ }
+ });
+ },
+ //
+ panEndHandler: function (e) {
+ if (e.data.chart.data('panning')) {
+ e.data.chart.data('panning', false).css('cursor', 'default').off('mousemove');
+ }
+ },
+ //
+ bindPan: function () {
+ this.$chartContainer.css('overflow', 'hidden');
+ this.$chart.on('mousedown touchstart', this.panStartHandler);
+ $(document).on('mouseup touchend', { 'chart': this.$chart }, this.panEndHandler);
+ },
+ //
+ unbindPan: function () {
+ this.$chartContainer.css('overflow', 'auto');
+ this.$chart.off('mousedown touchstart', this.panStartHandler);
+ $(document).off('mouseup touchend', this.panEndHandler);
+ },
+ //
+ zoomWheelHandler: function (e) {
+ var oc = e.data.oc;
+ e.preventDefault();
+ var newScale = 1 + (e.originalEvent.deltaY > 0 ? -0.2 : 0.2);
+ oc.setChartScale(oc.$chart, newScale);
+ },
+ //
+ zoomStartHandler: function (e) {
+ if(e.touches && e.touches.length === 2) {
+ var oc = e.data.oc;
+ oc.$chart.data('pinching', true);
+ var dist = oc.getPinchDist(e);
+ oc.$chart.data('pinchDistStart', dist);
+ }
+ },
+ zoomingHandler: function (e) {
+ var oc = e.data.oc;
+ if(oc.$chart.data('pinching')) {
+ var dist = oc.getPinchDist(e);
+ oc.$chart.data('pinchDistEnd', dist);
+ }
+ },
+ zoomEndHandler: function (e) {
+ var oc = e.data.oc;
+ if(oc.$chart.data('pinching')) {
+ oc.$chart.data('pinching', false);
+ var diff = oc.$chart.data('pinchDistEnd') - oc.$chart.data('pinchDistStart');
+ if (diff > 0) {
+ oc.setChartScale(oc.$chart, 1.2);
+ } else if (diff < 0) {
+ oc.setChartScale(oc.$chart, 0.8);
+ }
+ }
+ },
+ //
+ bindZoom: function () {
+ this.$chartContainer.on('wheel', { 'oc': this }, this.zoomWheelHandler);
+ this.$chartContainer.on('touchstart', { 'oc': this }, this.zoomStartHandler);
+ $(document).on('touchmove', { 'oc': this }, this.zoomingHandler);
+ $(document).on('touchend', { 'oc': this }, this.zoomEndHandler);
+ },
+ unbindZoom: function () {
+ this.$chartContainer.off('wheel', this.zoomWheelHandler);
+ this.$chartContainer.off('touchstart', this.zoomStartHandler);
+ $(document).off('touchmove', this.zoomingHandler);
+ $(document).off('touchend', this.zoomEndHandler);
+ },
+ //
+ getPinchDist: function (e) {
+ return Math.sqrt((e.touches[0].clientX - e.touches[1].clientX) * (e.touches[0].clientX - e.touches[1].clientX) +
+ (e.touches[0].clientY - e.touches[1].clientY) * (e.touches[0].clientY - e.touches[1].clientY));
+ },
+ //
+ setChartScale: function ($chart, newScale) {
+ var opts = $chart.data('options');
+ var lastTf = $chart.css('transform');
+ var matrix = '';
+ var targetScale = 1;
+ if (lastTf === 'none') {
+ $chart.css('transform', 'scale(' + newScale + ',' + newScale + ')');
+ } else {
+ matrix = lastTf.split(',');
+ if (lastTf.indexOf('3d') === -1) {
+ targetScale = Math.abs(window.parseFloat(matrix[3]) * newScale);
+ if (targetScale > opts.zoomoutLimit && targetScale < opts.zoominLimit) {
+ $chart.css('transform', lastTf + ' scale(' + newScale + ',' + newScale + ')');
+ }
+ } else {
+ targetScale = Math.abs(window.parseFloat(matrix[1]) * newScale);
+ if (targetScale > opts.zoomoutLimit && targetScale < opts.zoominLimit) {
+ $chart.css('transform', lastTf + ' scale3d(' + newScale + ',' + newScale + ', 1)');
+ }
+ }
+ }
+ },
+ //
+ buildJsonDS: function ($li) {
+ var that = this;
+ var subObj = {
+ 'name': $li.contents().eq(0).text().trim(),
+ 'relationship': ($li.parent().parent().is('li') ? '1': '0') + ($li.siblings('li').length ? 1: 0) + ($li.children('ul').length ? 1 : 0)
+ };
+ $.each($li.data(), function(key, value) {
+ subObj[key] = value;
+ });
+ $li.children('ul').children().each(function() {
+ if (!subObj.children) { subObj.children = []; }
+ subObj.children.push(that.buildJsonDS($(this)));
+ });
+ return subObj;
+ },
+ //
+ attachRel: function (data, flags) {
+ var that = this;
+ data.relationship = flags + (data.children && data.children.length > 0 ? 1 : 0);
+ if (data.children) {
+ data.children.forEach(function(item) {
+ that.attachRel(item, '1' + (data.children.length > 1 ? 1 : 0));
+ });
+ }
+ return data;
+ },
+ //
+ loopChart: function ($chart) {
+ var that = this;
+ var $tr = $chart.find('tr:first');
+ var subObj = { 'id': $tr.find('.node')[0].id };
+ $tr.siblings(':last').children().each(function() {
+ if (!subObj.children) { subObj.children = []; }
+ subObj.children.push(that.loopChart($(this)));
+ });
+ return subObj;
+ },
+ //
+ getHierarchy: function () {
+ if (typeof this.$chart === 'undefined') {
+ return 'Error: orgchart does not exist'
+ } else {
+ if (!this.$chart.find('.node').length) {
+ return 'Error: nodes do not exist'
+ } else {
+ var valid = true;
+ this.$chart.find('.node').each(function () {
+ if (!this.id) {
+ valid = false;
+ return false;
+ }
+ });
+ if (!valid) {
+ return 'Error: All nodes of orghcart to be exported must have data-id attribute!';
+ }
+ }
+ }
+ return this.loopChart(this.$chart);
+ },
+ // detect the exist/display state of related node
+ getNodeState: function ($node, relation) {
+ var $target = {};
+ var relation = relation || 'self';
+ if (relation === 'parent') {
+ $target = $node.closest('.nodes').siblings(':first');
+ if ($target.length) {
+ if ($target.is('.hidden') || (!$target.is('.hidden') && $target.closest('.nodes').is('.hidden'))) {
+ return { 'exist': true, 'visible': false };
+ }
+ return { 'exist': true, 'visible': true };
+ }
+ } else if (relation === 'children') {
+ $target = $node.closest('tr').siblings(':last');
+ if ($target.length) {
+ if (!$target.is('.hidden')) {
+ return { 'exist': true, 'visible': true };
+ }
+ return { 'exist': true, 'visible': false };
+ }
+ } else if (relation === 'siblings') {
+ $target = $node.closest('table').parent().siblings();
+ if ($target.length) {
+ if (!$target.is('.hidden') && !$target.parent().is('.hidden')) {
+ return { 'exist': true, 'visible': true };
+ }
+ return { 'exist': true, 'visible': false };
+ }
+ } else {
+ $target = $node;
+ if ($target.length) {
+ if (!(($target.closest('.nodes').length && $target.closest('.nodes').is('.hidden')) ||
+ ($target.closest('table').parent().length && $target.closest('table').parent().is('.hidden')) ||
+ ($target.parent().is('li') && ($target.closest('ul').is('.hidden') || $target.closest('verticalNodes').is('.hidden')))
+ )) {
+ return { 'exist': true, 'visible': true };
+ }
+ return { 'exist': true, 'visible': false };
+ }
+ }
+ return { 'exist': false, 'visible': false };
+ },
+ // find the related nodes
+ getRelatedNodes: function ($node, relation) {
+ if (!$node || !($node instanceof $) || !$node.is('.node')) {
+ return $();
+ }
+ if (relation === 'parent') {
+ return $node.closest('.nodes').parent().children(':first').find('.node');
+ } else if (relation === 'children') {
+ return $node.closest('tr').siblings('.nodes').children().find('.node:first');
+ } else if (relation === 'siblings') {
+ return $node.closest('table').parent().siblings().find('.node:first');
+ } else {
+ return $();
+ }
+ },
+ // show the parent node of the specified node
+ showParent: function ($node) {
+ // just show only one superior level
+ var $upperLevel = $node.closest('.nodes').siblings().removeClass('hidden');
+ // just show only one line
+ $upperLevel.eq(2).children().slice(1, -1).addClass('hidden');
+ // show parent node with animation
+ var $parent = $upperLevel.eq(0).find('.node');
+ this.repaint($parent[0]);
+ $parent.addClass('sliding').removeClass('slide-down').one('transitionend', { 'node': $node }, this.showParentEnd.bind(this));
+ },
+ stopAjax: function ($nodeLevel) {
+ if ($nodeLevel.find('.spinner').length) {
+ $nodeLevel.closest('.orgchart').data('inAjax', false);
+ }
+ },
+ isVisibleNode: function (index, elem) {
+ return this.getNodeState($(elem)).visible;
+ },
+ //
+ // start up loading status for requesting new nodes
+ startLoading: function ($edge) {
+ var $chart = this.$chart;
+ if (typeof $chart.data('inAjax') !== 'undefined' && $chart.data('inAjax') === true) {
+ return false;
+ }
+
+ $edge.addClass('hidden');
+ $edge.parent().append('<i class="fa fa-circle-o-notch fa-spin spinner"></i>')
+ .children().not('.spinner').css('opacity', 0.2);
+ $chart.data('inAjax', true);
+ $('.oc-export-btn' + (this.options.chartClass !== '' ? '.' + this.options.chartClass : '')).prop('disabled', true);
+ return true;
+ },
+ // terminate loading status for requesting new nodes
+ endLoading: function ($edge) {
+ var $node = $edge.parent();
+ $edge.removeClass('hidden');
+ $node.find('.spinner').remove();
+ $node.children().removeAttr('style');
+ this.$chart.data('inAjax', false);
+ $('.oc-export-btn' + (this.options.chartClass !== '' ? '.' + this.options.chartClass : '')).prop('disabled', false);
+ },
+ // whether the cursor is hovering over the node
+ isInAction: function ($node) {
+ return $node.children('.edge').attr('class').indexOf('fa-') > -1 ? true : false;
+ },
+ //
+ switchVerticalArrow: function ($arrow) {
+ $arrow.toggleClass('fa-chevron-up').toggleClass('fa-chevron-down');
+ },
+ //
+ switchHorizontalArrow: function ($node) {
+ var opts = this.options;
+ if (opts.toggleSiblingsResp && (typeof opts.ajaxURL === 'undefined' || $node.closest('.nodes').data('siblingsLoaded'))) {
+ var $prevSib = $node.closest('table').parent().prev();
+ if ($prevSib.length) {
+ if ($prevSib.is('.hidden')) {
+ $node.children('.leftEdge').addClass('fa-chevron-left').removeClass('fa-chevron-right');
+ } else {
+ $node.children('.leftEdge').addClass('fa-chevron-right').removeClass('fa-chevron-left');
+ }
+ }
+ var $nextSib = $node.closest('table').parent().next();
+ if ($nextSib.length) {
+ if ($nextSib.is('.hidden')) {
+ $node.children('.rightEdge').addClass('fa-chevron-right').removeClass('fa-chevron-left');
+ } else {
+ $node.children('.rightEdge').addClass('fa-chevron-left').removeClass('fa-chevron-right');
+ }
+ }
+ } else {
+ var $sibs = $node.closest('table').parent().siblings();
+ var sibsVisible = $sibs.length ? !$sibs.is('.hidden') : false;
+ $node.children('.leftEdge').toggleClass('fa-chevron-right', sibsVisible).toggleClass('fa-chevron-left', !sibsVisible);
+ $node.children('.rightEdge').toggleClass('fa-chevron-left', sibsVisible).toggleClass('fa-chevron-right', !sibsVisible);
+ }
+ },
+ //
+ repaint: function (node) {
+ if (node) {
+ node.style.offsetWidth = node.offsetWidth;
+ }
+ },
+ // load new nodes by ajax
+ loadNodes: function (rel, url, $edge) {
+ var that = this;
+ var opts = this.options;
+ $.ajax({ 'url': url, 'dataType': 'json' })
+ .done(function (data) {
+ if (that.$chart.data('inAjax')) {
+ if (rel === 'parent') {
+ if (!$.isEmptyObject(data)) {
+ that.addParent($edge.parent(), data);
+ }
+ } else if (rel === 'children') {
+ if (data.children.length) {
+ that.addChildren($edge.parent(), data[rel]);
+ }
+ } else {
+ that.addSiblings($edge.parent(), data.siblings ? data.siblings : data);
+ }
+ }
+ })
+ .fail(function () {
+ console.log('Failed to get ' + rel + ' data');
+ })
+ .always(function () {
+ that.endLoading($edge);
+ });
+ },
+ //
+ HideFirstParentEnd: function (event) {
+ var $topEdge = event.data.topEdge;
+ var $node = $topEdge.parent();
+ if (this.isInAction($node)) {
+ this.switchVerticalArrow($topEdge);
+ this.switchHorizontalArrow($node);
+ }
+ },
+ //
+ expandVNodesEnd: function (event) {
+ event.data.vNodes.removeClass('sliding');
+ },
+ //
+ collapseVNodesEnd: function (event) {
+ event.data.vNodes.removeClass('sliding').closest('ul').addClass('hidden');
+ },
+ //
+ createGhostNode: function (event) {
+ var $nodeDiv = $(event.target);
+ var opts = this.options;
+ var origEvent = event.originalEvent;
+ var isFirefox = /firefox/.test(window.navigator.userAgent.toLowerCase());
+ var ghostNode, nodeCover;
+ if (!document.querySelector('.ghost-node')) {
+ ghostNode = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+ ghostNode.classList.add('ghost-node');
+ nodeCover = document.createElementNS('http://www.w3.org/2000/svg','rect');
+ ghostNode.appendChild(nodeCover);
+ $nodeDiv.closest('.orgchart').append(ghostNode);
+ } else {
+ ghostNode = $nodeDiv.closest('.orgchart').children('.ghost-node').get(0);
+ nodeCover = $(ghostNode).children().get(0);
+ }
+ var transValues = $nodeDiv.closest('.orgchart').css('transform').split(',');
+ var isHorizontal = opts.direction === 't2b' || opts.direction === 'b2t';
+ var scale = Math.abs(window.parseFloat(isHorizontal ? transValues[0].slice(transValues[0].indexOf('(') + 1) : transValues[1]));
+ ghostNode.setAttribute('width', isHorizontal ? $nodeDiv.outerWidth(false) : $nodeDiv.outerHeight(false));
+ ghostNode.setAttribute('height', isHorizontal ? $nodeDiv.outerHeight(false) : $nodeDiv.outerWidth(false));
+ nodeCover.setAttribute('x',5 * scale);
+ nodeCover.setAttribute('y',5 * scale);
+ nodeCover.setAttribute('width', 120 * scale);
+ nodeCover.setAttribute('height', 40 * scale);
+ nodeCover.setAttribute('rx', 4 * scale);
+ nodeCover.setAttribute('ry', 4 * scale);
+ nodeCover.setAttribute('stroke-width', 1 * scale);
+ var xOffset = origEvent.offsetX * scale;
+ var yOffset = origEvent.offsetY * scale;
+ if (opts.direction === 'l2r') {
+ xOffset = origEvent.offsetY * scale;
+ yOffset = origEvent.offsetX * scale;
+ } else if (opts.direction === 'r2l') {
+ xOffset = $nodeDiv.outerWidth(false) - origEvent.offsetY * scale;
+ yOffset = origEvent.offsetX * scale;
+ } else if (opts.direction === 'b2t') {
+ xOffset = $nodeDiv.outerWidth(false) - origEvent.offsetX * scale;
+ yOffset = $nodeDiv.outerHeight(false) - origEvent.offsetY * scale;
+ }
+ if (isFirefox) { // hack for old version of Firefox(< 48.0)
+ nodeCover.setAttribute('fill', 'rgb(255, 255, 255)');
+ nodeCover.setAttribute('stroke', 'rgb(191, 0, 0)');
+ var ghostNodeWrapper = document.createElement('img');
+ ghostNodeWrapper.src = 'data:image/svg+xml;utf8,' + (new XMLSerializer()).serializeToString(ghostNode);
+ origEvent.dataTransfer.setDragImage(ghostNodeWrapper, xOffset, yOffset);
+ } else {
+ origEvent.dataTransfer.setDragImage(ghostNode, xOffset, yOffset);
+ }
+ },
+ //
+ filterAllowedDropNodes: function ($dragged) {
+ var opts = this.options;
+ var $dragZone = $dragged.closest('.nodes').siblings().eq(0).find('.node:first');
+ var $dragHier = $dragged.closest('table').find('.node');
+ this.$chart.data('dragged', $dragged)
+ .find('.node').each(function (index, node) {
+ if ($dragHier.index(node) === -1) {
+ if (opts.dropCriteria) {
+ if (opts.dropCriteria($dragged, $dragZone, $(node))) {
+ $(node).addClass('allowedDrop');
+ }
+ } else {
+ $(node).addClass('allowedDrop');
+ }
+ }
+ });
+ },
+ //
+ dragstartHandler: function (event) {
+ event.originalEvent.dataTransfer.setData('text/html', 'hack for firefox');
+ // if users enable zoom or direction options
+ if (this.$chart.css('transform') !== 'none') {
+ this.createGhostNode(event);
+ }
+ this.filterAllowedDropNodes($(event.target));
+ },
+ //
+ dragoverHandler: function (event) {
+ event.preventDefault();
+ if (!$(event.delegateTarget).is('.allowedDrop')) {
+ event.originalEvent.dataTransfer.dropEffect = 'none';
+ }
+ },
+ //
+ dragendHandler: function (event) {
+ this.$chart.find('.allowedDrop').removeClass('allowedDrop');
+ },
+ //
+ dropHandler: function (event) {
+ var $dropZone = $(event.delegateTarget);
+ var $dragged = this.$chart.data('dragged');
+ var $dragZone = $dragged.closest('.nodes').siblings().eq(0).children();
+ var dropEvent = $.Event('nodedrop.orgchart');
+ this.$chart.trigger(dropEvent, { 'draggedNode': $dragged, 'dragZone': $dragZone.children(), 'dropZone': $dropZone });
+ if (dropEvent.isDefaultPrevented()) {
+ return;
+ }
+ // firstly, deal with the hierarchy of drop zone
+ if (!$dropZone.closest('tr').siblings().length) { // if the drop zone is a leaf node
+ $dropZone.append('<i class="edge verticalEdge bottomEdge fa"></i>')
+ .parent().attr('colspan', 2)
+ .parent().after('<tr class="lines"><td colspan="2"><div class="lineDown"></div></td></tr>'
+ + '<tr class="lines"><td class="lineRight"></td><td class="lineLeft"></td></tr>'
+ + '<tr class="nodes"></tr>')
+ .siblings(':last').append($dragged.find('.horizontalEdge').remove().end().closest('table').parent());
+ } else {
+ var dropColspan = parseInt($dropZone.parent().attr('colspan')) + 2;
+ var horizontalEdges = '<i class="edge horizontalEdge rightEdge fa"></i><i class="edge horizontalEdge leftEdge fa"></i>';
+ $dropZone.closest('tr').next().addBack().children().attr('colspan', dropColspan);
+ if (!$dragged.find('.horizontalEdge').length) {
+ $dragged.append(horizontalEdges);
+ }
+ $dropZone.closest('tr').siblings().eq(1).children(':last').before('<td class="lineLeft lineTop"></td><td class="lineRight lineTop"></td>')
+ .end().next().append($dragged.closest('table').parent());
+ var $dropSibs = $dragged.closest('table').parent().siblings().find('.node:first');
+ if ($dropSibs.length === 1) {
+ $dropSibs.append(horizontalEdges);
+ }
+ }
+ // secondly, deal with the hierarchy of dragged node
+ var dragColspan = parseInt($dragZone.attr('colspan'));
+ if (dragColspan > 2) {
+ $dragZone.attr('colspan', dragColspan - 2)
+ .parent().next().children().attr('colspan', dragColspan - 2)
+ .end().next().children().slice(1, 3).remove();
+ var $dragSibs = $dragZone.parent().siblings('.nodes').children().find('.node:first');
+ if ($dragSibs.length ===1) {
+ $dragSibs.find('.horizontalEdge').remove();
+ }
+ } else {
+ $dragZone.removeAttr('colspan')
+ .find('.bottomEdge').remove()
+ .end().end().siblings().remove();
+ }
+ },
+ //
+ touchstartHandler: function (event) {
+ console.log("orgChart: touchstart 1: touchHandled=" + this.touchHandled + ", touchMoved=" + this.touchMoved + ", target=" + event.target.innerText);
+ if (this.touchHandled)
+ return;
+ this.touchHandled = true;
+ this.touchMoved = false; // this is so we can work out later if this was a 'press' or a 'drag' touch
+ event.preventDefault();
+ },
+ //
+ touchmoveHandler: function (event) {
+ if (!this.touchHandled)
+ return;
+ event.preventDefault();
+ if (!this.touchMoved) {
+ var nodeIsSelected = $(this).hasClass('focused');
+ console.log("orgChart: touchmove 1: " + event.touches.length + " touches, we have not moved, so simulate a drag start", event.touches);
+ // TODO: visualise the start of the drag (as would happen on desktop)
+ this.simulateMouseEvent(event, 'dragstart');
+ }
+ this.touchMoved = true;
+ var $touching = $(document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY));
+ var $touchingNode = $touching.closest('div.node');
+
+ if ($touchingNode.length > 0) {
+ var touchingNodeElement = $touchingNode[0];
+ // TODO: simulate the dragover visualisation
+ if ($touchingNode.is('.allowedDrop')) {
+ console.log("orgChart: touchmove 2: this node (" + touchingNodeElement.id + ") is allowed to be a drop target");
+ this.touchTargetNode = touchingNodeElement;
+ } else {
+ console.log("orgChart: touchmove 3: this node (" + touchingNodeElement.id + ") is NOT allowed to be a drop target");
+ this.touchTargetNode = null;
+ }
+ } else {
+ console.log("orgchart: touchmove 4: not touching a node");
+ this.touchTargetNode = null;
+ }
+ },
+ //
+ touchendHandler: function (event) {
+ console.log("orgChart: touchend 1: touchHandled=" + this.touchHandled + ", touchMoved=" + this.touchMoved + ", " + event.target.innerText + " ");
+ if (!this.touchHandled) {
+ console.log("orgChart: touchend 2: not handled by us, so aborting");
+ return;
+ }
+ if (this.touchMoved) {
+ // we've had movement, so this was a 'drag' touch
+ if (this.touchTargetNode) {
+ console.log("orgChart: touchend 3: moved to a node, so simulating drop");
+ var fakeEventForDropHandler = { delegateTarget: this.touchTargetNode };
+ this.dropHandler(fakeEventForDropHandler);
+ this.touchTargetNode = null;
+ }
+ console.log("orgChart: touchend 4: simulating dragend");
+ this.simulateMouseEvent(event, 'dragend');
+ }
+ else {
+ // we did not move, so assume this was a 'press' touch
+ console.log("orgChart: touchend 5: moved, so simulating click");
+ this.simulateMouseEvent(event, 'click');
+ }
+ this.touchHandled = false;
+ },
+ // simulate a mouse event (so we can fake them on a touch device)
+ simulateMouseEvent: function (event, simulatedType) {
+ // Ignore multi-touch events
+ if (event.originalEvent.touches.length > 1) {
+ return;
+ }
+ var touch = event.originalEvent.changedTouches[0];
+ var simulatedEvent = document.createEvent('MouseEvents');
+ simulatedEvent.initMouseEvent(
+ simulatedType, // type
+ true, // bubbles
+ true, // cancelable
+ window, // view
+ 1, // detail
+ touch.screenX, // screenX
+ touch.screenY, // screenY
+ touch.clientX, // clientX
+ touch.clientY, // clientY
+ false, // ctrlKey
+ false, // altKey
+ false, // shiftKey
+ false, // metaKey
+ 0, // button
+ null // relatedTarget
+ );
+ // Dispatch the simulated event to the target element
+ event.target.dispatchEvent(simulatedEvent);
+ },
+ //
+ bindDragDrop: function ($node) {
+ $node.on('dragstart', this.dragstartHandler.bind(this))
+ .on('dragover', this.dragoverHandler.bind(this))
+ .on('dragend', this.dragendHandler.bind(this))
+ .on('drop', this.dropHandler.bind(this))
+ .on('touchstart', this.touchstartHandler.bind(this))
+ .on('touchmove', this.touchmoveHandler.bind(this))
+ .on('touchend', this.touchendHandler.bind(this));
+ },
+ // create node
+ createNode: function (data) {
+ var that = this;
+ var opts = this.options;
+ var level = data.level;
+ if (data.children) {
+ $.each(data.children, function (index, child) {
+ child.parentId = data.id;
+ });
+ }
+ // construct the content of node
+ var $nodeDiv = $('<div' + (opts.draggable ? ' draggable="true"' : '') + (data[opts.nodeId] ? ' id="' + data[opts.nodeId] + '"' : '') + (data.parentId ? ' data-parent="' + data.parentId + '"' : '') + '>')
+ .addClass('node ' + (data.className || '') + (level > opts.visibleLevel ? ' slide-up' : ''));
+ if (opts.nodeTemplate) {
+ $nodeDiv.append(opts.nodeTemplate(data));
+ } else {
+ $nodeDiv.append('<div class="title">' + data[opts.nodeTitle] + '</div>')
+ .append(typeof opts.nodeContent !== 'undefined' ? '<div class="content">' + (data[opts.nodeContent] || '') + '</div>' : '');
+ }
+ //
+ var nodeData = $.extend({}, data);
+ delete nodeData.children;
+ $nodeDiv.data('nodeData', nodeData);
+ // append 4 direction arrows or expand/collapse buttons
+ var flags = data.relationship || '';
+ if (opts.verticalLevel && level >= opts.verticalLevel) {
+ if ((level + 1) > opts.verticalLevel && Number(flags.substr(2,1))) {
+ var icon = level + 1 > opts.visibleLevel ? 'plus' : 'minus';
+ $nodeDiv.append('<i class="toggleBtn fa fa-' + icon + '-square"></i>');
+ }
+ } else {
+ if (Number(flags.substr(0,1))) {
+ $nodeDiv.append('<i class="edge verticalEdge topEdge fa"></i>');
+ }
+ if(Number(flags.substr(1,1))) {
+ $nodeDiv.append('<i class="edge horizontalEdge rightEdge fa"></i>' +
+ '<i class="edge horizontalEdge leftEdge fa"></i>');
+ }
+ if(Number(flags.substr(2,1))) {
+ $nodeDiv.append('<i class="edge verticalEdge bottomEdge fa"></i>')
+ .children('.title').prepend('<i class="fa '+ opts.parentNodeSymbol + ' symbol"></i>');
+ }
+ }
+
+ if (opts.draggable) {
+ this.bindDragDrop($nodeDiv);
+ this.touchHandled = false;
+ this.touchMoved = false;
+ this.touchTargetNode = null;
+ }
+ // allow user to append dom modification after finishing node create of orgchart
+ if (opts.createNode) {
+ opts.createNode($nodeDiv, data);
+ }
+
+ return $nodeDiv;
+ },
+ // recursively build the tree
+ buildHierarchy: function ($appendTo, data) {
+ var that = this;
+ var opts = this.options;
+ var level = 0;
+ if (data.level) {
+ level = data.level;
+ } else {
+ level = data.level = $appendTo.parentsUntil('.orgchart', '.nodes').length + 1;
+ }
+ // Construct the node
+ var childrenData = data.children;
+ var hasChildren = childrenData ? childrenData.length : false;
+ var $nodeWrapper;
+ if (Object.keys(data).length > 2) {
+ var $nodeDiv = this.createNode(data);
+ if (opts.verticalLevel && level >= opts.verticalLevel) {
+ $appendTo.append($nodeDiv);
+ }else {
+ $nodeWrapper = $('<table>');
+ $appendTo.append($nodeWrapper.append($('<tr/>').append($('<td' + (hasChildren ? ' colspan="' + childrenData.length * 2 + '"' : '') + '></td>').append($nodeDiv))));
+ }
+ }
+ // Construct the lower level(two "connectiong lines" rows and "inferior nodes" row)
+ if (hasChildren) {
+ var isHidden = (level + 1 > opts.visibleLevel || data.collapsed) ? ' hidden' : '';
+ var isVerticalLayer = (opts.verticalLevel && (level + 1) >= opts.verticalLevel) ? true : false;
+ var $nodesLayer;
+ if (isVerticalLayer) {
+ $nodesLayer = $('<ul>');
+ if (isHidden && level + 1 > opts.verticalLevel) {
+ $nodesLayer.addClass(isHidden);
+ }
+ if (level + 1 === opts.verticalLevel) {
+ $appendTo.children('table').append('<tr class="verticalNodes' + isHidden + '"><td></td></tr>')
+ .find('.verticalNodes').children().append($nodesLayer);
+ } else {
+ $appendTo.append($nodesLayer);
+ }
+ } else {
+ var $upperLines = $('<tr class="lines' + isHidden + '"><td colspan="' + childrenData.length * 2 + '"><div class="lineDown"></div></td></tr>');
+ var lowerLines = '<tr class="lines' + isHidden + '"><td class="lineRight"></td>';
+ for (var i=1; i<childrenData.length; i++) {
+ lowerLines += '<td class="lineLeft lineTop"></td><td class="lineRight lineTop"></td>';
+ }
+ lowerLines += '<td class="lineLeft"></td></tr>';
+ $nodesLayer = $('<tr class="nodes' + isHidden + '">');
+ if (Object.keys(data).length === 2) {
+ $appendTo.append($upperLines).append(lowerLines).append($nodesLayer);
+ } else {
+ $nodeWrapper.append($upperLines).append(lowerLines).append($nodesLayer);
+ }
+ }
+ // recurse through children nodes
+ $.each(childrenData, function () {
+ var $nodeCell = isVerticalLayer ? $('<li>') : $('<td colspan="2">');
+ $nodesLayer.append($nodeCell);
+ this.level = level + 1;
+ that.buildHierarchy($nodeCell, this);
+ });
+ }
+ },
+ // build the child nodes of specific node
+ buildChildNode: function ($appendTo, data) {
+ $appendTo.find('td:first').attr('colspan', data.length * 2);
+ this.buildHierarchy($appendTo, { 'children': data });
+ },
+ // exposed method
+ addChildren: function ($node, data) {
+ this.buildChildNode($node.closest('table'), data);
+ if (!$node.children('.bottomEdge').length) {
+ $node.append('<i class="edge verticalEdge bottomEdge fa"></i>');
+ }
+ if (!$node.find('.symbol').length) {
+ $node.children('.title').prepend('<i class="fa '+ this.options.parentNodeSymbol + ' symbol"></i>');
+ }
+ if (this.isInAction($node)) {
+ this.switchVerticalArrow($node.children('.bottomEdge'));
+ }
+ },
+ // build the parent node of specific node
+ buildParentNode: function ($currentRoot, data) {
+ data.relationship = data.relationship || '001';
+ var $table = $('<table>')
+ .append($('<tr>').append($('<td colspan="2">').append(this.createNode(data))))
+ .append('<tr class="lines"><td colspan="2"><div class="lineDown"></div></td></tr>')
+ .append('<tr class="lines"><td class="lineRight"></td><td class="lineLeft"></td></tr>');
+ this.$chart.prepend($table)
+ .children('table:first').append('<tr class="nodes"><td colspan="2"></td></tr>')
+ .children('tr:last').children().append(this.$chart.children('table').last());
+ },
+ // exposed method
+ addParent: function ($currentRoot, data) {
+ this.buildParentNode($currentRoot, data);
+ if (!$currentRoot.children('.topEdge').length) {
+ $currentRoot.children('.title').after('<i class="edge verticalEdge topEdge fa"></i>');
+ }
+ if (this.isInAction($currentRoot)) {
+ this.switchVerticalArrow($currentRoot.children('.topEdge'));
+ }
+ },
+ // subsequent processing of build sibling nodes
+ complementLine: function ($oneSibling, siblingCount, existingSibligCount) {
+ var lines = '';
+ for (var i = 0; i < existingSibligCount; i++) {
+ lines += '<td class="lineLeft lineTop"></td><td class="lineRight lineTop"></td>';
+ }
+ $oneSibling.parent().prevAll('tr:gt(0)').children().attr('colspan', siblingCount * 2)
+ .end().next().children(':first').after(lines);
+ },
+ // build the sibling nodes of specific node
+ buildSiblingNode: function ($nodeChart, data) {
+ var newSiblingCount = $.isArray(data) ? data.length : data.children.length;
+ var existingSibligCount = $nodeChart.parent().is('td') ? $nodeChart.closest('tr').children().length : 1;
+ var siblingCount = existingSibligCount + newSiblingCount;
+ var insertPostion = (siblingCount > 1) ? Math.floor(siblingCount/2 - 1) : 0;
+ // just build the sibling nodes for the specific node
+ if ($nodeChart.parent().is('td')) {
+ var $parent = $nodeChart.closest('tr').prevAll('tr:last');
+ $nodeChart.closest('tr').prevAll('tr:lt(2)').remove();
+ this.buildChildNode($nodeChart.parent().closest('table'), data);
+ var $siblingTds = $nodeChart.parent().closest('table').children('tr:last').children('td');
+ if (existingSibligCount > 1) {
+ this.complementLine($siblingTds.eq(0).before($nodeChart.closest('td').siblings().addBack().unwrap()), siblingCount, existingSibligCount);
+ } else {
+ this.complementLine($siblingTds.eq(insertPostion).after($nodeChart.closest('td').unwrap()), siblingCount, 1);
+ }
+ } else { // build the sibling nodes and parent node for the specific ndoe
+ this.buildHierarchy($nodeChart.closest('.orgchart'), data);
+ this.complementLine($nodeChart.next().children('tr:last').children().eq(insertPostion).after($('<td colspan="2">').append($nodeChart)),
+ siblingCount, 1);
+ }
+ },
+ //
+ addSiblings: function ($node, data) {
+ this.buildSiblingNode($node.closest('table'), data);
+ $node.closest('.nodes').data('siblingsLoaded', true);
+ if (!$node.children('.leftEdge').length) {
+ $node.children('.topEdge').after('<i class="edge horizontalEdge rightEdge fa"></i><i class="edge horizontalEdge leftEdge fa"></i>');
+ }
+ if (this.isInAction($node)) {
+ this.switchHorizontalArrow($node);
+ $node.children('.topEdge').removeClass('fa-chevron-up').addClass('fa-chevron-down');
+ }
+ },
+ //
+ removeNodes: function ($node) {
+ var $parent = $node.closest('table').parent();
+ var $sibs = $parent.parent().siblings();
+ if ($parent.is('td')) {
+ if (this.getNodeState($node, 'siblings').exist) {
+ $sibs.eq(2).children('.lineTop:lt(2)').remove();
+ $sibs.slice(0, 2).children().attr('colspan', $sibs.eq(2).children().length);
+ $parent.remove();
+ } else {
+ $sibs.eq(0).children().removeAttr('colspan')
+ .find('.bottomEdge').remove()
+ .end().end().siblings().remove();
+ }
+ } else {
+ $parent.add($parent.siblings()).remove();
+ }
+ },
+ //
+ export: function (exportFilename, exportFileextension) {
+ var that = this;
+ exportFilename = (typeof exportFilename !== 'undefined') ? exportFilename : this.options.exportFilename;
+ exportFileextension = (typeof exportFileextension !== 'undefined') ? exportFileextension : this.options.exportFileextension;
+ if ($(this).children('.spinner').length) {
+ return false;
+ }
+ var $chartContainer = this.$chartContainer;
+ var $mask = $chartContainer.find('.mask');
+ if (!$mask.length) {
+ $chartContainer.append('<div class="mask"><i class="fa fa-circle-o-notch fa-spin spinner"></i></div>');
+ } else {
+ $mask.removeClass('hidden');
+ }
+ var sourceChart = $chartContainer.addClass('canvasContainer').find('.orgchart:not(".hidden")').get(0);
+ var flag = that.options.direction === 'l2r' || that.options.direction === 'r2l';
+ html2canvas(sourceChart, {
+ 'width': flag ? sourceChart.clientHeight : sourceChart.clientWidth,
+ 'height': flag ? sourceChart.clientWidth : sourceChart.clientHeight,
+ 'onclone': function (cloneDoc) {
+ $(cloneDoc).find('.canvasContainer').css('overflow', 'visible')
+ .find('.orgchart:not(".hidden"):first').css('transform', '');
+ },
+ 'onrendered': function (canvas) {
+ $chartContainer.find('.mask').addClass('hidden');
+ if (exportFileextension.toLowerCase() === 'pdf') {
+ var doc = {};
+ var docWidth = Math.floor(canvas.width * 0.2646);
+ var docHeight = Math.floor(canvas.height * 0.2646);
+ if (docWidth > docHeight) {
+ doc = new jsPDF('l', 'mm', [docWidth, docHeight]);
+ } else {
+ doc = new jsPDF('p', 'mm', [docHeight, docWidth]);
+ }
+ doc.addImage(canvas.toDataURL(), 'png', 0, 0);
+ doc.save(exportFilename + '.pdf');
+ } else {
+ var isWebkit = 'WebkitAppearance' in document.documentElement.style;
+ var isFf = !!window.sidebar;
+ var isEdge = navigator.appName === 'Microsoft Internet Explorer' || (navigator.appName === "Netscape" && navigator.appVersion.indexOf('Edge') > -1);
+
+ if ((!isWebkit && !isFf) || isEdge) {
+ window.navigator.msSaveBlob(canvas.msToBlob(), exportFilename + '.png');
+ } else {
+ var selector = '.oc-download-btn' + (that.options.chartClass !== '' ? '.' + that.options.chartClass : '');
+ if (!$chartContainer.find(selector).length) {
+ $chartContainer.append('<a class="oc-download-btn' + (that.options.chartClass !== '' ? ' ' + that.options.chartClass : '') + '"'
+ + ' download="' + exportFilename + '.png"></a>');
+ }
+ $chartContainer.find(selector).attr('href', canvas.toDataURL())[0].click();
+ }
+ }
+ }
+ })
+ .then(function () {
+ $chartContainer.removeClass('canvasContainer');
+ }, function () {
+ $chartContainer.removeClass('canvasContainer');
+ });
+ }
+ };
+
+ $.fn.orgchart = function (opts) {
+ return new OrgChart(this, opts).init();
+ };
+
+}));
diff --git a/hr_organizational_chart/static/src/css/hr_orgchart.css b/hr_organizational_chart/static/src/css/hr_orgchart.css
new file mode 100644
index 0000000..58815b8
--- /dev/null
+++ b/hr_organizational_chart/static/src/css/hr_orgchart.css
@@ -0,0 +1,474 @@
+/*
+ * jQuery OrgChart Plugin
+ * https://github.com/dabeng/OrgChart
+ *
+ * Copyright 2016, dabeng
+ * https://github.com/dabeng
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+.orgchart {
+ box-sizing: border-box;
+ display: inline-block;
+ min-height: 202px;
+ min-width: 202px;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ background-size: 10px 10px;
+ border: 1px dashed rgba(0,0,0,0);
+ padding: 20px;
+}
+
+.orgchart .hidden, .orgchart~.hidden {
+ display: none;
+}
+
+.orgchart.b2t {
+ transform: rotate(180deg);
+}
+
+.orgchart.l2r {
+ position: absolute;
+ transform: rotate(-90deg) rotateY(180deg);
+ transform-origin: left top;
+}
+
+.orgchart .verticalNodes ul {
+ list-style: none;
+ margin: 0;
+ padding-left: 18px;
+ text-align: left;
+}
+.orgchart .verticalNodes ul:first-child {
+ margin-top: 2px;
+}
+.orgchart .verticalNodes>td::before {
+ content: '';
+ border: 1px solid rgba(217, 83, 79, 0.8);
+}
+.orgchart .verticalNodes>td>ul>li:first-child::before {
+ box-sizing: border-box;
+ top: -4px;
+ height: 30px;
+ width: calc(50% - 2px);
+ border-width: 2px 0 0 2px;
+}
+.orgchart .verticalNodes ul>li {
+ position: relative;
+}
+.orgchart .verticalNodes ul>li::before,
+.orgchart .verticalNodes ul>li::after {
+ box-sizing: border-box;
+ content: '';
+ position: absolute;
+ left: -6px;
+ border-color: rgba(217, 83, 79, 0.8);
+ border-style: solid;
+ border-width: 0 0 2px 2px;
+}
+.orgchart .verticalNodes ul>li::before {
+ top: -4px;
+ height: 30px;
+ width: 11px;
+}
+.orgchart .verticalNodes ul>li::after {
+ top: 1px;
+ height: 100%;
+}
+.orgchart .verticalNodes ul>li:first-child::after {
+ box-sizing: border-box;
+ top: 24px;
+ width: 11px;
+ border-width: 2px 0 0 2px;
+}
+.orgchart .verticalNodes ul>li:last-child::after {
+ box-sizing: border-box;
+ border-width: 2px 0 0;
+}
+
+.orgchart.r2l {
+ position: absolute;
+ transform: rotate(90deg);
+ transform-origin: left top;
+}
+
+.orgchart>.spinner {
+ font-size: 100px;
+ margin-top: 30px;
+ color: rgba(68, 157, 68, 0.8);
+}
+
+.orgchart table {
+ border-spacing: 0;
+ border-collapse: separate;
+}
+
+.orgchart>table:first-child{
+ margin: 20px auto;
+}
+
+.orgchart td {
+ text-align: center;
+ vertical-align: top;
+ padding: 0;
+}
+
+.orgchart .lines:nth-child(3) td {
+ box-sizing: border-box;
+ height: 20px;
+}
+
+.orgchart .lines .lineTop {
+ border-top: 2px solid #acacac;
+}
+
+.orgchart .lines .lineRight {
+ border-right: 1px solid #acacac;
+ float: none;
+ border-radius: 0;
+}
+
+.orgchart .lines .lineLeft {
+ border-left: 1px solid #acacac;
+ float: none;
+ border-radius: 0;
+}
+
+.orgchart .lines .lineDown {
+ background-color: #acacac;
+ margin: 0 auto;
+ height: 20px;
+ width: 2px;
+ float: none;
+}
+
+/* node styling */
+.orgchart .node {
+ box-sizing: border-box;
+ display: inline-block;
+ position: relative;
+ margin: 0;
+ padding: 3px;
+ border: 2px dashed transparent;
+ text-align: center;
+ width: 160px;
+}
+
+.orgchart.l2r .node, .orgchart.r2l .node {
+ width: 50px;
+ height: 130px;
+}
+
+.orgchart .node>.spinner {
+ position: absolute;
+ top: calc(50% - 15px);
+ left: calc(50% - 15px);
+ vertical-align: middle;
+ font-size: 30px;
+ color: rgba(68, 157, 68, 0.8);
+}
+
+.orgchart .node:hover {
+ transition: .5s;
+ cursor: default;
+ z-index: 20;
+}
+
+.orgchart .node.focused {
+ background-color: rgba(238, 217, 54, 0.5);
+}
+
+.orgchart .ghost-node {
+ position: fixed;
+ left: -10000px;
+ top: -10000px;
+}
+
+.orgchart .ghost-node rect {
+ fill: #ffffff;
+ stroke: #bf0000;
+}
+
+.orgchart .node.allowedDrop {
+ border-color: rgba(68, 157, 68, 0.9);
+}
+
+.orgchart .node .title {
+ text-align: center;
+ font-size: 10px;
+ font-weight: bold;
+ height: 20px;
+ line-height: 20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ background-color: #e3e3e3;
+ color: #fff;
+ border-radius:0;
+}
+
+.orgchart.b2t .node .title {
+ transform: rotate(-180deg);
+ transform-origin: center bottom;
+}
+
+.orgchart.l2r .node .title {
+ transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg);
+ transform-origin: bottom center;
+ width: 120px;
+}
+
+.orgchart.r2l .node .title {
+ transform: rotate(-90deg) translate(-40px, -40px);
+ transform-origin: bottom center;
+ width: 120px;
+}
+
+.orgchart .node .title .symbol {
+ float: left;
+ margin-top: 4px;
+ margin-left: 2px;
+}
+
+
+.orgchart.b2t .node .content {
+ transform: rotate(180deg);
+ transform-origin: center top;
+}
+
+.orgchart.l2r .node .content {
+ transform: rotate(-90deg) translate(-40px, -40px) rotateY(180deg);
+ transform-origin: top center;
+ width: 120px;
+}
+
+.orgchart.r2l .node .content {
+ transform: rotate(-90deg) translate(-40px, -40px);
+ transform-origin: top center;
+ width: 120px;
+}
+
+.orgchart .node .edge {
+ font-size: 15px;
+ position: absolute;
+ color: rgba(68, 157, 68, 0.5);
+ cursor: default;
+ transition: .2s;
+}
+
+.orgchart.noncollapsable .node .edge {
+ display: none;
+}
+
+.orgchart .edge:hover {
+ color: #449d44;
+ cursor: pointer;
+}
+
+.orgchart .node .verticalEdge {
+ width: calc(100% - 10px);
+ width: -webkit-calc(100% - 10px);
+ width: -moz-calc(100% - 10px);
+ left: 5px;
+}
+
+.orgchart .node .topEdge {
+ top: -4px;
+}
+
+.orgchart .node .bottomEdge {
+ bottom: -4px;
+}
+
+.orgchart .node .horizontalEdge {
+ width: 15px;
+ height: calc(100% - 10px);
+ height: -webkit-calc(100% - 10px);
+ height: -moz-calc(100% - 10px);
+ top: 5px;
+}
+
+.orgchart .node .rightEdge {
+ right: -4px;
+}
+
+.orgchart .node .leftEdge {
+ left: -4px;
+}
+
+.orgchart .node .horizontalEdge::before {
+ position: absolute;
+ top: calc(50% - 7px);
+}
+
+.orgchart .node .rightEdge::before {
+ right: 3px;
+}
+
+.orgchart .node .leftEdge::before {
+ left: 3px;
+}
+
+.orgchart .node .toggleBtn {
+ position: absolute;
+ left: 5px;
+ bottom: -2px;
+ color: rgba(68, 157, 68, 0.6);
+}
+
+.orgchart .node .toggleBtn:hover {
+ color: rgba(68, 157, 68, 0.8);
+}
+
+.oc-export-btn {
+ display: inline-block;
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ padding: 6px 12px;
+ margin-bottom: 0;
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 1.42857143;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ touch-action: manipulation;
+ cursor: pointer;
+ user-select: none;
+ color: #fff;
+ background-color: #5cb85c;
+ border: 1px solid transparent;
+ border-color: #4cae4c;
+ border-radius: 4px;
+}
+
+.oc-export-btn[disabled] {
+ cursor: not-allowed;
+ box-shadow: none;
+ opacity: 0.3;
+}
+
+.oc-export-btn:hover,.oc-export-btn:focus,.oc-export-btn:active {
+ background-color: #449d44;
+ border-color: #347a34;
+}
+
+.orgchart~.mask {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 999;
+ text-align: center;
+ background-color: rgba(0,0,0,0.3);
+}
+
+.orgchart~.mask .spinner {
+ position: absolute;
+ top: calc(50% - 54px);
+ left: calc(50% - 54px);
+ color: rgba(255,255,255,0.8);
+ font-size: 108px;
+}
+
+.orgchart .node {
+ transition: transform 0.3s, opacity 0.3s;
+}
+
+.orgchart .slide-down {
+ opacity: 0;
+ transform: translateY(40px);
+}
+
+.orgchart.l2r .node.slide-down, .orgchart.r2l .node.slide-down {
+ transform: translateY(130px);
+}
+
+.orgchart .slide-up {
+ opacity: 0;
+ transform: translateY(-40px);
+}
+
+.orgchart.l2r .node.slide-up, .orgchart.r2l .node.slide-up {
+ transform: translateY(-130px);
+}
+
+.orgchart .slide-right {
+ opacity: 0;
+ transform: translateX(130px);
+}
+
+.orgchart.l2r .node.slide-right, .orgchart.r2l .node.slide-right {
+ transform: translateX(40px);
+}
+
+.orgchart .slide-left {
+ opacity: 0;
+ transform: translateX(-130px);
+}
+
+.orgchart.l2r .node.slide-left, .orgchart.r2l .node.slide-left {
+ transform: translateX(-40px);
+}
+.orgchart .middle-level .title {
+
+ background-color: #e3e3e3;
+
+}
+.orgchart .middle-level .content {
+
+ border-color: #e3e3e3;
+
+}
+.orgchart .node .content {
+
+ box-sizing: border-box;
+ width: 100%;
+ height: 20px;
+ font-size: 9px;
+ line-height: 18px;
+
+ border-radius: 0;
+ text-align: center;
+ background-color: #e3e3e3;
+ color: #333;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 0 9px 24px;
+
+}
+.orgchart .node .title {
+
+ text-align: center;
+ font-size: 11px;
+ font-weight: bold;
+ height: 16px;
+ line-height: 24px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ background-color: #e3e3e3;
+ color: #353535;
+ border-radius: 0px;
+
+}
+.office > img {
+
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ margin-bottom: 4px;
+
+}
+#chart-container ~ .o_content {
+display: none;
+} \ No newline at end of file
diff --git a/hr_organizational_chart/static/src/css/style.css b/hr_organizational_chart/static/src/css/style.css
new file mode 100644
index 0000000..05d3a35
--- /dev/null
+++ b/hr_organizational_chart/static/src/css/style.css
@@ -0,0 +1,42 @@
+html,body {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ line-height: 1.428571429;
+ color: #333333;
+}
+
+#chart-container {
+ display: inline-block;
+ text-align: center;
+ height: 100vh;
+ width: 100%;
+ overflow: auto;
+
+}
+.o_org_chart_title.mb16.mt0 {
+
+ color: #4661ae;
+ border-block-color: blue;
+ margin-top: 39px !important;
+ font-size: 22px;
+
+}
+
+
+.orgchart td.left, .orgchart td.right, .orgchart td.top { border-color: #aaa; }
+.orgchart td>.down { background-color: #aaa; }
+.orgchart .middle-level .title { background-color: #e3e3e3; }
+.orgchart .middle-level .content { border-color: #e3e3e3; }
+.orgchart .product-dept .title { background-color: #e3e3e3; }
+.orgchart .product-dept .content { border-color: #e3e3e3; }
+.orgchart .rd-dept .title { background-color: #e3e3e3; }
+.orgchart .rd-dept .content { border-color: #e3e3e3; }
+.orgchart .pipeline1 .title { background-color: #e3e3e3; }
+.orgchart .pipeline1 .content { border-color: #e3e3e3; }
+.orgchart .frontend1 .title { background-color: #e3e3e3; }
+.orgchart .frontend1 .content { border-color: #e3e3e3; }
diff --git a/hr_organizational_chart/static/src/img/default_image.png b/hr_organizational_chart/static/src/img/default_image.png
new file mode 100644
index 0000000..6557e68
--- /dev/null
+++ b/hr_organizational_chart/static/src/img/default_image.png
Binary files differ
diff --git a/hr_organizational_chart/static/src/js/organizational_view.js b/hr_organizational_chart/static/src/js/organizational_view.js
new file mode 100644
index 0000000..a0942a3
--- /dev/null
+++ b/hr_organizational_chart/static/src/js/organizational_view.js
@@ -0,0 +1,100 @@
+odoo.define('hr_organizational_chart.view_chart', function (require){
+"use strict";
+var AbstractAction = require('web.AbstractAction');
+var ajax = require('web.ajax');
+var core = require('web.core');
+var rpc = require('web.rpc');
+var ActionManager = require('web.ActionManager');
+var _t = core._t;
+
+
+var EmployeeOrganizationalChart = AbstractAction.extend({
+
+ contentTemplate: 'OrganizationalEmployeeChart',
+ events: {
+ 'click img': '_getChild_data',
+ 'click .employee_name': 'view_employee',
+ },
+
+ init: function(parent, context) {
+ this._super(parent, context);
+ this.renderEmployeeDetails();
+ },
+ renderEmployeeDetails: function (){
+ var employee_id = 1
+ var self = this;
+ this._rpc({
+ route: '/get/parent/employee',
+ }).then(function (result) {
+ self.parent_len = result[1];
+ $.ajax({
+ url: '/get/parent/child',
+ type: 'POST',
+ data: JSON.stringify(result[0]),
+ success: function (value) {
+ $('#o_parent_employee').append(value);
+ },
+ });
+
+ });
+
+ },
+ _getChild_data: function(events){
+ console.log(events)
+ if(events.target.parentElement.className){
+ var self = this
+ this.id = events.target.parentElement.id;
+ this.check_child = $( "#"+this.id+".o_level_1" );
+ if (this.check_child[0]){
+ this.colspan_td = this.check_child[0].parentElement.parentElement
+ this.tbody_child = this.colspan_td.parentElement.parentElement
+ var child_length = this.tbody_child.children.length
+ if (child_length == 1){
+ this._rpc({
+ route: '/get/parent/colspan',
+ params: {
+ emp_id: parseInt(this.id),
+ },
+ }).then(function (col_val){
+ if (col_val){
+ self.colspan_td.colSpan = col_val;
+ }
+ });
+ this._rpc({
+ route: '/get/child/data',
+ params: {
+ click_id: parseInt(this.id),
+ },
+ }).then(function (result){
+ if (result){
+ $(result).appendTo(self.tbody_child);
+ }
+ });
+ }
+ else{
+ for(var i = 0;i < 3; i++){
+ this.tbody_child.children[1].remove();
+ }
+ self.colspan_td.colSpan = 2;
+ }
+
+ }
+ }
+ },
+ view_employee: function(ev){
+ if (ev.target.parentElement.className){
+ var id = parseInt(ev.target.parentElement.parentElement.children[0].id)
+ this.do_action({
+ name: _t("Employee"),
+ type: 'ir.actions.act_window',
+ res_model: 'hr.employee',
+ res_id: id,
+ view_mode: 'form',
+ views: [[false, 'form']],
+ })
+ }
+ },
+});
+ core.action_registry.add('organization_dashboard', EmployeeOrganizationalChart);
+
+});
diff --git a/hr_organizational_chart/static/src/scss/chart_view.scss b/hr_organizational_chart/static/src/scss/chart_view.scss
new file mode 100644
index 0000000..3fd82f2
--- /dev/null
+++ b/hr_organizational_chart/static/src/scss/chart_view.scss
@@ -0,0 +1,73 @@
+.o_chart_head {
+ text-align: center;
+}
+.o_chart_head img {
+ width: 68px;
+ border: 3px solid #777;
+ border-radius: 100%;
+}
+.o_child_container {
+ display: flex;
+ justify-content: center;
+ text-align: center;
+ margin-top: 4rem;
+}
+.o_level_1 img {
+ width: 68px;
+ border: 3px solid #777;
+ border-radius: 100%;
+}
+.o_level_1 {
+ margin: 15px;
+ min-width: 100px;
+}
+
+.empchart table {
+ border-spacing: 0;
+ border-collapse: separate;
+}
+
+.empchart td {
+ text-align: center;
+ padding: 0;
+ vertical-align: top;
+}
+
+.empchart .lines:nth-child(3) td {
+ height: 20px;
+ box-sizing: border-box;
+}
+
+.empchart .lines .leftLine {
+ border-left: 1px solid rgb(89, 87, 87);
+ float: none;
+ border-radius: 0;
+}
+
+.empchart .lines .topLine {
+ border-top: 2px solid rgb(89, 87, 87);
+}
+
+.empchart .lines .downLine {
+ background-color: rgb(89, 87, 87);
+ float: none;
+ margin: 0 auto;
+ width: 2px;
+ height: 20px;
+}
+
+.empchart .lines .rightLine {
+ border-right: 1px solid rgb(89, 87, 87);
+ float: none;
+ border-radius: 0;
+}
+
+.employee_name p:nth-child(1) {
+ font-weight: 600;
+ margin-bottom: -2px;
+ margin-top: 7px;
+}
+#o_organizational_chart .o_org_chart_title.mb16.mt0 {
+ background-color: darkgray;
+ padding: 17px;
+} \ No newline at end of file
diff --git a/hr_organizational_chart/static/src/xml/chart_view.xml b/hr_organizational_chart/static/src/xml/chart_view.xml
new file mode 100644
index 0000000..ebdfbb9
--- /dev/null
+++ b/hr_organizational_chart/static/src/xml/chart_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates id="template" xml:space="preserve">
+
+ <t t-name="OrganizationalEmployeeChart">
+ <div id="o_organizational_chart">
+ <h4 class="o_org_chart_title mb16 mt0" align="center">Organization Chart</h4>
+ <center>
+ <div id="o_parent_employee" class="empchart">
+
+ </div>
+ </center>
+ </div>
+
+
+
+
+ </t>
+
+ </templates>
+
diff --git a/hr_organizational_chart/static/src/xml/hr_org_chart_template.xml b/hr_organizational_chart/static/src/xml/hr_org_chart_template.xml
new file mode 100644
index 0000000..71ad1a0
--- /dev/null
+++ b/hr_organizational_chart/static/src/xml/hr_org_chart_template.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates xml:space="preserve">
+ <t t-name="hr_organizational_chart.org_chart_template">
+ <h4 class="o_org_chart_title mb16 mt0" align="center">Organization Chart</h4>
+ <div id="chart-container"></div>
+ <script type="text/javascript">
+ $(function() {
+ <!-- Get Employee Data -->
+ var datascource = employee_data.values;
+
+ var oc = $('#chart-container').orgchart({
+ 'data' : datascource,
+ 'nodeTemplate': nodeTemplate,
+ 'toggleSiblingsResp': true
+ });
+
+ });
+ </script>
+ </t>
+</templates>