diff --git a/third_party_addons/ks_dashboard_ninja/__manifest__.py b/third_party_addons/ks_dashboard_ninja/__manifest__.py
index f3a72f398..01deb3625 100644
--- a/third_party_addons/ks_dashboard_ninja/__manifest__.py
+++ b/third_party_addons/ks_dashboard_ninja/__manifest__.py
@@ -116,6 +116,7 @@ Dashboard Ninja v16.0,
'ks_dashboard_ninja/static/src/css/ks_toggle_icon.css',
'ks_dashboard_ninja/static/src/css/ks_flower_view.css',
'ks_dashboard_ninja/static/src/css/ks_map_view.css',
+ 'ks_dashboard_ninja/static/src/css/ks_profile.css',
'ks_dashboard_ninja/static/src/css/ks_funnel_view.css',
'ks_dashboard_ninja/static/src/css/ks_dashboard_options.css',
'/ks_dashboard_ninja/static/lib/js/gridstack-h5.js',
diff --git a/third_party_addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py b/third_party_addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py
index 2612c4aec..73f172a38 100644
--- a/third_party_addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py
+++ b/third_party_addons/ks_dashboard_ninja/models/ks_dashboard_ninja_items.py
@@ -387,7 +387,8 @@ class KsDashboardNinjaItems(models.Model):
('ks_to_do', 'To Do'),
('ks_map_view', 'Map View'),
('ks_funnel_chart', 'Funnel Chart'),
- ('ks_bullet_chart', 'Bullet Chart')
+ ('ks_bullet_chart', 'Bullet Chart'),
+ ('ks_profile', 'Profile Chart'),
], default=lambda self: self._context.get('ks_dashboard_item_type',
'ks_tile'), required=True,
string="Dashboard Item Type",
@@ -639,6 +640,7 @@ class KsDashboardNinjaItems(models.Model):
help="Display the total sum of each legends as it grows with times")
ks_radial_preview = fields.Char(string="Radial Preview", default="Radial Preview")
ks_map_preview = fields.Char(string="Map Preview", default="Map Preview")
+ ks_profile_preview = fields.Char(string="Profile Preview", default="Profile Preview")
ks_partners_map = fields.Char(compute="_compute_map_partners")
ks_country_id = fields.Many2one('res.country', string="Country")
ks_country_code = fields.Char(related="ks_country_id.code", store=True)
@@ -694,6 +696,11 @@ class KsDashboardNinjaItems(models.Model):
ks_three_d = fields.Boolean(string='3D View', default=False)
+ @api.onchange('ks_dashboard_item_type')
+ def onchange_ks_dashboard_item_type(self):
+ for rec in self:
+ if rec.ks_dashboard_item_type == 'ks_profile':
+ rec.ks_model_id = self.env['ir.model'].sudo().search([('model','=','hr.employee')],limit=1)
@api.model
def create_ai_dash(self, data, ks_dash_id, model):
@@ -4533,7 +4540,9 @@ class KsDashboardItemsActions(models.Model):
('ks_radar_view', 'Radar View'),
('ks_flower_view', 'Flower View'),
('ks_funnel_chart', 'Funnel Chart'),
- ('ks_bullet_chart', 'Bullet Chart')],
+ ('ks_bullet_chart', 'Bullet Chart'),
+ ('ks_profile', 'Profile Chart')
+ ],
string="Item Type")
ks_dashboard_item_id = fields.Many2one('ks_dashboard_ninja.item', string="Dashboard Item")
diff --git a/third_party_addons/ks_dashboard_ninja/static/images/profile.svg b/third_party_addons/ks_dashboard_ninja/static/images/profile.svg
new file mode 100644
index 000000000..da51491cc
--- /dev/null
+++ b/third_party_addons/ks_dashboard_ninja/static/images/profile.svg
@@ -0,0 +1,6 @@
+
diff --git a/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_graphs/ks_dashboard_graphs.js b/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_graphs/ks_dashboard_graphs.js
index a2020f02a..c235f80fe 100644
--- a/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_graphs/ks_dashboard_graphs.js
+++ b/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_graphs/ks_dashboard_graphs.js
@@ -401,7 +401,6 @@ export class Ksdashboardgraph extends Component{
// 3D Bar Chart Implementation
create3DBarChart(chart, data, ks_data, item) {
// Create axes
- debugger;
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "category";
categoryAxis.renderer.labels.template.rotation = -45;
@@ -736,7 +735,6 @@ export class Ksdashboardgraph extends Component{
['ks_bar_chart','ks_horizontalBar_chart','ks_pie_chart','ks_doughnut_chart'].includes(item.ks_dashboard_item_type);
if (use3D) {
- debugger;
switch (theme) {
case "dark":
am4core.unuseAllThemes();
diff --git a/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_profile_view/ks_dashboard_profile.js b/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_profile_view/ks_dashboard_profile.js
new file mode 100644
index 000000000..8a86ab172
--- /dev/null
+++ b/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_profile_view/ks_dashboard_profile.js
@@ -0,0 +1,218 @@
+/** @odoo-module **/
+import { Component, useState, useEffect, onWillUpdateProps, useRef, onMounted, onWillUnmount } from "@odoo/owl";
+import { globalfunction } from '@ks_dashboard_ninja/js/ks_global_functions';
+import { loadBundle } from "@web/core/assets";
+import { useService } from "@web/core/utils/hooks";
+import { _t } from "@web/core/l10n/translation";
+import { onAudioEnded } from '@ks_dashboard_ninja/js/ks_global_functions';
+import { rpc } from "@web/core/network/rpc";
+
+export class Ksdashboardprofile extends Component {
+ setup() {
+ debugger;
+ var self = this;
+ this.orm = useService("orm");
+ this.actionService = useService("action");
+ this.ks_profile = useRef('ks_profile');
+ this.ks_container_class = 'grid-stack-item';
+ this.aiAudioRef = useRef("aiAudioRef");
+ this.ks_inner_container_class = 'grid-stack-item-content';
+ this.state = useState({
+ employee: {
+ name: '',
+ image_1920: '',
+ job_id: null,
+ current_company_exp: null,
+ doj: '',
+ employee_id: null,
+ birthday: '',
+ attendance_state: null,
+ mobile_phone: '',
+ work_email: '',
+ private_street: '',
+ department_id: ''
+ }
+ });
+ this.storeService = useService("mail.store");
+ this.item = this.props.item;
+ this.ks_dashboard_data = this.props.dashboard_data;
+ this.ks_ai_analysis = this.ks_dashboard_data.ks_ai_explain_dash;
+
+ if (this.ks_ai_analysis) {
+ this.ks_container_class = 'grid-stack-item ks_ai_explain_tile';
+ this.ks_inner_container_class = 'grid-stack-item-content ks_ai_dashboard_item';
+ } else {
+ this.ks_container_class = 'grid-stack-item';
+ this.ks_inner_container_class = 'encapsulated-profile-tile grid-stack-item-content';
+ }
+
+ if (this.item.ks_ai_analysis && this.item.ks_ai_analysis) {
+ var ks_analysis = this.item.ks_ai_analysis.split('ks_gap');
+ this.ks_ai_analysis_1 = ks_analysis[0];
+ this.ks_ai_analysis_2 = ks_analysis[1];
+ }
+
+ this.prepare_profile();
+ var update_interval = this.props.dashboard_data.ks_set_interval;
+
+ onWillUpdateProps(async (nextprops) => {
+ if (nextprops.ksdatefilter != 'none') {
+ await this.ksFetchUpdateProfile(this.item.id, this.props.dashboard_data.context);
+ }
+ if (Object.keys(nextprops.pre_defined_filter).length) {
+ if (nextprops.pre_defined_filter?.item_ids?.includes(this.item.id)) {
+ await this.ksFetchUpdateProfile(this.item.id, this.props.dashboard_data.context);
+ }
+ }
+ if (Object.keys(nextprops.custom_filter).length) {
+ if (nextprops.custom_filter?.item_ids?.includes(this.item.id)) {
+ await this.ksFetchUpdateProfile(this.item.id, this.props.dashboard_data.context);
+ }
+ }
+ });
+
+ useEffect(() => {
+ if (update_interval && !this.env.inDialog) {
+ const interval = setInterval(() => {
+ this.ksFetchUpdateProfile(this.item.id, this.props.dashboard_data.context);
+ }, update_interval);
+ return () => clearInterval(interval);
+ }
+ });
+
+ onMounted(() => {
+ if (this.ks_ai_analysis) {
+ const dashboardItems = this.ks_profile.el.querySelectorAll('.ks_dashboarditem_id');
+ dashboardItems.forEach(item => {
+ item.classList.add('ks_ai_chart_body');
+ });
+ }
+ this.aiAudioRef.el?.addEventListener('ended', onAudioEnded);
+ });
+
+ onWillUnmount(() => {
+ this.aiAudioRef.el?.removeEventListener('ended', onAudioEnded);
+ });
+ }
+
+ ksFetchUpdateProfile(item_id, domain) {
+ var self = this;
+ if (!domain) {
+ if (this.__owl__.parent.component.hasOwnProperty('ksGetParamsForItemFetch') &&
+ this.__owl__.parent.component?.ksGetParamsForItemFetch(item_id) instanceof Function) {
+ domain = this.__owl__.parent.component?.ksGetParamsForItemFetch(item_id);
+ } else {
+ domain = {};
+ }
+ }
+
+ return rpc("/web/dataset/call_kw/", {
+ model: 'ks_dashboard_ninja.board',
+ method: 'ks_fetch_item',
+ args: [
+ [parseInt(item_id)], self.ks_dashboard_data.ks_dashboard_id, domain
+ ],
+ kwargs: { context: this.props.dashboard_data.context },
+ }).then(function (new_item_data) {
+ this.ks_dashboard_data.ks_item_data[item_id] = new_item_data[item_id];
+ this.item = this.ks_dashboard_data.ks_item_data[item_id];
+ this.__owl__.parent.component.ks_dashboard_data.ks_item_data[this.item.id] = new_item_data[item_id];
+ this.prepare_profile();
+ }.bind(this));
+ }
+
+ ksStopClickPropagation(e) {
+ this.ksAllowItemClick = false;
+ }
+
+ prepare_profile() {
+ var self = this;
+ var ks_rgba_background_color, ks_rgba_font_color, ks_rgba_button_color;
+
+ this.item.ksIsDashboardManager = self.ks_dashboard_data.ks_dashboard_manager;
+ this.item.ksIsUser = true;
+ this.ks_rgba_background_color = self._ks_get_rgba_format(this.item.ks_background_color);
+ this.ks_rgba_font_color = self._ks_get_rgba_format(this.item.ks_font_color);
+ this.ks_rgba_button_color = self._ks_get_rgba_format(this.item.ks_button_color);
+
+ if (this.item.ks_info) {
+ var ks_description = this.item.ks_info.split('\n');
+ var ks_description = ks_description.filter(element => element !== '');
+ } else {
+ var ks_description = false;
+ }
+
+ this.ks_info = ks_description;
+ this.ks_dashboard_list = self.ks_dashboard_data.ks_dashboard_list;
+ this.style_main_body = this._ksMainBodyStyle(this.ks_rgba_background_color, this.ks_rgba_font_color, this.item).background_style;
+
+ // Fetch employee data
+ this.fetchEmployeeData();
+ }
+
+ async fetchEmployeeData() {
+ try {
+ debugger;
+ const employeeData = await this.orm.call("hr.employee", 'get_user_employee_details');
+ debugger;
+ if (employeeData && employeeData.length > 0) {
+ const employee = employeeData[0];
+ this.state.employee = {
+ name: employee.name,
+ image_1920: employee.image_1920,
+ doj: employee.doj,
+ job_id: employee.job_id,
+ employee_id: employee.employee_id,
+ current_company_exp: employee.current_company_exp,
+ attendance_state: employee.attendance_state,
+ birthday: employee.birthday,
+ mobile_phone: employee.mobile_phone,
+ work_email: employee.work_email,
+ private_street: employee.private_street,
+ department_id: employee.department_id ? employee.department_id[1] : ''
+ };
+ }
+ } catch (error) {
+ console.error("Error fetching employee data:", error);
+ }
+ }
+
+ async attendance_sign_in_out() {
+ try {
+ await this.orm.call('hr.employee', 'attendance_manual', [[this.state.employee.id]]);
+ this.state.employee.attendance_state =
+ this.state.employee.attendance_state === 'checked_in' ? 'checked_out' : 'checked_in';
+ } catch (error) {
+ console.error("Error updating attendance:", error);
+ }
+ }
+
+ _ks_get_rgba_format(val) {
+ var rgba = val.split(',')[0].match(/[A-Za-z0-9]{2}/g);
+ rgba = rgba.map(function (v) {
+ return parseInt(v, 16);
+ }).join(",");
+ return "rgba(" + rgba + "," + val.split(',')[1] + ")";
+ }
+
+ _ksMainBodyStyle(ks_rgba_background_color, ks_rgba_font_color, tile) {
+ var background_style = "background-color:" + ks_rgba_background_color + ";color : " + ks_rgba_font_color + ";";
+ return {
+ 'background_style': background_style,
+ };
+ }
+}
+
+Ksdashboardprofile.props = {
+ item: { type: Object, Optional: true },
+ dashboard_data: { type: Object, Optional: true },
+ ksdatefilter: { type: String, Optional: true },
+ pre_defined_filter: { type: Object, Optional: true },
+ custom_filter: { type: Object, Optional: true },
+ ks_speak: { type: Function, Optional: true },
+ hideButtons: { type: Number, optional: true },
+ on_dialog: { type: Boolean, optional: true },
+ generate_dialog: { type: Boolean, optional: true },
+};
+
+Ksdashboardprofile.template = "Ksdashboardprofile";
\ No newline at end of file
diff --git a/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_profile_view/ks_dashboard_profile.xml b/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_profile_view/ks_dashboard_profile.xml
new file mode 100644
index 000000000..34e972601
--- /dev/null
+++ b/third_party_addons/ks_dashboard_ninja/static/src/components/ks_dashboard_profile_view/ks_dashboard_profile.xml
@@ -0,0 +1,330 @@
+
+
+
+
+ Birthday :
+
+
+
+
+
+ Address:
+ Check In Check Out
+
+
+ Birthday :
+
+
+
+
+
+ Address:
+ Check In Check Out
+
+
+
+
+
+