upload web_responsive module

This commit is contained in:
eman 2024-08-19 06:49:32 +03:00
parent 8b9daef505
commit 4635547f54
234 changed files with 46578 additions and 4643 deletions

View File

@ -1,12 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
{ {
'name': 'Dashboard Ninja', 'name': 'Dashboard Ninja With AI',
'summary': """ 'summary': """
Ksolves Dashboard Ninja gives you a wide-angle view of your business that you might have missed. Get smart visual data with interactive and engaging dashboards for your Odoo ERP. Odoo Dashboard, CRM Dashboard, Inventory Dashboard, Sales Dashboard, Account Dashboard, Invoice Dashboard, Revamp Dashboard, Best Dashboard, Odoo Best Dashboard, Odoo Apps Dashboard, Best Ninja Dashboard, Analytic Dashboard, Pre-Configured Dashboard, Create Dashboard, Beautiful Dashboard, Customized Robust Dashboard, Predefined Dashboard, Multiple Dashboards, Advance Dashboard, Beautiful Powerful Dashboards, Chart Graphs Table View, All In One Dynamic Dashboard, Accounting Stock Dashboard, Pie Chart Dashboard, Modern Dashboard, Dashboard Studio, Dashboard Builder, Dashboard Designer, Odoo Studio. Revamp your Odoo Dashboard like never before! It is one of the best dashboard odoo apps in the market. Ksolves Dashboard Ninja gives you a wide-angle view of your business that you might have missed. Get smart visual data with interactive and engaging dashboards for your Odoo ERP. Odoo Dashboard, CRM Dashboard, Inventory Dashboard, Sales Dashboard, Account Dashboard, Invoice Dashboard, Revamp Dashboard, Best Dashboard, Odoo Best Dashboard, Odoo Apps Dashboard, Best Ninja Dashboard, Analytic Dashboard, Pre-Configured Dashboard, Create Dashboard, Beautiful Dashboard, Customized Robust Dashboard, Predefined Dashboard, Multiple Dashboards, Advance Dashboard, Beautiful Powerful Dashboards, Chart Graphs Table View, All In One Dynamic Dashboard, Accounting Stock Dashboard, Pie Chart Dashboard, Modern Dashboard, Dashboard Studio, Dashboard Builder, Dashboard Designer, Odoo Studio. Revamp your Odoo Dashboard like never before! It is one of the best dashboard odoo apps in the market.
""", """,
'description': """ 'description': """
Dashboard Ninja v14.0, Dashboard Ninja v14.0,
Odoo Dashboard, Odoo Dashboard,
Dashboard, Dashboard,
@ -63,35 +63,48 @@ Dashboard Ninja v14.0,
odoo dashboard module odoo dashboard module
""", """,
'author': 'Ksolves India Ltd.', 'author': 'Ksolves India Ltd.',
'license': 'OPL-1', 'license': 'OPL-1',
'currency': 'EUR', 'currency': 'EUR',
'price': '272.25',
'website': 'https://store.ksolves.com/', 'price': '287.19',
'maintainer': 'Ksolves India Ltd.', 'website': 'https://store.ksolves.com/',
'live_test_url': 'https://dn15demo.kappso.com/web/demo_login', 'maintainer': 'Ksolves India Ltd.',
'category': 'Tools', 'live_test_url': 'https://dn15demo.kappso.com/web#cids=1&menu_id=599&ks_dashboard_id=1&action=835',
'version': '14.0.1.7.2', 'category': 'Tools',
'support': 'sales@ksolves.com', 'version': '14.0.2.0.0',
'images': ['static/description/banner.gif'], 'support': 'sales@ksolves.com',
'depends': ['base', 'web', 'base_setup', 'bus'], 'images': ['static/description/Independence_sale.jpg'],
'data': ['security/ir.model.access.csv', 'security/ks_security_groups.xml', 'data/ks_default_data.xml', 'wizard/ks_create_dashboard_wizard_view.xml', 'wizard/ks_duplicate_dashboard_wiz_view.xml', 'views/ks_dashboard_ninja_view.xml', 'views/ks_dashboard_ninja_item_view.xml', 'views/ks_dashboard_ninja_assets.xml', 'views/ks_dashboard_action.xml', 'views/ks_import_dashboard_view.xml'], 'depends': ['base', 'web', 'base_setup', 'bus'],
'qweb': ['static/src/xml/ks_dn_global_filter.xml', 'static/src/xml/ks_dashboard_ninja_templates.xml', 'static/src/xml/ks_dashboard_ninja_item_templates.xml', 'static/src/xml/ks_dashboard_ninja_item_theme.xml', 'static/src/xml/ks_widget_toggle.xml', 'static/src/xml/ks_dashboard_pro.xml', 'static/src/xml/ks_import_list_view_template.xml', 'static/src/xml/ks_quick_edit_view.xml', 'static/src/xml/ks_to_do_template.xml'], 'data': ['security/ir.model.access.csv', 'security/ks_security_groups.xml', 'data/ks_default_data.xml',
'data/dn_data.xml',
'wizard/ks_create_dashboard_wizard_view.xml', 'wizard/ks_duplicate_dashboard_wiz_view.xml',
'views/ks_dashboard_ninja_view.xml', 'views/ks_dashboard_ninja_item_view.xml', 'views/res_settings.xml',
'views/ks_dashboard_ninja_assets.xml',
'views/ks_dashboard_action.xml',
'views/ks_import_dashboard_view.xml', 'views/ks_ai_dashboard.xml', 'views/ks_key_fetch.xml',
'views/ks_whole_ai_dashboard.xml'],
'demo': ['demo/ks_dashboard_ninja_demo.xml'], 'qweb': ['static/src/xml/ks_dn_global_filter.xml', 'static/src/xml/ks_dashboard_ninja_templates.xml',
'static/src/xml/ks_dashboard_ninja_item_templates.xml', 'static/src/xml/ks_ai_dash_button.xml',
'static/src/xml/ks_dashboard_ninja_item_theme.xml',
'static/src/xml/ks_widget_toggle.xml', 'static/src/xml/ks_dashboard_pro.xml',
'static/src/xml/ks_import_list_view_template.xml', 'static/src/xml/ks_quick_edit_view.xml',
'static/src/xml/ks_to_do_template.xml', 'static/src/xml/ks_keyword_selection.xml'],
'uninstall_hook': 'uninstall_hook', 'demo': ['demo/ks_dashboard_ninja_demo.xml'],
'uninstall_hook': 'uninstall_hook',
} }

View File

@ -32,9 +32,75 @@ def ks_get_date(ks_date_filter_selection, self, type):
series = ks_date_filter_selection series = ks_date_filter_selection
if ks_date_filter_selection in ['t_fiscal_year', 'n_fiscal_year', 'ls_fiscal_year']: if ks_date_filter_selection in ['t_fiscal_year', 'n_fiscal_year', 'ls_fiscal_year']:
return eval("ks_date_series_" + series.split("_")[0])(series.split("_")[1], timezone, type,self) function_name = globals()["ks_date_series_" + series.split("_")[0]]
return function_name(series.split("_")[1], timezone, type, self)
else: else:
return eval("ks_date_series_" + series.split("_")[0])(series.split("_")[1], timezone, type, self) function_name = globals()["ks_date_series_" + series.split("_")[0]]
return function_name(series.split("_")[1], timezone, type, self)
def ks_date_series_td(ks_date_selection, timezone, type, self=None):
ks_function_name = globals()["ks_get_date_range_from_td_" + ks_date_selection]
return ks_function_name(timezone, type, self)
def ks_get_date_range_from_td_year(timezone, type,self):
ks_date_data = {}
date = datetime.now(pytz.timezone(timezone))
year = date.year
start_date = datetime(year, 1, 1)
end_date = date
if type == 'date':
ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
else:
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
return ks_date_data
def ks_get_date_range_from_td_month(timezone, type,self):
ks_date_data = {}
date = datetime.now(pytz.timezone(timezone))
year = date.year
month = date.month
start_date = datetime(year, month, 1)
end_date = date
if type == 'date':
ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
else:
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
return ks_date_data
def ks_get_date_range_from_td_week(timezone, type,self):
ks_date_data = {}
lang = self.env['res.lang']._lang_get(self.env.user.lang)
week_start = lang.week_start
start_Date = rrule.weekday(int(week_start) - 1)
start_date = datetime.today() + relativedelta(weekday=start_Date(-1))
end_date = datetime.now(pytz.timezone(timezone))
start_date = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
if type == 'date':
ks_date_data["selected_start_date"] = start_date
end_date = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
ks_date_data["selected_end_date"] = end_date
else:
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
return ks_date_data
def ks_get_date_range_from_td_quarter(timezone, type,self):
ks_date_data = {}
date = datetime.now(pytz.timezone(timezone))
year = date.year
quarter = int((date.month - 1) / 3) + 1
start_date = datetime(year, 3 * quarter - 2, 1)
end_date = date
if type == 'date':
ks_date_data["selected_start_date"] = datetime.strptime(start_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
ks_date_data["selected_end_date"] = datetime.strptime(end_date.strftime("%Y-%m-%d"), '%Y-%m-%d')
else:
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
return ks_date_data
# Last Specific Days Ranges : 7, 30, 90, 365 # Last Specific Days Ranges : 7, 30, 90, 365
@ -65,18 +131,18 @@ def ks_date_series_l(ks_date_selection, timezone, type, self=None):
# Current Date Ranges : Week, Month, Quarter, year # Current Date Ranges : Week, Month, Quarter, year
def ks_date_series_t(ks_date_selection, timezone, type, self=None): def ks_date_series_t(ks_date_selection, timezone, type, self=None):
return eval("ks_get_date_range_from_" + ks_date_selection)("current", timezone, type,self) ks_function_name = globals()["ks_get_date_range_from_" + ks_date_selection]
return ks_function_name("current", timezone, type, self)
# Previous Date Ranges : Week, Month, Quarter, year # Previous Date Ranges : Week, Month, Quarter, year
def ks_date_series_ls(ks_date_selection, timezone, type,self=None): def ks_date_series_ls(ks_date_selection, timezone, type,self=None):
return eval("ks_get_date_range_from_" + ks_date_selection)("previous", timezone, type,self) ks_function_name = globals()["ks_get_date_range_from_" + ks_date_selection]
return ks_function_name("previous", timezone, type, self)
# Next Date Ranges : Day, Week, Month, Quarter, year # Next Date Ranges : Day, Week, Month, Quarter, year
def ks_date_series_n(ks_date_selection, timezone, type,self=None): def ks_date_series_n(ks_date_selection, timezone, type,self=None):
return eval("ks_get_date_range_from_" + ks_date_selection)("next", timezone, type, self) ks_function_name = globals()["ks_get_date_range_from_" + ks_date_selection]
return ks_function_name("next", timezone, type, self)
def ks_get_date_range_from_day(date_state, timezone, type,self): def ks_get_date_range_from_day(date_state, timezone, type,self):
ks_date_data = {} ks_date_data = {}
@ -234,6 +300,17 @@ def ks_get_date_range_from_pastwithout(date_state, self_tz, type,self):
else: else:
ks_date_data["selected_end_date"] = ks_convert_into_utc(date, self_tz) ks_date_data["selected_end_date"] = ks_convert_into_utc(date, self_tz)
return ks_date_data return ks_date_data
def ks_get_date_range_from_pastuntil(date_state, self_tz, type, self):
ks_date_data = {}
date = datetime.now(pytz.timezone(self_tz))
date = date - timedelta(days=30)
if type == 'date':
ks_date_data["selected_end_date"] = datetime.strptime(date.strftime("%Y-%m-%d"), '%Y-%m-%d')
else:
ks_date_data["selected_end_date"] = ks_convert_into_utc(date, self_tz)
ks_date_data["selected_start_date"] = False
return ks_date_data
def ks_get_date_range_from_future(date_state, self_tz, type,self): def ks_get_date_range_from_future(date_state, self_tz, type,self):

View File

@ -1,4 +1,4 @@
from . import ks_chart_export from . import ks_chart_export
from . import ks_list_export from . import ks_list_export
from . import ks_dashboard_export
from . import ks_dashboard_export from . import ks_login

View File

@ -27,8 +27,8 @@ class KsListExport(ExportFormat, http.Controller):
'context', 'params')( 'context', 'params')(
params) params)
list_data = json.loads(list_data) list_data = json.loads(list_data)
item = request.env['ks_dashboard_ninja.item'].browse(int(item_id))
if ks_export_boolean: if ks_export_boolean:
item = request.env['ks_dashboard_ninja.item'].browse(int(item_id))
ks_timezone = item._context.get('tz') or item.env.user.tz ks_timezone = item._context.get('tz') or item.env.user.tz
if not ks_timezone: if not ks_timezone:
ks_tzone = os.environ.get('TZ') ks_tzone = os.environ.get('TZ')

View File

@ -0,0 +1,37 @@
from odoo.http import Controller, request, route
from odoo.addons.web.controllers.main import Home
from odoo import http, tools
class KsHome(Home):
# this is for handle the color and font at login time
@http.route('/web/login', type='http', auth="none")
def web_login(self, redirect=None, **kw):
res = super(KsHome, self).web_login(redirect, **kw)
ksis_enterprise = request.env['res.company'].sudo().ks_check_is_enterprise()
if ksis_enterprise:
template = request.env.ref("ks_dashboard_ninja.ks_dn_load_assets")
template.sudo().write({
'active': False
})
active_template = request.env.ref("ks_dashboard_ninja.ks_dn_load_assets_en")
active_template.sudo().write({
'active': True
})
else:
template = request.env.ref("ks_dashboard_ninja.ks_dn_load_assets_en")
template.sudo().write({
'active': False
})
active_template = request.env.ref("ks_dashboard_ninja.ks_dn_load_assets")
active_template.sudo().write({
'active': True
})
return res

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data noupdate="1">
<record id="config_dn_url" model="ir.config_parameter">
<field name="key">ks_dashboard_ninja.url</field>
<field name="value">https://dn16ai.kappso.in</field>
</record>
</data>
</odoo>

View File

@ -4,9 +4,12 @@ from . import ks_item_action
from . import ks_child_dashboard from . import ks_child_dashboard
from . import ks_dashboard_filters from . import ks_dashboard_filters
from . import ks_dashboard_templates from . import ks_dashboard_templates
from . import ks_odoo_base
from . import ks_dn_to_do_item from . import ks_dn_to_do_item
from . import ks_gridstack_per_company from . import ks_gridstack_per_company
from . import res_settings
from . import ks_ai_ninja_dashboard
from . import ks_ai_whole_dashboard
from . import ks_key_fetch
from . import ks_import_dashboard from . import ks_import_dashboard
from . import ks_load_menu from . import ks_load_menu

View File

@ -0,0 +1,216 @@
import json
import logging
import requests
from odoo import http, api, fields, models, _
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
class KsDashboardNInjaAI(models.TransientModel):
_name = 'ks_dashboard_ninja.arti_int'
_description = 'AI Dashboard'
ks_type = fields.Selection([('ks_model', 'Model'), ('ks_keyword', 'Keywords')],
string="Ks AI Type", default='ks_model')
ks_import_model_id = fields.Many2one('ir.model', string='Model',
domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]",
help="Data source to fetch and read the data for the creation of dashboard items. ")
ks_import_model = fields.Many2one('ir.model', string='Model',
domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]",
help="Data source to fetch and read the data for the creation of dashboard items. ")
ks_input_keywords = fields.Char("Ks Keywords")
ks_model_show = fields.Boolean(default=False, compute='_compute_show_model')
@api.onchange('ks_input_keywords')
def _compute_show_model(self):
if self.ks_input_keywords and self.ks_type == "ks_keyword":
api_key = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.dn_api_key')
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if api_key and url:
json_data = {'name': api_key,
'type': self.ks_type,
'keyword': self.ks_input_keywords
}
url = url + "/api/v1/ks_dn_keyword_gen"
ks_response = requests.post(url, data=json_data)
if json.loads(ks_response.text) == False:
self.ks_model_show = True
else:
self.ks_model_show = False
else:
self.ks_model_show = False
@api.model
def ks_get_keywords(self):
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if url:
url = url + "/api/v1/ks_dn_get_keyword"
ks_response = requests.post(url)
if ks_response.status_code == 200:
return json.loads(ks_response.text)
else:
return []
def ks_do_action(self):
headers = {"Content-Type": "application/json",
"Accept": "application/json",
"Catch-Control": "no-cache",
}
if self.ks_import_model_id:
ks_model_name = self.ks_import_model_id.model
ks_fields = self.env[ks_model_name].fields_get()
ks_filtered_fields = {key: val for key, val in ks_fields.items() if
val['type'] not in ['many2many', 'one2many', 'binary'] and key not in ['id',
'sequence'] and
val['store'] == True}
ks_fields_name = {key: val['type'] for key, val in ks_filtered_fields.items()}
question = ("columns: " + f"{ks_fields_name}")
api_key = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.dn_api_key')
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if api_key and url:
json_data = {'name': api_key,
'question': question,
'url': self.env['ir.config_parameter'].sudo().get_param('web.base.url'),
'db_name': self.env.cr.dbname
}
url = url + "/api/v1/ks_dn_main_api"
ks_ai_response = requests.post(url, data=json_data)
if ks_ai_response.status_code == 200:
ks_ai_response = json.loads(ks_ai_response.text)
# create dummy dash to create items on the dashboard, later deleted it.
ks_create_record = self.env['ks_dashboard_ninja.board'].create({
'name': 'AI dashboard',
'ks_dashboard_menu_name': 'AI menu',
'ks_dashboard_default_template': self.env.ref('ks_dashboard_ninja.ks_blank', False).id,
'ks_dashboard_top_menu_id': self.env['ir.ui.menu'].search([('name', '=', 'My Dashboard')])[
0].id,
})
ks_dash_id = ks_create_record.id
ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id,
ks_model_name)
context = {'ks_dash_id': self._context['ks_dashboard_id'],
'ks_dash_name': self.env['ks_dashboard_ninja.board'].search([
('id', '=', self._context['ks_dashboard_id'])]).name,
'ks_delete_dash_id': ks_dash_id}
# return client action created through js for AI dashboard to render items on dummy dashboard
if (ks_result == "success"):
return {
'type': 'ir.actions.client',
'name': context['ks_dash_name'],
'params': {'ks_dashboard_id': ks_create_record.id},
'tag': 'ks_dashboard_ninja_ai',
'target': 'new',
'context': context
}
else:
self.env['ks_dashboard_ninja.board'].browse(ks_dash_id).unlink()
raise ValidationError(
_("Items didn't render because AI provides invalid response for this model.Please try again"))
else:
raise ValidationError(_("AI Responds with the following status:- %s") % ks_ai_response.text)
else:
raise ValidationError(_("Please enter URL and API Key in General Settings"))
else:
raise ValidationError(_("Please enter the Model"))
def ks_generate_item(self):
if self.ks_input_keywords:
api_key = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.dn_api_key')
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if api_key and url:
json_data = {'name': api_key,
'type': self.ks_type,
'keyword': self.ks_input_keywords
}
url = url + "/api/v1/ks_dn_keyword_gen"
ks_response = requests.post(url, data=json_data)
else:
raise ValidationError(_("Please put API key and URL"))
if json.loads(ks_response.text) != False and ks_response.status_code == 200:
ks_ai_response = json.loads(ks_response.text)
ks_dash_id = self._context['ks_dashboard_id']
ks_model_name = ks_ai_response[0]['model']
ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id,
ks_model_name)
if ks_result == "success":
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
else:
raise ValidationError(_("Items didn't render, please try again!"))
else:
ks_model_name = self.ks_import_model.model
ks_fields = self.env[ks_model_name].fields_get()
ks_filtered_fields = {key: val for key, val in ks_fields.items() if
val['type'] not in ['many2many', 'one2many', 'binary'] and key not in ['id',
'sequence'] and
val['store'] == True}
ks_fields_name = {key: val['type'] for key, val in ks_filtered_fields.items()}
question = ("schema: " + f"{ks_fields_name}")
model = ("model:" + f"{ks_model_name}")
api_key = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.dn_api_key')
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if api_key and url:
json_data = {'name': api_key,
'question': self.ks_input_keywords,
'type': self.ks_type,
'schema': question,
'model': model,
'url': self.env['ir.config_parameter'].sudo().get_param('web.base.url'),
'db_name': self.env.cr.dbname
}
url = url + "/api/v1/ks_dn_main_api"
ks_ai_response = requests.post(url, data=json_data)
if ks_ai_response.status_code == 200:
ks_ai_response = json.loads(ks_ai_response.text)
ks_dash_id = self._context['ks_dashboard_id']
ks_model_name = (ks_ai_response[0]['model']).lower()
if self.env['ir.model'].search([('model', '=', ks_model_name)]).id or self.env[
'ir.model'].search([('name', '=', ks_model_name)]).id:
if self.env['ir.model'].search([('name', '=', ks_model_name)]).id:
ks_model_name = self.env['ir.model'].search([('name', '=', ks_model_name)]).model
else:
ks_model_name = (ks_ai_response[0]['model']).lower()
ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id,
ks_model_name)
if ks_result == "success":
return {
'type': 'ir.actions.client',
'tag': 'reload',
}
else:
raise ValidationError(_("Items didn't render, please try again!"))
else:
raise ValidationError(_("%s model does not exist.Please install") % ks_model_name)
else:
raise ValidationError(
_("AI Responds with the following status:- %s") % ks_ai_response.text)
else:
raise ValidationError(_("Please enter URL and API Key in General Settings"))
else:
raise ValidationError(_("Enter the input keywords to render the item"))

View File

@ -0,0 +1,87 @@
import json
import logging
import requests
from odoo import http, api, fields, models, _
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
class KsAIDashboardninja(models.TransientModel):
_name = 'ks_dashboard_ninja.ai_dashboard'
_description = 'AI Dashboard'
ks_import_model_id = fields.Many2one('ir.model', string='Model',
domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]",
help="Data source to fetch and read the data for the creation of dashboard items. ", required=True)
ks_dash_name = fields.Char(string="Dashboard Name", required=True)
ks_menu_name = fields.Char(string="Menu Name", required=True)
ks_top_menu_id = fields.Many2one('ir.ui.menu',
domain="[('parent_id','=',False)]",
string="Show Under Menu", required=True,
default=lambda self: self.env['ir.ui.menu'].search(
[('name', '=', 'My Dashboard')])[0])
ks_template = fields.Many2one('ks_dashboard_ninja.board_template',
default=lambda self: self.env.ref('ks_dashboard_ninja.ks_blank',
False),
string="Dashboard Template")
def ks_do_action(self):
headers = {"Content-Type": "application/json",
"Accept": "application/json",
"Catch-Control": "no-cache",
}
if self.ks_import_model_id:
ks_model_name = self.ks_import_model_id.model
ks_fields = self.env[ks_model_name].fields_get()
ks_filtered_fields = {key: val for key, val in ks_fields.items() if val['type'] not in ['many2many', 'one2many', 'binary'] and key not in ['id','sequence'] and val['store'] == True}
ks_fields_name = {key:val['type'] for key , val in ks_filtered_fields.items()}
question = ("columns: "+ f"{ks_fields_name}")
api_key = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.dn_api_key')
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if api_key and url:
json_data = {'name': api_key,
'question':question,
'url':self.env['ir.config_parameter'].sudo().get_param('web.base.url'),
'db_name':self.env.cr.dbname
}
url = url+"/api/v1/ks_dn_main_api"
ks_ai_response = requests.post(url, data=json_data)
if ks_ai_response.status_code == 200:
ks_ai_response = json.loads(ks_ai_response.text)
ks_create_record = self.env['ks_dashboard_ninja.board'].create({
'name': self.ks_dash_name,
'ks_dashboard_menu_name': self.ks_menu_name,
'ks_dashboard_default_template': self.ks_template.id,
'ks_dashboard_top_menu_id': self.ks_top_menu_id.id,
})
ks_dash_id = ks_create_record.id
ks_result = self.env['ks_dashboard_ninja.item'].create_ai_dash(ks_ai_response, ks_dash_id,
ks_model_name)
if (ks_result == "success"):
return {
'type': 'ir.actions.client',
'name': "Dashboard Ninja",
'res_model': 'ks_dashboard_ninja.board',
'params': {'ks_dashboard_id': ks_dash_id},
'tag': 'ks_dashboard_ninja',
}
else:
self.env['ks_dashboard_ninja.board'].browse(ks_dash_id).unlink()
raise ValidationError(_("Items didn't render, please try again!"))
else:
raise ValidationError(_("AI Responds with the following status:- %s") % ks_ai_response.text)
else:
raise ValidationError(_("Please enter URL and API Key in General Settings"))
else:
raise ValidationError(_("Please enter the Model"))

View File

@ -11,7 +11,7 @@ class KsDashboardNinjaTemplate(models.Model):
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard") ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard")
ks_model_id = fields.Many2one('ir.model', string='Model', ks_model_id = fields.Many2one('ir.model', string='Model',
domain="[('access_ids','!=',False),('transient','=',False)," domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%')," "('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=ilike','_%ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]", "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]",
help="Data source to fetch and read the data for the creation of dashboard items. ") help="Data source to fetch and read the data for the creation of dashboard items. ")
@ -54,7 +54,7 @@ class KsDashboardNinjaTemplate(models.Model):
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard") ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard")
ks_model_id = fields.Many2one('ir.model', string='Model', ks_model_id = fields.Many2one('ir.model', string='Model',
domain="[('access_ids','!=',False),('transient','=',False)," domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%')," "('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=ilike','_%ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]", "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]",
help="Data source to fetch and read the data for the creation of dashboard items. ") help="Data source to fetch and read the data for the creation of dashboard items. ")

View File

@ -41,6 +41,10 @@ class KsDashboardNinjaBoard(models.Model):
('t_month', 'This Month'), ('t_month', 'This Month'),
('t_quarter', 'This Quarter'), ('t_quarter', 'This Quarter'),
('t_year', 'This Year'), ('t_year', 'This Year'),
('td_week', 'Week to Date'),
('td_month', 'Month to Date'),
('td_quarter', 'Quarter to Date'),
('td_year', 'Year to Date'),
('n_day', 'Next Day'), ('n_day', 'Next Day'),
('n_week', 'Next Week'), ('n_week', 'Next Week'),
('n_month', 'Next Month'), ('n_month', 'Next Month'),
@ -56,6 +60,7 @@ class KsDashboardNinjaBoard(models.Model):
('l_quarter', 'Last 90 days'), ('l_quarter', 'Last 90 days'),
('l_year', 'Last 365 days'), ('l_year', 'Last 365 days'),
('ls_past_until_now', 'Past Till Now'), ('ls_past_until_now', 'Past Till Now'),
('ls_pastuntil_lastmonth', 'Past Till: 30 days ago'),
('ls_pastwithout_now', ' Past Excluding Today'), ('ls_pastwithout_now', ' Past Excluding Today'),
('n_future_starting_now', 'Future Starting Now'), ('n_future_starting_now', 'Future Starting Now'),
('n_futurestarting_tomorrow', 'Future Starting Tomorrow'), ('n_futurestarting_tomorrow', 'Future Starting Tomorrow'),
@ -178,6 +183,8 @@ class KsDashboardNinjaBoard(models.Model):
if 'ks_dashboard_menu_sequence' in vals: if 'ks_dashboard_menu_sequence' in vals:
rec.ks_dashboard_menu_id.sudo().sequence = vals['ks_dashboard_menu_sequence'] rec.ks_dashboard_menu_id.sudo().sequence = vals['ks_dashboard_menu_sequence']
if 'name' in vals:
self.ks_dashboard_client_action_id.name = vals['name']
return record return record
@ -187,6 +194,7 @@ class KsDashboardNinjaBoard(models.Model):
else: else:
for rec in self: for rec in self:
rec.ks_dashboard_client_action_id.sudo().unlink() rec.ks_dashboard_client_action_id.sudo().unlink()
rec.ks_child_dashboard_ids.unlink()
rec.ks_dashboard_menu_id.sudo().unlink() rec.ks_dashboard_menu_id.sudo().unlink()
rec.ks_dashboard_items_ids.unlink() rec.ks_dashboard_items_ids.unlink()
res = super(KsDashboardNinjaBoard, self).unlink() res = super(KsDashboardNinjaBoard, self).unlink()
@ -257,14 +265,14 @@ class KsDashboardNinjaBoard(models.Model):
} }
default_grid_id = ks_dashboard_rec.ks_get_grid_config() default_grid_id = ks_dashboard_rec.ks_get_grid_config()
dashboard_data['ks_gridstack_config'] = default_grid_id.ks_gridstack_config dashboard_data['ks_gridstack_config'] = default_grid_id[0].ks_gridstack_config
dashboard_data['ks_gridstack_config_id'] = default_grid_id.id dashboard_data['ks_gridstack_config_id'] = default_grid_id[0].id
if self.env['ks_dashboard_ninja.child_board'].search( if self.env['ks_dashboard_ninja.child_board'].search(
[['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], ['company_id', '=', self.env.company.id], [['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], ['company_id', '=', self.env.company.id],
['board_type', '!=', 'default']], limit=1): ['board_type', '!=', 'default']], limit=1):
dashboard_data['ks_child_boards'] = { dashboard_data['ks_child_boards'] = {
'ks_default': [ks_dashboard_rec.name, default_grid_id.ks_gridstack_config]} 'ks_default': [ks_dashboard_rec.name, default_grid_id[0].ks_gridstack_config]}
selecred_rec = self.env['ks_dashboard_ninja.child_board'].search( selecred_rec = self.env['ks_dashboard_ninja.child_board'].search(
[['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], ['ks_active', '=', True], [['id', 'in', ks_dashboard_rec.ks_child_dashboard_ids.ids], ['ks_active', '=', True],
['company_id', '=', self.env.company.id], ['board_type', '!=', 'default']], limit=1) ['company_id', '=', self.env.company.id], ['board_type', '!=', 'default']], limit=1)
@ -326,27 +334,31 @@ class KsDashboardNinjaBoard(models.Model):
if rec.ks_actions: if rec.ks_actions:
context = {} context = {}
try: try:
context = eval(rec.ks_actions.context) context = safe_eval(rec.ks_actions.context)
except Exception: except Exception:
context = {} context = {}
action['name'] = rec.ks_actions.name # Managing those views that have the access rights
action['type'] = rec.ks_actions.type ks_actions = rec.ks_actions.sudo()
action['res_model'] = rec.ks_actions.res_model action['name'] = ks_actions.name
action['views'] = rec.ks_actions.views action['type'] = ks_actions.type
action['view_mode'] = rec.ks_actions.view_mode action['res_model'] = ks_actions.res_model
action['search_view_id'] = rec.ks_actions.search_view_id.id action['views'] = ks_actions.views
action['view_mode'] = ks_actions.view_mode
action['search_view_id'] = ks_actions.search_view_id.id
action['context'] = context action['context'] = context
action['target'] = 'current' action['target'] = 'current'
elif rec.ks_is_client_action and rec.ks_client_action: elif rec.ks_is_client_action and rec.ks_client_action:
clint_action = {} clint_action = {}
clint_action['name'] = rec.ks_client_action.name ks_client_action = rec.ks_client_action.sudo()
clint_action['type'] = rec.ks_client_action.type clint_action['name'] = ks_client_action.name
clint_action['res_model'] = rec.ks_client_action.res_model clint_action['type'] = ks_client_action.type
clint_action['xml_id'] = rec.ks_client_action.xml_id clint_action['res_model'] = ks_client_action.res_model
clint_action['tag'] = rec.ks_client_action.tag clint_action['xml_id'] = ks_client_action.xml_id
clint_action['binding_type'] = rec.ks_client_action.binding_type clint_action['tag'] = ks_client_action.tag
clint_action['params'] = rec.ks_client_action.params clint_action['binding_type'] = ks_client_action.binding_type
clint_action['params'] = ks_client_action.params
clint_action['target'] = 'current' clint_action['target'] = 'current'
action = clint_action, action = clint_action,
@ -386,8 +398,12 @@ class KsDashboardNinjaBoard(models.Model):
'ks_dashboard_item_type': rec.ks_dashboard_item_type, 'ks_dashboard_item_type': rec.ks_dashboard_item_type,
'ks_chart_item_color': rec.ks_chart_item_color, 'ks_chart_item_color': rec.ks_chart_item_color,
'ks_chart_groupby_type': rec.ks_chart_groupby_type, 'ks_chart_groupby_type': rec.ks_chart_groupby_type,
'ks_chart_measure_field': rec.ks_chart_measure_field.ids,
'ks_chart_measure_field_2': rec.ks_chart_measure_field_2.ids,
'ks_chart_relation_groupby': rec.ks_chart_relation_groupby.id, 'ks_chart_relation_groupby': rec.ks_chart_relation_groupby.id,
'ks_chart_relation_groupby_name': rec.ks_chart_relation_groupby.name, 'ks_chart_relation_groupby_name': rec.ks_chart_relation_groupby.name,
'ks_chart_relation_sub_groupby': rec.ks_chart_relation_sub_groupby.id,
'ks_chart_relation_sub_groupby_name': rec.ks_chart_relation_sub_groupby.name,
'ks_chart_date_groupby': rec.ks_chart_date_groupby, 'ks_chart_date_groupby': rec.ks_chart_date_groupby,
'ks_record_field': rec.ks_record_field.id if rec.ks_record_field else False, 'ks_record_field': rec.ks_record_field.id if rec.ks_record_field else False,
'ks_chart_data': rec._ks_get_chart_data(item_domain1), 'ks_chart_data': rec._ks_get_chart_data(item_domain1),
@ -406,8 +422,8 @@ class KsDashboardNinjaBoard(models.Model):
'ks_target_view': rec.ks_target_view, 'ks_target_view': rec.ks_target_view,
'ks_date_filter_selection': rec.ks_date_filter_selection, 'ks_date_filter_selection': rec.ks_date_filter_selection,
'ks_show_data_value': rec.ks_show_data_value, 'ks_show_data_value': rec.ks_show_data_value,
'ks_update_items_data': rec.ks_update_items_data,
'ks_show_records': rec.ks_show_records, 'ks_show_records': rec.ks_show_records,
'ks_tile_data':rec._ksGettileData(item_domain1),
# 'action_id': rec.ks_actions.id if rec.ks_actions else False, # 'action_id': rec.ks_actions.id if rec.ks_actions else False,
'sequence': 0, 'sequence': 0,
'max_sequnce': len(rec.ks_action_lines) if rec.ks_action_lines else False, 'max_sequnce': len(rec.ks_action_lines) if rec.ks_action_lines else False,
@ -416,21 +432,30 @@ class KsDashboardNinjaBoard(models.Model):
'ks_data_calculation_type': rec.ks_data_calculation_type, 'ks_data_calculation_type': rec.ks_data_calculation_type,
'ks_export_all_records': rec.ks_export_all_records, 'ks_export_all_records': rec.ks_export_all_records,
'ks_data_formatting': rec.ks_data_format, 'ks_data_formatting': rec.ks_data_format,
'ks_auto_update_type': rec.ks_auto_update_type,
'ks_show_live_pop_up': rec.ks_show_live_pop_up,
'ks_is_client_action': rec.ks_is_client_action, 'ks_is_client_action': rec.ks_is_client_action,
'ks_pagination_limit': rec.ks_pagination_limit, 'ks_pagination_limit': rec.ks_pagination_limit,
'ks_record_data_limit': rec.ks_record_data_limit, 'ks_record_data_limit': rec.ks_record_data_limit,
'ks_chart_cumulative_field': rec.ks_chart_cumulative_field.ids, 'ks_chart_cumulative_field': rec.ks_chart_cumulative_field.ids,
'ks_chart_cumulative': rec.ks_chart_cumulative, 'ks_chart_cumulative': rec.ks_chart_cumulative,
'ks_chart_is_cumulative': rec.ks_chart_is_cumulative,
'ks_button_color': rec.ks_button_color, 'ks_button_color': rec.ks_button_color,
'ks_to_do_data': rec._ksGetToDOData(), 'ks_to_do_data': rec._ksGetToDOData(),
'ks_multiplier_active': rec.ks_multiplier_active, 'ks_multiplier_active': rec.ks_multiplier_active,
'ks_multiplier': rec.ks_multiplier, 'ks_multiplier': rec.ks_multiplier,
'ks_unit': rec.ks_unit,
'ks_unit_selection':rec.ks_unit_selection,
'ks_chart_unit':rec.ks_chart_unit,
'ks_currency_id':rec.ks_currency_id,
'ks_goal_liness': True if rec.ks_goal_lines else False, 'ks_goal_liness': True if rec.ks_goal_lines else False,
'ks_currency_symbol': ks_currency_symbol, 'ks_currency_symbol': ks_currency_symbol,
'ks_currency_position': ks_currency_position, 'ks_currency_position': ks_currency_position,
'ks_precision_digits': ks_precision_digits if ks_precision_digits else 2 'ks_precision_digits': ks_precision_digits if ks_precision_digits else 2,
'ks_data_label_type': rec.ks_data_label_type,
'ks_as_of_now': rec.ks_as_of_now,
'ks_info': rec.ks_info,
'ks_company': rec.ks_company_id.name if rec.ks_company_id else False,
} }
return item return item
@ -587,14 +612,18 @@ class KsDashboardNinjaBoard(models.Model):
[['id', 'in', rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids.ids], ['ks_active', '=', True], [['id', 'in', rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids.ids], ['ks_active', '=', True],
['company_id', '=', self.env.company.id]], limit=1) ['company_id', '=', self.env.company.id]], limit=1)
default_grid_id = rec.ks_dashboard_ninja_board_id.ks_get_grid_config() default_grid_id = rec.ks_dashboard_ninja_board_id.ks_get_grid_config()
keys_data = {}
if rec.ks_dashboard_ninja_board_id.ks_gridstack_config: if rec.ks_dashboard_ninja_board_id.ks_gridstack_config:
keys_data = json.loads(rec.ks_dashboard_ninja_board_id.ks_gridstack_config) keys_data = json.loads(rec.ks_dashboard_ninja_board_id.ks_gridstack_config)
elif selecred_rec: elif selecred_rec:
keys_data = json.loads(selecred_rec.ks_gridstack_config) keys_data = json.loads(selecred_rec.ks_gridstack_config)
elif rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids[0].ks_gridstack_config: elif rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids[0].ks_gridstack_config:
keys_data = json.loads(rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids[0].ks_gridstack_config) keys_data = json.loads(rec.ks_dashboard_ninja_board_id.ks_child_dashboard_ids[0].ks_gridstack_config)
elif self._context.get('gridstack_config',False):
keys_data = self._context.get('gridstack_config',False)
else: else:
keys_data = {rec.id: json.loads(rec.grid_corners.replace("\'", "\""))} if rec.grid_corners:
keys_data = {rec.id: json.loads(rec.grid_corners.replace("\'", "\""))}
keys_list = keys_data.keys() keys_list = keys_data.keys()
grid_corners = {} grid_corners = {}
if val in keys_list: if val in keys_list:
@ -662,9 +691,6 @@ class KsDashboardNinjaBoard(models.Model):
'ks_year_period_2': rec.ks_year_period_2, 'ks_year_period_2': rec.ks_year_period_2,
'ks_domain_2': rec.ks_domain_2, 'ks_domain_2': rec.ks_domain_2,
'ks_show_data_value': rec.ks_show_data_value, 'ks_show_data_value': rec.ks_show_data_value,
'ks_auto_update_type': rec.ks_auto_update_type,
'ks_show_live_pop_up': rec.ks_show_live_pop_up,
'ks_update_items_data': rec.ks_update_items_data,
'ks_list_target_deviation_field': rec.ks_list_target_deviation_field.name, 'ks_list_target_deviation_field': rec.ks_list_target_deviation_field.name,
'ks_unit': rec.ks_unit, 'ks_unit': rec.ks_unit,
'ks_show_records': rec.ks_show_records, 'ks_show_records': rec.ks_show_records,
@ -673,6 +699,7 @@ class KsDashboardNinjaBoard(models.Model):
'ks_domain_extension': rec.ks_domain_extension, 'ks_domain_extension': rec.ks_domain_extension,
'ks_unit_selection': rec.ks_unit_selection, 'ks_unit_selection': rec.ks_unit_selection,
'ks_chart_unit': rec.ks_chart_unit, 'ks_chart_unit': rec.ks_chart_unit,
'ks_currency_id':rec.ks_currency_id.id,
'ks_bar_chart_stacked': rec.ks_bar_chart_stacked, 'ks_bar_chart_stacked': rec.ks_bar_chart_stacked,
'ks_goal_bar_line': rec.ks_goal_bar_line, 'ks_goal_bar_line': rec.ks_goal_bar_line,
'ks_actions': rec.ks_actions.xml_id if rec.ks_actions else False, 'ks_actions': rec.ks_actions.xml_id if rec.ks_actions else False,
@ -690,6 +717,9 @@ class KsDashboardNinjaBoard(models.Model):
'ks_multiplier_active': rec.ks_multiplier_active, 'ks_multiplier_active': rec.ks_multiplier_active,
'ks_multiplier': rec.ks_multiplier, 'ks_multiplier': rec.ks_multiplier,
'ks_multiplier_lines': ks_multiplier_lines if ks_multiplier_lines else False, 'ks_multiplier_lines': ks_multiplier_lines if ks_multiplier_lines else False,
'ks_data_label_type': rec.ks_data_label_type,
'ks_as_of_now': rec.ks_as_of_now,
# 'ks_info':rec.ks_info,
} }
if grid_corners: if grid_corners:
item.update({ item.update({
@ -759,23 +789,25 @@ class KsDashboardNinjaBoard(models.Model):
[['id', 'in', dash.ks_child_dashboard_ids.ids], ['ks_active', '=', True], [['id', 'in', dash.ks_child_dashboard_ids.ids], ['ks_active', '=', True],
['company_id', '=', self.env.company.id]], limit=1) ['company_id', '=', self.env.company.id]], limit=1)
ks_dashboard_rec = self.browse(ks_dashboard_id) ks_dashboard_rec = self.browse(ks_dashboard_id)
dashboard_data = { if selecred_rec:
'name': ks_dashboard_rec.name, name = selecred_rec.name
'ks_dashboard_menu_name': ks_dashboard_rec.ks_dashboard_menu_name, grid_conf = selecred_rec.ks_gridstack_config
'ks_gridstack_config': ks_dashboard_rec.ks_gridstack_config, elif dash.ks_child_dashboard_ids:
'ks_set_interval': ks_dashboard_rec.ks_set_interval, name = dash.display_name
'ks_date_filter_selection': ks_dashboard_rec.ks_date_filter_selection, grid_conf = dash.ks_child_dashboard_ids[0].ks_gridstack_config
'ks_dashboard_start_date': ks_dashboard_rec.ks_dashboard_start_date, else:
'ks_dashboard_end_date': ks_dashboard_rec.ks_dashboard_end_date, name = dash.name
'ks_dashboard_top_menu_id': ks_dashboard_rec.ks_dashboard_top_menu_id.id, grid_conf = dash.ks_gridstack_config
'ks_data_formatting': ks_dashboard_rec.ks_data_formatting, dashboard_data = self.ks_prepare_export_data_vals(ks_dashboard_rec, grid_conf=grid_conf)
}
if selecred_rec: if selecred_rec:
dashboard_data['name'] = selecred_rec.name dashboard_data['name'] = selecred_rec.name
dashboard_data['ks_gridstack_config'] = selecred_rec.ks_gridstack_config dashboard_data['ks_gridstack_config'] = selecred_rec.ks_gridstack_config
elif len(ks_dashboard_rec.ks_child_dashboard_ids) == 1: elif len(ks_dashboard_rec.ks_child_dashboard_ids) == 1:
dashboard_data['name'] = ks_dashboard_rec.ks_child_dashboard_ids.name dashboard_data['name'] = ks_dashboard_rec.ks_child_dashboard_ids.name
dashboard_data['ks_gridstack_config'] = ks_dashboard_rec.ks_child_dashboard_ids.ks_gridstack_config dashboard_data['ks_gridstack_config'] = ks_dashboard_rec.ks_child_dashboard_ids.ks_gridstack_config
elif len(ks_dashboard_rec.ks_child_dashboard_ids) > 1:
dashboard_data['name'] = ks_dashboard_rec.ks_child_dashboard_ids[0].name
dashboard_data['ks_gridstack_config'] = ks_dashboard_rec.ks_child_dashboard_ids[0].ks_gridstack_config
if dashboard_data['name'] != 'Default Board Layout': if dashboard_data['name'] != 'Default Board Layout':
dashboard_data['ks_dashboard_menu_name'] = selecred_rec.name dashboard_data['ks_dashboard_menu_name'] = selecred_rec.name
if dashboard_data['name'] == 'Default Board Layout': if dashboard_data['name'] == 'Default Board Layout':
@ -789,7 +821,6 @@ class KsDashboardNinjaBoard(models.Model):
items.append(item) items.append(item)
dashboard_data['ks_item_data'] = items dashboard_data['ks_item_data'] = items
ks_dashboard_data.append(dashboard_data) ks_dashboard_data.append(dashboard_data)
ks_dashboard_export_data = { ks_dashboard_export_data = {
@ -798,6 +829,20 @@ class KsDashboardNinjaBoard(models.Model):
} }
return ks_dashboard_export_data return ks_dashboard_export_data
def ks_prepare_export_data_vals(self, ks_dashboard_rec, grid_conf=None,):
dashboard_data = {
'name': ks_dashboard_rec.name,
'ks_dashboard_menu_name': ks_dashboard_rec.ks_dashboard_menu_name,
'ks_gridstack_config': grid_conf if grid_conf else '{}',
'ks_set_interval': ks_dashboard_rec.ks_set_interval,
'ks_date_filter_selection': ks_dashboard_rec.ks_date_filter_selection,
'ks_dashboard_start_date': ks_dashboard_rec.ks_dashboard_start_date,
'ks_dashboard_end_date': ks_dashboard_rec.ks_dashboard_end_date,
'ks_dashboard_top_menu_id': ks_dashboard_rec.ks_dashboard_top_menu_id.id,
'ks_data_formatting': ks_dashboard_rec.ks_data_formatting,
}
return dashboard_data
@api.model @api.model
def ks_import_dashboard(self, file, menu_id): def ks_import_dashboard(self, file, menu_id):
try: try:
@ -828,25 +873,13 @@ class KsDashboardNinjaBoard(models.Model):
ks_dashboard_top_menu_id = self.env['ir.ui.menu'].browse(ks_dashboard_top_menu_id) ks_dashboard_top_menu_id = self.env['ir.ui.menu'].browse(ks_dashboard_top_menu_id)
except Exception: except Exception:
ks_dashboard_top_menu_id = False ks_dashboard_top_menu_id = False
vals = { vals = self.ks_prepare_import_data_vals(data, menu_id)
'name': data['name'],
'ks_dashboard_menu_name': data['ks_dashboard_menu_name'],
'ks_dashboard_top_menu_id': menu_id.id if menu_id else self.env.ref(
"ks_dashboard_ninja.board_menu_root").id,
'ks_dashboard_active': True,
'ks_gridstack_config': data['ks_gridstack_config'],
'ks_dashboard_default_template': self.env.ref("ks_dashboard_ninja.ks_blank").id,
'ks_dashboard_group_access': False,
'ks_set_interval': data['ks_set_interval'],
'ks_date_filter_selection': data['ks_date_filter_selection'],
'ks_dashboard_start_date': data['ks_dashboard_start_date'],
'ks_dashboard_end_date': data['ks_dashboard_end_date'],
}
# Creating Dashboard # Creating Dashboard
dashboard_id = self.create(vals) dashboard_id = self.create(vals)
if data['ks_gridstack_config']: if data['ks_gridstack_config']:
ks_gridstack_config = eval(data['ks_gridstack_config']) ks_gridstack_config = safe_eval(data['ks_gridstack_config'])
ks_grid_stack_config = {} ks_grid_stack_config = {}
item_ids = [] item_ids = []
@ -898,6 +931,23 @@ class KsDashboardNinjaBoard(models.Model):
return "Success" return "Success"
# separate function to make item for import # separate function to make item for import
def ks_prepare_import_data_vals(self, data, menu_id):
vals = {
'name': data['name'],
'ks_dashboard_menu_name': data['ks_dashboard_menu_name'],
'ks_dashboard_top_menu_id': menu_id.id if menu_id else self.env.ref(
"ks_dashboard_ninja.board_menu_root").id,
'ks_dashboard_active': True,
'ks_gridstack_config': data['ks_gridstack_config'],
'ks_dashboard_default_template': self.env.ref("ks_dashboard_ninja.ks_blank").id,
'ks_dashboard_group_access': False,
'ks_set_interval': data['ks_set_interval'],
'ks_date_filter_selection': data['ks_date_filter_selection'],
'ks_dashboard_start_date': data['ks_dashboard_start_date'],
'ks_dashboard_end_date': data['ks_dashboard_end_date'],
}
return vals
def ks_create_item(self, item): def ks_create_item(self, item):
model = self.env['ir.model'].search([('model', '=', item['ks_model_id'])]) model = self.env['ir.model'].search([('model', '=', item['ks_model_id'])])
@ -982,149 +1032,155 @@ class KsDashboardNinjaBoard(models.Model):
return ks_item return ks_item
def ks_prepare_item(self, item): def ks_prepare_item(self, item):
ks_measure_field_ids = [] try:
ks_measure_field_2_ids = [] ks_measure_field_ids = []
ks_measure_field_2_ids = []
for ks_measure in item['ks_chart_measure_field']: for ks_measure in item['ks_chart_measure_field']:
ks_measure_id = self.env['ir.model.fields'].search( ks_measure_id = self.env['ir.model.fields'].search(
[('name', '=', ks_measure), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_measure), ('model', '=', item['ks_model_id'])])
if ks_measure_id: if ks_measure_id:
ks_measure_field_ids.append(ks_measure_id.id) ks_measure_field_ids.append(ks_measure_id.id)
item['ks_chart_measure_field'] = [(6, 0, ks_measure_field_ids)] item['ks_chart_measure_field'] = [(6, 0, ks_measure_field_ids)]
for ks_measure in item['ks_chart_measure_field_2']: for ks_measure in item['ks_chart_measure_field_2']:
ks_measure_id = self.env['ir.model.fields'].search( ks_measure_id = self.env['ir.model.fields'].search(
[('name', '=', ks_measure), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_measure), ('model', '=', item['ks_model_id'])])
if ks_measure_id: if ks_measure_id:
ks_measure_field_2_ids.append(ks_measure_id.id) ks_measure_field_2_ids.append(ks_measure_id.id)
item['ks_chart_measure_field_2'] = [(6, 0, ks_measure_field_2_ids)] item['ks_chart_measure_field_2'] = [(6, 0, ks_measure_field_2_ids)]
ks_list_view_group_fields = [] ks_list_view_group_fields = []
for ks_measure in item['ks_list_view_group_fields']: for ks_measure in item['ks_list_view_group_fields']:
ks_measure_id = self.env['ir.model.fields'].search( ks_measure_id = self.env['ir.model.fields'].search(
[('name', '=', ks_measure), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_measure), ('model', '=', item['ks_model_id'])])
if ks_measure_id: if ks_measure_id:
ks_list_view_group_fields.append(ks_measure_id.id) ks_list_view_group_fields.append(ks_measure_id.id)
item['ks_list_view_group_fields'] = [(6, 0, ks_list_view_group_fields)] item['ks_list_view_group_fields'] = [(6, 0, ks_list_view_group_fields)]
ks_list_view_field_ids = [] ks_list_view_field_ids = []
for ks_list_field in item['ks_list_view_fields']: for ks_list_field in item['ks_list_view_fields']:
ks_list_field_id = self.env['ir.model.fields'].search( ks_list_field_id = self.env['ir.model.fields'].search(
[('name', '=', ks_list_field), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_list_field), ('model', '=', item['ks_model_id'])])
if ks_list_field_id: if ks_list_field_id:
ks_list_view_field_ids.append(ks_list_field_id.id) ks_list_view_field_ids.append(ks_list_field_id.id)
item['ks_list_view_fields'] = [(6, 0, ks_list_view_field_ids)] item['ks_list_view_fields'] = [(6, 0, ks_list_view_field_ids)]
if item['ks_record_field']: if item['ks_record_field']:
ks_record_field = item['ks_record_field'] ks_record_field = item['ks_record_field']
ks_record_id = self.env['ir.model.fields'].search( ks_record_id = self.env['ir.model.fields'].search(
[('name', '=', ks_record_field), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_record_field), ('model', '=', item['ks_model_id'])])
if ks_record_id: if ks_record_id:
item['ks_record_field'] = ks_record_id.id item['ks_record_field'] = ks_record_id.id
else: else:
item['ks_record_field'] = False item['ks_record_field'] = False
if item['ks_date_filter_field']: if item['ks_date_filter_field']:
ks_date_filter_field = item['ks_date_filter_field'] ks_date_filter_field = item['ks_date_filter_field']
ks_record_id = self.env['ir.model.fields'].search( ks_record_id = self.env['ir.model.fields'].search(
[('name', '=', ks_date_filter_field), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_date_filter_field), ('model', '=', item['ks_model_id'])])
if ks_record_id: if ks_record_id:
item['ks_date_filter_field'] = ks_record_id.id item['ks_date_filter_field'] = ks_record_id.id
else: else:
item['ks_date_filter_field'] = False item['ks_date_filter_field'] = False
if item['ks_chart_relation_groupby']: if item['ks_chart_relation_groupby']:
ks_group_by = item['ks_chart_relation_groupby'] ks_group_by = item['ks_chart_relation_groupby']
ks_record_id = self.env['ir.model.fields'].search( ks_record_id = self.env['ir.model.fields'].search(
[('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])])
if ks_record_id: if ks_record_id:
item['ks_chart_relation_groupby'] = ks_record_id.id item['ks_chart_relation_groupby'] = ks_record_id.id
else: else:
item['ks_chart_relation_groupby'] = False item['ks_chart_relation_groupby'] = False
if item['ks_chart_relation_sub_groupby']: if item['ks_chart_relation_sub_groupby']:
ks_group_by = item['ks_chart_relation_sub_groupby'] ks_group_by = item['ks_chart_relation_sub_groupby']
ks_chart_relation_sub_groupby = self.env['ir.model.fields'].search( ks_chart_relation_sub_groupby = self.env['ir.model.fields'].search(
[('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])])
if ks_chart_relation_sub_groupby: if ks_chart_relation_sub_groupby:
item['ks_chart_relation_sub_groupby'] = ks_chart_relation_sub_groupby.id item['ks_chart_relation_sub_groupby'] = ks_chart_relation_sub_groupby.id
else: else:
item['ks_chart_relation_sub_groupby'] = False item['ks_chart_relation_sub_groupby'] = False
# Sort by field : Many2one Entery # Sort by field : Many2one Entery
if item['ks_sort_by_field']: if item['ks_sort_by_field']:
ks_group_by = item['ks_sort_by_field'] ks_group_by = item['ks_sort_by_field']
ks_sort_by_field = self.env['ir.model.fields'].search( ks_sort_by_field = self.env['ir.model.fields'].search(
[('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])]) [('name', '=', ks_group_by), ('model', '=', item['ks_model_id'])])
if ks_sort_by_field: if ks_sort_by_field:
item['ks_sort_by_field'] = ks_sort_by_field.id item['ks_sort_by_field'] = ks_sort_by_field.id
else:
item['ks_sort_by_field'] = False
if item['ks_list_target_deviation_field']:
ks_list_target_deviation_field = item['ks_list_target_deviation_field']
record_id = self.env['ir.model.fields'].search(
[('name', '=', ks_list_target_deviation_field), ('model', '=', item['ks_model_id'])])
if record_id:
item['ks_list_target_deviation_field'] = record_id.id
else:
item['ks_list_target_deviation_field'] = False
ks_model_id = self.env['ir.model'].search([('model', '=', item['ks_model_id'])]).id
if item.get("ks_actions"):
ks_action = self.env.ref(item["ks_actions"], False)
if ks_action:
item["ks_actions"] = ks_action.id
else:
item["ks_actions"] = False
if item.get("ks_client_action"):
ks_action = self.env.ref(item["ks_client_action"], False)
if ks_action:
item["ks_client_action"] = ks_action.id
else:
item["ks_client_action"] = False
if (item['ks_model_id_2']):
ks_model_2 = item['ks_model_id_2'].replace(".", "_")
ks_model_id_2 = self.env['ir.model'].search([('model', '=', item['ks_model_id_2'])]).id
if item['ks_record_field_2']:
ks_record_field = item['ks_record_field_2']
ks_record_id = self.env['ir.model.fields'].search(
[('model', '=', item['ks_model_id_2']), ('name', '=', ks_record_field)])
if ks_record_id:
item['ks_record_field_2'] = ks_record_id.id
else: else:
item['ks_record_field_2'] = False item['ks_sort_by_field'] = False
if item['ks_date_filter_field_2']:
ks_record_id = self.env['ir.model.fields'].search(
[('model', '=', item['ks_model_id_2']), ('name', '=', item['ks_date_filter_field_2'])])
if ks_record_id: if item['ks_list_target_deviation_field']:
item['ks_date_filter_field_2'] = ks_record_id.id ks_list_target_deviation_field = item['ks_list_target_deviation_field']
record_id = self.env['ir.model.fields'].search(
[('name', '=', ks_list_target_deviation_field), ('model', '=', item['ks_model_id'])])
if record_id:
item['ks_list_target_deviation_field'] = record_id.id
else: else:
item['ks_date_filter_field_2'] = False item['ks_list_target_deviation_field'] = False
item['ks_model_id_2'] = ks_model_id_2 ks_model_id = self.env['ir.model'].search([('model', '=', item['ks_model_id'])]).id
else:
item['ks_date_filter_field_2'] = False
item['ks_record_field_2'] = False
item['ks_model_id'] = ks_model_id if item.get("ks_actions"):
ks_action = self.env.ref(item["ks_actions"], False)
if ks_action:
item["ks_actions"] = ks_action.id
else:
item["ks_actions"] = False
if item.get("ks_client_action"):
ks_action = self.env.ref(item["ks_client_action"], False)
if ks_action:
item["ks_client_action"] = ks_action.id
else:
item["ks_client_action"] = False
item['ks_goal_liness'] = False if (item['ks_model_id_2']):
item['ks_item_start_date'] = item['ks_item_start_date'] if \ ks_model_2 = item['ks_model_id_2'].replace(".", "_")
item['ks_item_start_date'] else False ks_model_id_2 = self.env['ir.model'].search([('model', '=', item['ks_model_id_2'])]).id
item['ks_item_end_date'] = item['ks_item_end_date'] if \ if item['ks_record_field_2']:
item['ks_item_end_date'] else False ks_record_field = item['ks_record_field_2']
item['ks_item_start_date_2'] = item['ks_item_start_date_2'] if \ ks_record_id = self.env['ir.model.fields'].search(
item['ks_item_start_date_2'] else False [('model', '=', item['ks_model_id_2']), ('name', '=', ks_record_field)])
item['ks_item_end_date_2'] = item['ks_item_end_date_2'] if \
item['ks_item_end_date_2'] else False
return item if ks_record_id:
item['ks_record_field_2'] = ks_record_id.id
else:
item['ks_record_field_2'] = False
if item['ks_date_filter_field_2']:
ks_record_id = self.env['ir.model.fields'].search(
[('model', '=', item['ks_model_id_2']), ('name', '=', item['ks_date_filter_field_2'])])
if ks_record_id:
item['ks_date_filter_field_2'] = ks_record_id.id
else:
item['ks_date_filter_field_2'] = False
item['ks_model_id_2'] = ks_model_id_2
else:
item['ks_date_filter_field_2'] = False
item['ks_record_field_2'] = False
item['ks_model_id'] = ks_model_id
# if item['ks_currency_id']:
# ks_currency = self.env['res.currency'].browse(item['ks_currency_id']).name
# item['ks_currency_id'] = self.env['res.currency'].search([('name','=',ks_currency)])
item['ks_goal_liness'] = False
item['ks_item_start_date'] = item['ks_item_start_date'] if \
item['ks_item_start_date'] else False
item['ks_item_end_date'] = item['ks_item_end_date'] if \
item['ks_item_end_date'] else False
item['ks_item_start_date_2'] = item['ks_item_start_date_2'] if \
item['ks_item_start_date_2'] else False
item['ks_item_end_date_2'] = item['ks_item_end_date_2'] if \
item['ks_item_end_date_2'] else False
return item
except Exception as e:
raise ValidationError('JSON file not supported.')
@api.model @api.model
def update_child_board(self, action, dashboard_id, data): def update_child_board(self, action, dashboard_id, data):

View File

@ -112,15 +112,27 @@ def ks_time_addition(self, gb, query):
tz_convert = field_type == 'datetime' and self._context.get('tz') in pytz.all_timezones tz_convert = field_type == 'datetime' and self._context.get('tz') in pytz.all_timezones
qualified_field = self._inherits_join_calc(self._table, split[0], query) qualified_field = self._inherits_join_calc(self._table, split[0], query)
if temporal: if temporal:
display_formats = { lang = self.env['res.lang']._lang_get(self.env.user.lang).time_format
'minute': 'hh:mm dd MMM', if '%H' in lang:
'hour': 'hh:00 dd MMM', display_formats = {
'day': 'dd MMM yyyy', # yyyy = normal year 'minute': 'HH:mm dd MMM',
'week': "'W'w YYYY", # w YYYY = ISO week-year 'hour': 'HH:00 dd MMM',
'month': 'MMMM yyyy', 'day': 'dd MMM yyyy', # yyyy = normal year
'quarter': 'QQQ yyyy', 'week': "'W'w YYYY", # w YYYY = ISO week-year
'year': 'yyyy', 'month': 'MMMM yyyy',
} 'quarter': 'QQQ yyyy',
'year': 'yyyy',
}
else:
display_formats = {
'minute': 'hh:mm dd MMM',
'hour': 'hh:00 dd MMM',
'day': 'dd MMM yyyy', # yyyy = normal year
'week': "'W'w YYYY", # w YYYY = ISO week-year
'month': 'MMMM yyyy',
'quarter': 'QQQ yyyy',
'year': 'yyyy',
}
time_intervals = { time_intervals = {
'minute': dateutil.relativedelta.relativedelta(minutes=1), 'minute': dateutil.relativedelta.relativedelta(minutes=1),
'hour': dateutil.relativedelta.relativedelta(hours=1), 'hour': dateutil.relativedelta.relativedelta(hours=1),
@ -153,19 +165,24 @@ class KsDashboardNinjaItems(models.Model):
_name = 'ks_dashboard_ninja.item' _name = 'ks_dashboard_ninja.item'
_description = 'Dashboard Ninja items' _description = 'Dashboard Ninja items'
name = fields.Char(string="Name", size=256, help="The item will be represented by this unique name.") name = fields.Char(string="Name", size=256,
translate=True,
help="The item will be represented by this unique name.")
ks_info = fields.Text(string="Item Description",
translate=True)
ks_model_id = fields.Many2one('ir.model', string='Model', ks_model_id = fields.Many2one('ir.model', string='Model',
domain="[('access_ids','!=',False),('transient','=',False)," domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%')," "('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=ilike','_%ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'),('model','not ilike','ks_to%')]", "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]",
help="Data source to fetch and read the data for the creation of dashboard items. ") help="Data source to fetch and read the data for the creation of dashboard items. ")
ks_dashboard_board_template_id = fields.Many2one('ks_dashboard_ninja.board_template', string="Dashboard Template") ks_dashboard_board_template_id = fields.Many2one('ks_dashboard_ninja.board_template', string="Dashboard Template")
ks_domain = fields.Char(string="Domain", help="Define conditions for filter. ") ks_domain = fields.Char(string="Domain", help="Define conditions for filter. ")
ks_model_id_2 = fields.Many2one('ir.model', string='Kpi Model', ks_model_id_2 = fields.Many2one('ir.model', string='Kpi Model',
domain="[('access_ids','!=',False),('transient','=',False)," domain="[('access_ids','!=',False),('transient','=',False),"
"('model','not ilike','base_import%'),('model','not ilike','ir.%')," "('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=ilike','_%ir.%'),"
"('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%')," "('model','not ilike','web_editor.%'),('model','not ilike','web_tour.%'),"
"('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]") "('model','!=','mail.thread'),('model','not ilike','ks_dash%'), ('model','not ilike','ks_to%')]")
@ -231,6 +248,10 @@ class KsDashboardNinjaItems(models.Model):
('t_month', 'This Month'), ('t_month', 'This Month'),
('t_quarter', 'This Quarter'), ('t_quarter', 'This Quarter'),
('t_year', 'This Year'), ('t_year', 'This Year'),
('td_week', 'Week to Date'),
('td_month', 'Month to Date'),
('td_quarter', 'Quarter to Date'),
('td_year', 'Year to Date'),
('n_day', 'Next Day'), ('n_day', 'Next Day'),
('n_week', 'Next Week'), ('n_week', 'Next Week'),
('n_month', 'Next Month'), ('n_month', 'Next Month'),
@ -246,6 +267,7 @@ class KsDashboardNinjaItems(models.Model):
('l_quarter', 'Last 90 days'), ('l_quarter', 'Last 90 days'),
('l_year', 'Last 365 days'), ('l_year', 'Last 365 days'),
('ls_past_until_now', 'Past Till Now'), ('ls_past_until_now', 'Past Till Now'),
('ls_pastuntil_lastmonth', 'Past Till: 30 days ago'),
('ls_pastwithout_now', ' Past Excluding Today'), ('ls_pastwithout_now', ' Past Excluding Today'),
('n_future_starting_now', 'Future Starting Now'), ('n_future_starting_now', 'Future Starting Now'),
('n_futurestarting_tomorrow', 'Future Starting Tomorrow'), ('n_futurestarting_tomorrow', 'Future Starting Tomorrow'),
@ -279,6 +301,10 @@ class KsDashboardNinjaItems(models.Model):
('t_month', 'This Month'), ('t_month', 'This Month'),
('t_quarter', 'This Quarter'), ('t_quarter', 'This Quarter'),
('t_year', 'This Year'), ('t_year', 'This Year'),
('td_week', 'Week to Date'),
('td_month', 'Month to Date'),
('td_quarter', 'Quarter to Date'),
('td_year', 'Year to Date'),
('n_day', 'Next Day'), ('n_day', 'Next Day'),
('n_week', 'Next Week'), ('n_week', 'Next Week'),
('n_month', 'Next Month'), ('n_month', 'Next Month'),
@ -294,6 +320,7 @@ class KsDashboardNinjaItems(models.Model):
('l_quarter', 'Last 90 days'), ('l_quarter', 'Last 90 days'),
('l_year', 'Last 365 days'), ('l_year', 'Last 365 days'),
('ls_past_until_now', 'Past Till Now'), ('ls_past_until_now', 'Past Till Now'),
('ls_pastuntil_lastmonth', 'Past Till: 30 days ago'),
('ls_pastwithout_now', ' Past Excluding Today'), ('ls_pastwithout_now', ' Past Excluding Today'),
('n_future_starting_now', 'Future Starting Now'), ('n_future_starting_now', 'Future Starting Now'),
('n_futurestarting_tomorrow', 'Future Starting Tomorrow'), ('n_futurestarting_tomorrow', 'Future Starting Tomorrow'),
@ -366,7 +393,7 @@ class KsDashboardNinjaItems(models.Model):
"('ttype','=','integer'),('ttype','=','float')," "('ttype','=','integer'),('ttype','=','float'),"
"('ttype','=','monetary')]", "('ttype','=','monetary')]",
string="Measure 1", help='Data points to be selected.') string="Measure 1", help='Data points to be selected.')
ks_chart_is_cumulative = fields.Boolean('Is Cumulative')
ks_chart_cumulative_field = fields.Many2many('ir.model.fields', 'ks_dn_cumulative_measure_field_rel', ks_chart_cumulative_field = fields.Many2many('ir.model.fields', 'ks_dn_cumulative_measure_field_rel',
'measure_cumulative_field_id', 'measure_cumulative_field_id',
'cumulative_field_id', 'cumulative_field_id',
@ -375,7 +402,7 @@ class KsDashboardNinjaItems(models.Model):
"('store','=',True),'|','|'," "('store','=',True),'|','|',"
"('ttype','=','integer'),('ttype','=','float')," "('ttype','=','integer'),('ttype','=','float'),"
"('ttype','=','monetary')]", "('ttype','=','monetary')]",
string="Cumulative Field", help='Data points to be selected.') string="Cumulative Fields", help='Data points to be selected.')
ks_chart_cumulative = fields.Boolean("Cumulative As Line") ks_chart_cumulative = fields.Boolean("Cumulative As Line")
ks_chart_measure_field_2 = fields.Many2many('ir.model.fields', 'ks_dn_measure_field_rel_2', 'measure_field_id_2', ks_chart_measure_field_2 = fields.Many2many('ir.model.fields', 'ks_dn_measure_field_rel_2', 'measure_field_id_2',
@ -414,6 +441,11 @@ class KsDashboardNinjaItems(models.Model):
ks_kpi_data = fields.Char(string="KPI Data", compute="ks_get_kpi_data", compute_sudo=False) ks_kpi_data = fields.Char(string="KPI Data", compute="ks_get_kpi_data", compute_sudo=False)
# ------------------------ Tile View Fields ------------------------------
ks_tile_data = fields.Char(string="TILE Data", compute="ks_get_tile_data", compute_sudo=False)
ks_chart_item_color = fields.Selection( ks_chart_item_color = fields.Selection(
[('default', 'Default'), ('cool', 'Cool'), ('warm', 'Warm'), ('neon', 'Neon')], [('default', 'Default'), ('cool', 'Cool'), ('warm', 'Warm'), ('neon', 'Neon')],
string="Chart Color Palette", default="default", help='Select the display preference. ') string="Chart Color Palette", default="default", help='Select the display preference. ')
@ -481,20 +513,11 @@ class KsDashboardNinjaItems(models.Model):
help="Provides the visibility of multiplier field") help="Provides the visibility of multiplier field")
ks_multiplier = fields.Float(string="Multiplier", default=1, help="Provides the multiplication of record value") ks_multiplier = fields.Float(string="Multiplier", default=1, help="Provides the multiplication of record value")
# Adding refresh per item override global update interval
ks_update_items_data = fields.Selection([
('15000', '15 Seconds'),
('30000', '30 Seconds'),
('45000', '45 Seconds'),
('60000', '1 minute'),
('120000', '2 minute'),
('300000', '5 minute'),
('600000', '10 minute'),
], string="Item Update Interval", default=lambda self: self._context.get('ks_set_interval', False),
help=" Data will be refreshed after the selected interval.")
# User can select custom units for measure # User can select custom units for measure
ks_unit = fields.Boolean(string="Show Custom Unit", default=False, help='Display the unit of the data.') ks_unit = fields.Boolean(string="Show Custom Unit", default=False, help='Display the unit of the data.')
ks_currency_id= fields.Many2one("res.currency",string="Currency", domain="['|', ('active', '=', False), ('active', '=', True)]")
ks_unit_selection = fields.Selection([ ks_unit_selection = fields.Selection([
('monetary', 'Monetary'), ('monetary', 'Monetary'),
('custom', 'Custom'), ('custom', 'Custom'),
@ -529,14 +552,7 @@ class KsDashboardNinjaItems(models.Model):
help="To Change the number format showing in chart to given option") help="To Change the number format showing in chart to given option")
ks_button_color = fields.Char(string="Top Button Color", ks_button_color = fields.Char(string="Top Button Color",
default="#000000,0.99") default="#000000,0.99")
ks_auto_update_type = fields.Selection(
[('ks_live_update', 'Update at every instance.'),
('ks_update_interval', ' Update after the selected interval')],
string='Auto Update Type',
default=lambda self: 'ks_update_interval' if self._context.get('ks_set_interval', False) else False,
help='Select the update type.')
ks_show_live_pop_up = fields.Boolean(string='Show Live Update Pop Up',
help='Checkbox to enable notification after every update. ')
ks_is_client_action = fields.Boolean('Client Action', default=False) ks_is_client_action = fields.Boolean('Client Action', default=False)
ks_client_action = fields.Many2one('ir.actions.client', ks_client_action = fields.Many2one('ir.actions.client',
@ -552,6 +568,153 @@ class KsDashboardNinjaItems(models.Model):
ks_precision_digits = fields.Integer('Digits', compute="_ks_compute_precision_digits", store=True, readonly=False) ks_precision_digits = fields.Integer('Digits', compute="_ks_compute_precision_digits", store=True, readonly=False)
ks_data_label_type = fields.Selection([('percent', 'Percent'), ('value', 'Value')], string='Show Data Value Type',
help='When "Show Data Value Type" selected this field enables to select label type in percent or value',
default='percent')
ks_as_of_now = fields.Boolean("Data Till Now",
help="Display the total sum of each legends as it grows with times")
@api.model
def create_ai_dash(self, data, ks_dash_id, model):
try:
result= []
for item in data:
ks_measure_field_ids = []
value = {}
chart_switch = {
'bar': "ks_bar_chart",
'pie': 'ks_pie_chart',
'donut': 'ks_doughnut_chart',
'area': 'ks_area_chart',
'line': 'ks_line_chart',
'polar': 'ks_polarArea_chart',
'horizontalbar': 'ks_horizontalBar_chart',
'table': "ks_list_view"
}
if item["chart_type"].lower() in ['bar', 'line', 'pie', 'area', 'donut', 'polar', 'horizontalbar']:
ks_measure_id = self.env['ir.model.fields'].search(
[('name', '=', item["aggregations"][0]["field"]), ('model', '=', model)])
if ks_measure_id and ks_measure_id['ttype'] in ['integer','float','monetary']:
ks_measure_field_ids.append(ks_measure_id.id)
value["ks_chart_measure_field"] = [(6, 0, ks_measure_field_ids)]
ks_record_id = self.env['ir.model.fields'].search(
[('name', '=', item["group_by_column"]), ('model', '=', model)])
if ks_record_id:
value['ks_chart_relation_groupby'] = ks_record_id.id
if ks_record_id['ttype'] == "datetime" or ks_record_id['ttype'] == "date":
value['ks_chart_date_groupby'] = "month"
value["name"] = item["chart_name"]
ks_model_id = self.env['ir.model'].search([('model', '=', model)]).id
value['ks_model_id'] = ks_model_id
if item["aggregations"][0]["type"] == 'avg':
value['ks_chart_data_count_type'] = 'average'
else:
value['ks_chart_data_count_type'] = item["aggregations"][0]["type"]
value['ks_dashboard_item_type'] = chart_switch.get(item['chart_type'], False)
value['ks_dashboard_ninja_board_id'] = ks_dash_id
if ks_measure_field_ids and ks_record_id and ks_model_id:
try:
ks_result = self.create(value)
result.append(ks_result)
except Exception as e:
result
elif item["chart_type"].lower() == "table":
value["name"] = item["chart_name"]
value['ks_dashboard_ninja_board_id'] = ks_dash_id
value['ks_dashboard_item_type'] = chart_switch.get(item['chart_type'], False)
ks_model_id = self.env['ir.model'].search([('model', '=', model)]).id
value['ks_model_id'] = ks_model_id
ks_measure_id = self.env['ir.model.fields'].search(
[('name', '=', item["aggregations"][0]["field"]), ('model', '=', model)])
if ks_measure_id and ks_measure_id['ttype'] in ['integer','float','monetary']:
ks_measure_field_ids.append(ks_measure_id.id)
value["ks_list_view_group_fields"] = [(6, 0, ks_measure_field_ids)]
# value["ks_list_view_fields"] = [(6, 0, ks_measure_field_ids)]
ks_record_id = self.env['ir.model.fields'].search(
[('name', '=', item["group_by_column"]), ('model', '=', model)])
if ks_record_id:
value['ks_chart_relation_groupby'] = ks_record_id.id
if ks_record_id['ttype'] == "datetime" or ks_record_id['ttype'] == "date":
value['ks_chart_date_groupby'] = "month"
value['ks_list_view_type'] = 'grouped'
if ks_measure_field_ids and ks_record_id and ks_model_id:
try:
ks_result = self.create(value)
result.append(ks_result)
except Exception as e:
result
elif item["chart_type"].lower() == "kpi":
value["name"] = item["chart_name"]
value['ks_dashboard_ninja_board_id'] = ks_dash_id
value['ks_dashboard_item_type'] = "ks_kpi"
ks_model_id = self.env['ir.model'].search([('model', '=', model)]).id
value['ks_model_id'] = ks_model_id
ks_measure_id = self.env['ir.model.fields'].search(
[('name', '=', item["aggregations"][0]["field"]), ('model', '=', model)])
if ks_measure_id:
value["ks_record_field"] = ks_measure_id.id
if item["aggregations"][0]["type"] == 'avg':
value['ks_record_count_type'] = 'average'
else:
value['ks_record_count_type'] = item["aggregations"][0]["type"]
value['ks_background_color'] = "#ffffff,0.99"
value['ks_default_icon_color'] = "#000000,0.99"
value['ks_font_color'] = "#000000,0.99"
value['ks_button_color'] = "#000000,0.99"
if ks_measure_id and ks_model_id:
try:
ks_result = self.create(value)
result.append(ks_result)
except Exception as e:
result
else:
pass
if len(result):
return "success"
else:
return "Abort"
except:
raise ValidationError(_("Getting invalid response from AI, please try again"))
# Making model, csv and excel field invisible on condition.
@api.onchange('data_source')
def make_invisible(self):
if self.data_source == 'excel':
self.excel_bool = True
self.model_bool = False
self.csv_bool = False
elif self.data_source == 'odoo':
self.model_bool = True
self.excel_bool = False
self.csv_bool = False
elif self.data_source == 'csv':
self.csv_bool = True
self.model_bool = False
self.excel_bool = False
else:
self.model_bool = False
self.excel_bool = False
self.csv_bool = False
# Reading the Csv file
@api.onchange('ks_year_period', 'ks_year_period_2') @api.onchange('ks_year_period', 'ks_year_period_2')
def ks_year_neg_val_not_allow(self): def ks_year_neg_val_not_allow(self):
for rec in self: for rec in self:
@ -589,7 +752,8 @@ class KsDashboardNinjaItems(models.Model):
# default = lambda self: self.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision') # default = lambda self: self.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision')
@api.onchange('ks_multiplier_active', 'ks_chart_measure_field', 'ks_list_view_group_fields') @api.onchange('ks_multiplier_active', 'ks_chart_measure_field',
'ks_chart_measure_field_2' ,'ks_list_view_group_fields')
def _ks_compute_multiplier_lines(self): def _ks_compute_multiplier_lines(self):
for rec in self: for rec in self:
rec.ks_multiplier_lines = [(5, 0, 0)] rec.ks_multiplier_lines = [(5, 0, 0)]
@ -598,16 +762,32 @@ class KsDashboardNinjaItems(models.Model):
if rec.ks_dashboard_item_type == 'ks_list_view' and rec.ks_list_view_type == 'grouped': if rec.ks_dashboard_item_type == 'ks_list_view' and rec.ks_list_view_type == 'grouped':
ks_chart_measure_fields = rec.ks_list_view_group_fields ks_chart_measure_fields = rec.ks_list_view_group_fields
ks_temp_list = [] ks_temp_list = []
ks_chart_measure_id = []
for ks_chart_measure_field in ks_chart_measure_fields: for ks_chart_measure_field in ks_chart_measure_fields:
ks_dict = { ks_dict = {
'ks_dashboard_item_id': rec.id, 'ks_dashboard_item_id': rec.id,
'ks_multiplier_fields': ks_chart_measure_field.ids[0], 'ks_multiplier_fields': ks_chart_measure_field.ids[0],
'ks_multiplier_value': 1 'ks_multiplier_value': 1
} }
ks_chart_measure_id.append(ks_chart_measure_field.ids[0])
ks_line = self.env['ks_dashboard_item.multiplier'].create(ks_dict) ks_line = self.env['ks_dashboard_item.multiplier'].create(ks_dict)
ks_temp_list.append(ks_line.id) ks_temp_list.append(ks_line.id)
if rec.ks_chart_measure_field_2:
for ks_chart_measure_field in rec.ks_chart_measure_field_2:
if ks_chart_measure_field.ids[0] not in ks_chart_measure_id:
ks_dict = {
'ks_dashboard_item_id': rec.id,
'ks_multiplier_fields': ks_chart_measure_field.ids[0],
'ks_multiplier_value': 1
}
ks_line = self.env['ks_dashboard_item.multiplier'].create(ks_dict)
ks_temp_list.append(ks_line.id)
# rec.ks_multiplier_lines = [(6, 0, [])]
# rec.ks_multiplier_lines = [(6, 0, ks_temp_list)]
rec.ks_multiplier_lines = [(6, 0, [])] rec.ks_multiplier_lines = [(6, 0, [])]
rec.ks_multiplier_lines = [(6, 0, ks_temp_list)] rec.ks_multiplier_lines = [(6, 0, ks_temp_list)]
if len(rec.ks_chart_measure_field) == 0: if len(rec.ks_chart_measure_field) == 0:
rec.ks_chart_cumulative_field = False rec.ks_chart_cumulative_field = False
# if rec.ks_chart_cumulative_field: # if rec.ks_chart_cumulative_field:
@ -714,6 +894,11 @@ class KsDashboardNinjaItems(models.Model):
if 'ks_goal_lines' not in default: if 'ks_goal_lines' not in default:
default['ks_goal_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_goal_lines] default['ks_goal_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_goal_lines]
if 'ks_multiplier_lines' not in default:
default['ks_multiplier_lines'] = [(0, 0, line.copy_data()[0]) for line in self.ks_multiplier_lines]
return super(KsDashboardNinjaItems, self).copy_data(default) return super(KsDashboardNinjaItems, self).copy_data(default)
def copy(self, default=None): def copy(self, default=None):
@ -1011,7 +1196,7 @@ class KsDashboardNinjaItems(models.Model):
if selected_start_date and selected_end_date: if selected_start_date and selected_end_date:
if rec.ks_compare_period: if rec.ks_compare_period:
ks_compare_period = abs(rec.ks_compare_period) ks_compare_period = abs(rec.ks_compare_period)
if ks_compare_period > 100: if ks_compare_period > 100 and rec.ks_date_filter_selection.split('_')[1] != 'day':
ks_compare_period = 100 ks_compare_period = 100
if rec.ks_compare_period > 0: if rec.ks_compare_period > 0:
selected_end_date = selected_end_date + ( selected_end_date = selected_end_date + (
@ -1076,14 +1261,13 @@ class KsDashboardNinjaItems(models.Model):
ks_extensiom_domain = ks_extensiom_domain.replace('"%UID"', str(self.env.user.id)) ks_extensiom_domain = ks_extensiom_domain.replace('"%UID"', str(self.env.user.id))
if "%UID" in ks_extensiom_domain: if "%UID" in ks_extensiom_domain:
ks_extensiom_domain = ks_extensiom_domain.replace("'%UID'", str(self.env.user.id)) ks_extensiom_domain = ks_extensiom_domain.replace("'%UID'", str(self.env.user.id))
print(ks_extensiom_domain)
if ks_extensiom_domain and "%MYCOMPANY" in ks_extensiom_domain: if ks_extensiom_domain and "%MYCOMPANY" in ks_extensiom_domain:
ks_extensiom_domain = ks_extensiom_domain.replace('"%MYCOMPANY"', str(self.env.company.id)) ks_extensiom_domain = ks_extensiom_domain.replace('"%MYCOMPANY"', str(self.env.company.id))
if "%MYCOMPANY" in ks_extensiom_domain: if "%MYCOMPANY" in ks_extensiom_domain:
ks_extensiom_domain = ks_extensiom_domain.replace("'%MYCOMPANY'", str(self.env.company.id)) ks_extensiom_domain = ks_extensiom_domain.replace("'%MYCOMPANY'", str(self.env.company.id))
ks_domain = eval(ks_extensiom_domain) ks_domain = safe_eval(ks_extensiom_domain)
return ks_domain return ks_domain
@api.onchange('ks_domain_extension') @api.onchange('ks_domain_extension')
@ -1176,8 +1360,9 @@ class KsDashboardNinjaItems(models.Model):
rec.ks_goal_lines = False rec.ks_goal_lines = False
rec.ks_goal_enable = False rec.ks_goal_enable = False
rec.ks_fill_temporal = False rec.ks_fill_temporal = False
rec.ks_as_of_now = False
@api.onchange('ks_chart_relation_sub_groupby', 'ks_fill_temporal', 'ks_goal_lines') @api.onchange('ks_chart_relation_sub_groupby', 'ks_fill_temporal','ks_as_of_now', 'ks_goal_lines')
def ks_empty_limit(self): def ks_empty_limit(self):
for rec in self: for rec in self:
if rec.ks_chart_relation_sub_groupby or rec.ks_fill_temporal or rec.ks_goal_lines: if rec.ks_chart_relation_sub_groupby or rec.ks_fill_temporal or rec.ks_goal_lines:
@ -1185,6 +1370,7 @@ class KsDashboardNinjaItems(models.Model):
if rec.ks_chart_relation_sub_groupby: if rec.ks_chart_relation_sub_groupby:
rec.ks_chart_cumulative_field = False rec.ks_chart_cumulative_field = False
rec.ks_fill_temporal = False rec.ks_fill_temporal = False
rec.ks_as_of_now = False
# @api.onchange('ks_chart_cumulative_field') # @api.onchange('ks_chart_cumulative_field')
# def ks_onchange_cumutive(self): # def ks_onchange_cumutive(self):
@ -1292,11 +1478,11 @@ class KsDashboardNinjaItems(models.Model):
ks_chart_data['datasets'].append( ks_chart_data['datasets'].append(
{'data': [], 'label': rec.ks_chart_cumulative_field[res].field_description, {'data': [], 'label': rec.ks_chart_cumulative_field[res].field_description,
'ks_chart_cumulative_field': True}) 'ks_chart_cumulative_field': True, 'ks_as_of_now': rec.ks_as_of_now})
else: else:
ks_chart_data['datasets'].append( ks_chart_data['datasets'].append(
{'data': [], 'label': rec.ks_chart_measure_field[res].field_description, {'data': [], 'label': rec.ks_chart_measure_field[res].field_description,
'ks_chart_cumulative_field': False}) 'ks_chart_cumulative_field': False, 'ks_as_of_now': rec.ks_as_of_now})
# ks_chart_measure_field = [res.name for res in rec.ks_chart_measure_field] # ks_chart_measure_field = [res.name for res in rec.ks_chart_measure_field]
ks_chart_groupby_relation_field = rec.ks_chart_relation_groupby.name ks_chart_groupby_relation_field = rec.ks_chart_relation_groupby.name
@ -1309,6 +1495,8 @@ class KsDashboardNinjaItems(models.Model):
if rec.ks_sort_by_order: if rec.ks_sort_by_order:
orderby = orderby + " " + rec.ks_sort_by_order orderby = orderby + " " + rec.ks_sort_by_order
limit = rec.ks_record_data_limit if rec.ks_record_data_limit and rec.ks_record_data_limit > 0 else 5000 limit = rec.ks_record_data_limit if rec.ks_record_data_limit and rec.ks_record_data_limit > 0 else 5000
if rec.ks_as_of_now:
limit=5000
if ((rec.ks_chart_data_count_type != "count" and ks_chart_measure_field) or ( if ((rec.ks_chart_data_count_type != "count" and ks_chart_measure_field) or (
rec.ks_chart_data_count_type == "count" and not ks_chart_measure_field)) \ rec.ks_chart_data_count_type == "count" and not ks_chart_measure_field)) \
@ -1467,6 +1655,7 @@ class KsDashboardNinjaItems(models.Model):
ks_goal_datasets = { ks_goal_datasets = {
'label': 'Target', 'label': 'Target',
'data': goal_dataset, 'data': goal_dataset,
'ks_as_of_now': False
} }
if rec.ks_goal_bar_line: if rec.ks_goal_bar_line:
ks_goal_datasets['type'] = 'line' ks_goal_datasets['type'] = 'line'
@ -1659,12 +1848,13 @@ class KsDashboardNinjaItems(models.Model):
xlabels = [] xlabels = []
series = [] series = []
values = {} values = {'ks_sub_domain': {}}
domains = {} domains = {}
for data in chart_data: for data in chart_data:
label = data['labels'] label = data['labels']
serie = data['series'] serie = data['series']
domain = data['domain'] domain = data['domain']
ks_sub_group_domain = data['domain'].copy()
if (len(xlabels) == 0) or (label not in xlabels): if (len(xlabels) == 0) or (label not in xlabels):
xlabels.append(label) xlabels.append(label)
@ -1679,12 +1869,16 @@ class KsDashboardNinjaItems(models.Model):
value = data['value'] value = data['value']
counter = 0 counter = 0
for seri in serie: for seri in serie:
if seri not in values: if seri not in values:
values[seri] = {} values[seri] = {'ks_sub_domain': {}}
if label in values[seri]: if label in values[seri]:
values[seri][label] = values[seri][label] + value[counter] values[seri][label] = values[seri][label] + value[counter]
values[seri]['ks_sub_domain'][label] = ks_sub_group_domain
else: else:
values[seri][label] = value[counter] values[seri][label] = value[counter]
values[seri]['ks_sub_domain'][label] = ks_sub_group_domain
counter += 1 counter += 1
final_datasets = [] final_datasets = []
@ -1696,13 +1890,15 @@ class KsDashboardNinjaItems(models.Model):
for dataset in final_datasets: for dataset in final_datasets:
ks_dataset = { ks_dataset = {
'value': [], 'value': [],
'key': dataset 'key': dataset,
} }
for label in xlabels: for label in xlabels:
ks_dataset['value'].append({ ks_dataset['value'].append({
'domain': domains[label], 'domain': domains[label],
'x': label, 'x': label,
'y': values[dataset][label] if label in values[dataset] else 0 'y': values[dataset][label] if label in values[dataset] else 0,
'ks_sub_domain': values[dataset]['ks_sub_domain'][label] if values[dataset].get('ks_sub_domain', False) and values[dataset]['ks_sub_domain'].get(label, False) else []
}) })
ks_data.append(ks_dataset) ks_data.append(ks_dataset)
@ -1735,22 +1931,25 @@ class KsDashboardNinjaItems(models.Model):
ks_chart_data['domains'].append(res['domain']) ks_chart_data['domains'].append(res['domain'])
if rec.ks_chart_measure_field_2 and rec.ks_dashboard_item_type == 'ks_bar_chart': if rec.ks_chart_measure_field_2 and rec.ks_dashboard_item_type == 'ks_bar_chart':
ks_chart_data['ks_show_second_y_scale'] = True ks_chart_data['ks_show_second_y_scale'] = True
values_2 = {} values_2 = {'ks_sub_domain': {}}
series_2 = [] series_2 = []
for data in chart_sub_data: for data in chart_sub_data:
label = data['labels'] label = data['labels']
serie = data['series'] serie = data['series']
series_2 = series_2 + serie series_2 = series_2 + serie
value = data['value'] value = data['value']
ks_sub_domain = data['domain'].copy()
counter = 0 counter = 0
for seri in serie: for seri in serie:
if seri not in values_2: if seri not in values_2:
values_2[seri] = {} values_2[seri] = {'ks_sub_domain': {}}
if label in values_2[seri]: if label in values_2[seri]:
values_2[seri][label] = values_2[seri][label] + value[counter] values_2[seri][label] = values_2[seri][label] + value[counter]
values_2[seri]['ks_sub_domain'][label] = ks_sub_domain
else: else:
values_2[seri][label] = value[counter] values_2[seri][label] = value[counter]
values_2[seri]['ks_sub_domain'][label] = ks_sub_domain
counter += 1 counter += 1
final_datasets_2 = [] final_datasets_2 = []
for serie in series_2: for serie in series_2:
@ -1760,12 +1959,13 @@ class KsDashboardNinjaItems(models.Model):
for dataset in final_datasets_2: for dataset in final_datasets_2:
ks_dataset = { ks_dataset = {
'value': [], 'value': [],
'key': dataset 'key': dataset,
} }
for label in xlabels: for label in xlabels:
ks_dataset['value'].append({ ks_dataset['value'].append({
'x': label, 'x': label,
'y': values_2[dataset][label] if label in values_2[dataset] else 0 'y': values_2[dataset][label] if label in values_2[dataset] else 0,
'ks_sub_domain': values_2[dataset]['ks_sub_domain'][label] if values_2[dataset].get('ks_sub_domain', False) and values_2[dataset]['ks_sub_domain'].get(label, False) else []
}) })
ks_data_2.append(ks_dataset) ks_data_2.append(ks_dataset)
@ -1774,20 +1974,25 @@ class KsDashboardNinjaItems(models.Model):
'label': ks_dat['key'], 'label': ks_dat['key'],
'data': [], 'data': [],
'type': 'line', 'type': 'line',
'yAxisID': 'y-axis-1' 'yAxisID': 'y-axis-1',
'ks_sub_domain': []
} }
for res in ks_dat['value']: for res in ks_dat['value']:
dataset['data'].append(res['y']) dataset['data'].append(res['y'])
dataset['ks_sub_domain'].append(
res['ks_sub_domain'] if res.get('ks_sub_domain', False) else [])
ks_chart_data['datasets'].append(dataset) ks_chart_data['datasets'].append(dataset)
for ks_dat in ks_data: for ks_dat in ks_data:
dataset = { dataset = {
'label': ks_dat['key'], 'label': ks_dat['key'],
'data': [] 'data': [],
'ks_sub_domain': []
} }
for res in ks_dat['value']: for res in ks_dat['value']:
dataset['data'].append(res['y']) dataset['data'].append(res['y'])
dataset['ks_sub_domain'].append(res['ks_sub_domain'] if res.get('ks_sub_domain',False) else [])
ks_chart_data['datasets'].append(dataset) ks_chart_data['datasets'].append(dataset)
@ -1800,6 +2005,7 @@ class KsDashboardNinjaItems(models.Model):
ks_goal_datasets = { ks_goal_datasets = {
'label': 'Target', 'label': 'Target',
'data': goal_dataset, 'data': goal_dataset,
'ks_as_of_now': False
} }
if rec.ks_goal_bar_line and rec.ks_dashboard_item_type != 'ks_horizontalBar_chart': if rec.ks_goal_bar_line and rec.ks_dashboard_item_type != 'ks_horizontalBar_chart':
ks_goal_datasets['type'] = 'line' ks_goal_datasets['type'] = 'line'
@ -1811,11 +2017,15 @@ class KsDashboardNinjaItems(models.Model):
if self.ks_multiplier_active: if self.ks_multiplier_active:
for ks_multiplier in self.ks_multiplier_lines: for ks_multiplier in self.ks_multiplier_lines:
for i in range(0, len(ks_chart_data['datasets'])): for i in range(0, len(ks_chart_data['datasets'])):
if ks_multiplier.ks_multiplier_fields.field_description in ks_chart_data['datasets'][i][ try:
'label']: if ks_multiplier.ks_multiplier_fields.field_description != False and ks_multiplier.ks_multiplier_fields.field_description in \
data_values = ks_chart_data['datasets'][i]['data'] ks_chart_data['datasets'][i][
data_values = list(map(lambda x: ks_multiplier.ks_multiplier_value * x, data_values)) 'label']:
ks_chart_data['datasets'][i]['data'] = data_values data_values = ks_chart_data['datasets'][i]['data']
data_values = list(map(lambda x: ks_multiplier.ks_multiplier_value * x, data_values))
ks_chart_data['datasets'][i]['data'] = data_values
except Exception as e:
raise ValidationError('JSON file not supported.')
# res_list = [i for n, i in enumerate(ks_chart_data.get('datasets',[])) if i not in ks_chart_data.get('datasets',[])[n + 1:]] # res_list = [i for n, i in enumerate(ks_chart_data.get('datasets',[])) if i not in ks_chart_data.get('datasets',[])[n + 1:]]
# ks_chart_data['datasets'] = res_list # ks_chart_data['datasets'] = res_list
return json.dumps(ks_chart_data) return json.dumps(ks_chart_data)
@ -2335,6 +2545,7 @@ class KsDashboardNinjaItems(models.Model):
rec.ks_chart_cumulative = False rec.ks_chart_cumulative = False
rec.ks_multiplier_active = False rec.ks_multiplier_active = False
rec.ks_model_id_2 = False rec.ks_model_id_2 = False
rec.ks_chart_measure_field_2 = False
if rec.ks_dashboard_item_type == 'ks_to_do': if rec.ks_dashboard_item_type == 'ks_to_do':
rec.ks_model_id_2 = False rec.ks_model_id_2 = False
rec.ks_model_id = False rec.ks_model_id = False
@ -2351,9 +2562,32 @@ class KsDashboardNinjaItems(models.Model):
rec.ks_item_start_date = ks_date_data["selected_start_date"] rec.ks_item_start_date = ks_date_data["selected_start_date"]
rec.ks_item_end_date = ks_date_data["selected_end_date"] rec.ks_item_end_date = ks_date_data["selected_end_date"]
@api.depends('ks_dashboard_item_type', 'ks_record_count','ks_model_id','ks_multiplier','ks_multiplier_active','ks_unit', 'ks_unit_selection', 'ks_currency_id')
def ks_get_tile_data(self):
for rec in self:
rec.ks_tile_data = rec._ksGettileData(domain=[])
def _ksGettileData(self, domain=[]):
rec = self
if rec.ks_dashboard_item_type and rec.ks_dashboard_item_type == 'ks_tile' and rec.ks_model_id :
ks_tile_data = {'ks_currency': 0, 'ks_field': "", 'ks_selection': ""}
if rec.ks_unit and rec.ks_unit_selection == 'monetary':
ks_tile_data['ks_selection'] += rec.ks_unit_selection
ks_tile_data['ks_currency'] += rec.env.user.company_id.currency_id.id
elif rec.ks_unit and rec.ks_unit_selection == 'custom':
ks_tile_data['ks_selection'] += rec.ks_unit_selection
if rec.ks_currency_id:
ks_tile_data['ks_field'] += rec.ks_currency_id.symbol
return json.dumps(ks_tile_data)
else:
return False
@api.depends('ks_dashboard_item_type', 'ks_goal_enable', 'ks_standard_goal_value', 'ks_record_count', @api.depends('ks_dashboard_item_type', 'ks_goal_enable', 'ks_standard_goal_value', 'ks_record_count',
'ks_record_count_2', 'ks_previous_period', 'ks_compare_period', 'ks_year_period', 'ks_record_count_2', 'ks_previous_period', 'ks_compare_period', 'ks_year_period',
'ks_compare_period_2', 'ks_year_period_2', 'ks_domain_extension_2') 'ks_compare_period_2', 'ks_year_period_2', 'ks_domain_extension_2','ks_unit','ks_unit_selection','ks_currency_id')
def ks_get_kpi_data(self): def ks_get_kpi_data(self):
for rec in self: for rec in self:
rec.ks_kpi_data = rec._ksGetKpiData(domain1=[], domain2=[]) rec.ks_kpi_data = rec._ksGetKpiData(domain1=[], domain2=[])
@ -2364,11 +2598,22 @@ class KsDashboardNinjaItems(models.Model):
ks_kpi_data = [] ks_kpi_data = []
ks_record_count = 0.0 ks_record_count = 0.0
ks_kpi_data_model_1 = {} ks_kpi_data_model_1 = {}
ks_kpi_data_model_1 = {'ks_currency': 0, 'ks_field': "", 'ks_selection': ""}
ks_record_count = rec._ksGetRecordCount(domain1) ks_record_count = rec._ksGetRecordCount(domain1)
ks_kpi_data_model_1['model'] = rec.ks_model_name ks_kpi_data_model_1['model'] = rec.ks_model_name
ks_kpi_data_model_1['record_field'] = rec.ks_record_field.field_description ks_kpi_data_model_1['record_field'] = rec.ks_record_field.field_description
ks_kpi_data_model_1['record_data'] = ks_record_count ks_kpi_data_model_1['record_data'] = ks_record_count
if rec.ks_unit and rec.ks_unit_selection == 'monetary':
ks_kpi_data_model_1['ks_selection'] += rec.ks_unit_selection
ks_kpi_data_model_1['ks_currency'] += rec.env.user.company_id.currency_id.id
elif rec.ks_unit and rec.ks_unit_selection == 'custom':
ks_kpi_data_model_1['ks_selection'] += rec.ks_unit_selection
if rec.ks_currency_id:
ks_kpi_data_model_1['ks_field'] += rec.ks_currency_id.symbol
if rec.ks_goal_enable: if rec.ks_goal_enable:
ks_kpi_data_model_1['target'] = rec.ks_standard_goal_value ks_kpi_data_model_1['target'] = rec.ks_standard_goal_value
ks_kpi_data.append(ks_kpi_data_model_1) ks_kpi_data.append(ks_kpi_data_model_1)
@ -2609,17 +2854,17 @@ class KsDashboardNinjaItems(models.Model):
if selected_start_date and selected_end_date: if selected_start_date and selected_end_date:
if rec.ks_compare_period_2: if rec.ks_compare_period_2:
ks_compare_period_2 = abs(rec.ks_compare_period_2) ks_compare_period_2 = abs(rec.ks_compare_period_2)
if ks_compare_period_2 > 100: if ks_compare_period_2 > 100 and rec.ks_date_filter_selection_2.split('_')[1] != 'day':
ks_compare_period_2 = 100 ks_compare_period_2 = 100
if rec.ks_compare_period_2 > 0: if rec.ks_compare_period_2 > 0:
selected_end_date = selected_end_date + ( selected_end_date = selected_end_date + (
selected_end_date - selected_start_date) * ks_compare_period_2 selected_end_date - selected_start_date) * ks_compare_period_2
if rec.ks_date_filter_field.ttype == "date" and rec.ks_date_filter_selection == 'l_day': if rec.ks_date_filter_field_2.ttype == "date" and rec.ks_date_filter_selection_2 == 'l_day':
selected_end_date = selected_end_date + timedelta(days=ks_compare_period_2) selected_end_date = selected_end_date + timedelta(days=ks_compare_period_2)
elif rec.ks_compare_period_2 < 0: elif rec.ks_compare_period_2 < 0:
selected_start_date = selected_start_date - ( selected_start_date = selected_start_date - (
selected_end_date - selected_start_date) * ks_compare_period_2 selected_end_date - selected_start_date) * ks_compare_period_2
if rec.ks_date_filter_field.ttype == "date" and rec.ks_date_filter_selection == 'l_day': if rec.ks_date_filter_field_2.ttype == "date" and rec.ks_date_filter_selection_2 == 'l_day':
selected_start_date = selected_end_date - timedelta(days=ks_compare_period_2) selected_start_date = selected_end_date - timedelta(days=ks_compare_period_2)
if rec.ks_year_period_2 and rec.ks_year_period_2 != 0: if rec.ks_year_period_2 and rec.ks_year_period_2 != 0:
@ -2763,6 +3008,8 @@ class KsDashboardNinjaItems(models.Model):
continue continue
except ZeroDivisionError: except ZeroDivisionError:
data = 0 data = 0
# if data > 0:
ks_chart_data['datasets'][counter]['ks_sub_domain'] = [(field_rec, '!=', False)]
ks_chart_data['datasets'][counter]['data'].append(data) ks_chart_data['datasets'][counter]['data'].append(data)
counter += 1 counter += 1
index += 1 index += 1
@ -2792,6 +3039,9 @@ class KsDashboardNinjaItems(models.Model):
continue continue
except ZeroDivisionError: except ZeroDivisionError:
data = 0 data = 0
# if data > 0:
ks_chart_data['datasets'][counter]['ks_sub_domain'] = [(field_rec, '!=', False)]
ks_chart_data['datasets'][counter]['data'].append(data) ks_chart_data['datasets'][counter]['data'].append(data)
counter += 1 counter += 1
index += 1 index += 1

View File

@ -1,15 +1,18 @@
import base64 import base64
import logging import logging
from odoo import api, fields, models,_ from odoo import api, fields, models, _
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class KsDashboardNInjaImport(models.TransientModel): class KsDashboardNInjaImport(models.TransientModel):
_name = 'ks_dashboard_ninja.import' _name = 'ks_dashboard_ninja.import'
_description = 'Import Dashboard' _description = 'Import Dashboard'
ks_import_dashboard = fields.Binary(string="Upload Dashboard", attachment=True) ks_import_dashboard = fields.Binary(string="Upload Dashboard", attachment=True)
ks_top_menu_id = fields.Many2one('ir.ui.menu', string="Show Under Menu", required=True, ks_top_menu_id = fields.Many2one('ir.ui.menu', domain="[('parent_id','=',False)]", string="Show Under Menu",
required=True,
default=lambda self: self.env['ir.ui.menu'].search( default=lambda self: self.env['ir.ui.menu'].search(
[('name', '=', 'My Dashboard')])) [('name', '=', 'My Dashboard')]))

View File

@ -0,0 +1,31 @@
import base64
import logging
import requests
import json
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
class KsAIDashboardFetch(models.TransientModel):
_name = 'ks_dashboard_ninja.fetch_key'
_description = 'Fetch API key'
ks_email_id = fields.Char(String="Email ID")
ks_api_key =fields.Char(string="Generated AI API Key")
ks_show_api_key = fields.Boolean(string="Show key",default=False)
def ks_fetch_details(self):
url = self.env['ir.config_parameter'].sudo().get_param(
'ks_dashboard_ninja.url')
if url and self.ks_email_id:
url = url + "/api/v1/ks_dn_fetch_api"
json_data = {'email':self.ks_email_id}
ks_ai_response = requests.post(url,data=json_data)
if ks_ai_response.status_code == 200:
ks_ai_response = json.loads(ks_ai_response.text)
self.ks_api_key = ks_ai_response
self.ks_show_api_key = True
else:
raise ValidationError(_("Error generates with following status %s"),ks_ai_response.status_code)

View File

@ -1,21 +1,14 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
import operator
import re
from odoo import api, fields, models, tools, _ from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError
from odoo.http import request
from odoo.modules import get_module_resource
class KSIrUiMenu(models.Model): class ResCompany(models.Model):
_inherit = "ir.ui.menu" _inherit = 'res.company'
def ksMenu(self, ks_xml_id): def ks_check_is_enterprise(self):
ks_temp = False
print("@@@@@@@@@@@@@@@@@@@@@@@@@") if len(self.env['ir.module.module'].sudo().search([('name', '=', 'web_enterprise')]))>0 \
return self.env['ir.ui.menu'].search([('id','=',72)]).child_id[12].action.id and self.env['ir.module.module'].sudo().search([('name', '=', 'web_enterprise')],limit=1).state == \
'installed':
ks_temp = True
return ks_temp

View File

@ -0,0 +1,49 @@
from odoo import api, fields, models,_
from odoo.exceptions import ValidationError
import requests
import json
class ResConfig(models.TransientModel):
_inherit = "res.config.settings"
dn_api_key = fields.Char(string="Dashboard AI API Key",store=True,
config_parameter='ks_dashboard_ninja.dn_api_key')
url = fields.Char(string="URL", store=True,
config_parameter="ks_dashboard_ninja.url")
ks_email_id = fields.Char(string="Email ID",store=True,config_parameter="ks_dashboard_ninja.ks_email_id")
def Open_wizard(self):
if self.url and self.ks_email_id:
try:
url = self.url + "/api/v1/ks_dn_fetch_api"
json_data = {'email':self.ks_email_id,
'url':self.env['ir.config_parameter'].sudo().get_param('web.base.url'),
'db_name':self.env.cr.dbname
}
ks_ai_response = requests.post(url,data=json_data)
except Exception as e:
raise ValidationError(_("Please enter correct URL"))
if ks_ai_response.status_code == 200:
try:
ks_ai_response = json.loads(ks_ai_response.text)
except Exception as e:
ks_ai_response = False
if ks_ai_response == "success":
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': 'API key sent on Email ID',
'sticky': False,
}
}
elif ks_ai_response == 'key already generated':
raise ValidationError(
_("key already generated.If you need assistance, feel free to contact at sales@ksolves.com"))
else:
raise ValidationError(_("Either you have entered wrong URL path or there is some problem in sending request. If you need assistance, feel free to contact at sales@ksolves.com"))
else:
raise ValidationError(_("Some problem in sending request.Please contact at sales@ksolves.com"))
else:
raise ValidationError(_("Please enter URL and Email ID"))

View File

@ -22,4 +22,7 @@ access_ks_dashboard_ninja_ks_grid_per_company,ks_dashboard_ninja.ks_grid_per_com
access_ks_dashboard_wizard,access_ks_dashboard_wizard,model_ks_dashboard_wizard,,1,1,1,1 access_ks_dashboard_wizard,access_ks_dashboard_wizard,model_ks_dashboard_wizard,,1,1,1,1
access_ir_model_ks_duplicate_dashboard_wizard,ks_duplicate_dashboard__wizard,model_ks_dashboard_duplicate_wizard,,1,1,1,1 access_ir_model_ks_duplicate_dashboard_wizard,ks_duplicate_dashboard__wizard,model_ks_dashboard_duplicate_wizard,,1,1,1,1
access_ir_model_ks_delete_dashboard_wizard,ks_delete_dashboard__wizard,model_ks_dashboard_delete_wizard,,1,1,1,1 access_ir_model_ks_delete_dashboard_wizard,ks_delete_dashboard__wizard,model_ks_dashboard_delete_wizard,,1,1,1,1
access_ks_dashboard_ninja_arti_int,ks_dashboard_ninja.arti_int,model_ks_dashboard_ninja_arti_int,,1,1,1,1
access_ks_dashboard_ninja_ai_dashboard,ks_dashboard_ninja.ai_dashboard,model_ks_dashboard_ninja_ai_dashboard,,1,1,1,1
access_ks_dashboard_ninja_fetch_key,ks_dashboard_ninja.fetch_key,model_ks_dashboard_ninja_fetch_key,,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
22 access_ir_model_ks_delete_dashboard_wizard ks_delete_dashboard__wizard model_ks_dashboard_delete_wizard 1 1 1 1
23 access_ks_dashboard_ninja_arti_int ks_dashboard_ninja.arti_int model_ks_dashboard_ninja_arti_int 1 1 1 1
24 access_ks_dashboard_ninja_ai_dashboard ks_dashboard_ninja.ai_dashboard model_ks_dashboard_ninja_ai_dashboard 1 1 1 1
25 access_ks_dashboard_ninja_fetch_key ks_dashboard_ninja.fetch_key model_ks_dashboard_ninja_fetch_key 1 1 1 1
26
27
28

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 528 KiB

View File

@ -0,0 +1,4 @@
<svg width="41" height="41" viewBox="0 0 41 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="20.5" cy="20.5" r="20" stroke="black"/>
<path d="M15.6333 26.3417L9.15833 19.8667L7 22.025L15.6333 30.6583L34.1333 12.1583L31.975 10L15.6333 26.3417Z" fill="#F04F65"/>
</svg>

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,26 @@
.ks_new_tag{
position: absolute;
font-size: 6px;
background: #71639e;
padding: 2px 6px;
margin: 0px;
border-radius: 4px;
color: white;
font-weight: 600;
text-transform: uppercase;
margin-right: 6px;
letter-spacing: 0.5px;
margin-top: -4px;
margin-left: 6px;
}
.ks_img_selected{
background:#f2f2f2;
}
.ks_dashboard_kpi_dashboard .ks_img_display{
display: block;
margin-left: auto;
margin-top: -7em
}
.modal-body .ks_dashboard_header_sticky{
top:-20px !important;
}

View File

@ -624,3 +624,16 @@ ul.nav li.dropdown:hover ul.dropdown-menu{ display: block; }
} }
.ks_global_filter_padding {
padding:10px;
}
.ks_qe_form_view span.o_field_translate.btn.btn-link {
display:none;
}
.ks_dn_separator {
background: #b9d4de;
padding: 5px;
font-size: 13px;
}

View File

@ -197,7 +197,7 @@ table#ksListViewTable {
.ks_date_filters_menu_drop_down { .ks_date_filters_menu_drop_down {
max-height: 300px !important; max-height: 270px !important;
overflow: auto !important; overflow: auto !important;
background-clip:unset; background-clip:unset;
} }

View File

@ -14,6 +14,7 @@
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
flex-wrap: wrap; flex-wrap: wrap;
margin-top: -1px;
} }
i.ks-options-plus { i.ks-options-plus {
color: white; color: white;
@ -65,6 +66,10 @@ i.ks-options-plus {
text-align: start; text-align: start;
} }
.ks_dashboard_header{
height: 55px;
}
.ks-dashboard-date-labels{ .ks-dashboard-date-labels{
font-weight: bold; font-weight: bold;
margin-top: inherit; margin-top: inherit;
@ -80,3 +85,7 @@ i.ks-options-plus {
.ks_event_offer_list:focus { .ks_event_offer_list:focus {
box-shadow: none; box-shadow: none;
} }
ul#ks_date_selector_container {
transform: translate3d(0px, 31px, 0px) !important;
}

View File

@ -0,0 +1,125 @@
.input_bar{
border-radius: 8px;
border: 0.5px solid #DADADA;
background: #FF;
color: #A8A8A8 !important;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
height: 40px;
padding-left: 24px !important;
}
input#ks_selection_field:focus {
border: 1px solid #797979;
}
.ks_input_custom{
position: relative;
}
.ks_input_custom svg{
position: absolute;
right: 0px;
top: 9px;
}
.search_style{
text-align:center;
font-size:14px;
color: #444;
border-radius: 5px;
}
.search_style{
overflow-y: scroll;
max-height: calc(100vh - 400px);
}
.search_style::-webkit-scrollbar {
width: 6px;
}
/* Track */
.search_style::-webkit-scrollbar-track {
background: transparent;
}
/* Handle */
.search_style::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
.search_style::-webkit-scrollbar-thumb:hover {
background: #555;
}
.ks_response_container_list{
border-bottom: 1px solid #d4d4d4;
border-left: 1px solid transparent;
padding: 17px 6px 18px 24px;
background-color: #fff;
color: #A8A8A8;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.ks_response_container_list:hover{
color: #9C5789;
border-left: 2px solid #9C5789;
}
.ks_response_container_list:hover svg path{
stroke: #9C5789;
}
.ks_response_container_list:hover svg line{
stroke: #9C5789;
}
.ks_dashboard_option_category span.ks_dashboard_option{
color: #9C5789;
height: 21px;
padding: 3px;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.ks_dashboard_option_category span{
display: flex;
align-items: center;
justify-content: start;
width: fit-content;
font-size: 8px;
background: #EEE;
padding: 0px 10px;
margin: 0px;
border-radius: 4px;
color: #888;
font-weight: 600;
text-transform: uppercase;
margin-right: 6px;
letter-spacing: 0.5px;
margin-top: 0px;
}
.ks_dashboard_ai_chart_icons{
display: flex;
align-items: center;
justify-content: start;
width: fit-content;
padding: 0px 10px;
margin: 0px;
font-weight: 600;
margin-top: 0px;
}
.ks_border_class{
border-radius: 8px !important;
border: 1px solid #DADADA !important;
background: #FFF !important;
margin-top: 8px !important;
height: 40px !important;
padding: 11px 11px 11px 24px !important;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.ks_border_class .ks_response{
width: 100%;
}

View File

@ -103,4 +103,48 @@ border-top: 1px solid #dcdada;
.ks_quick_edit_footer > .ks_discard { .ks_quick_edit_footer > .ks_discard {
border-color: #dee2e6; border-color: #dee2e6;
} }
@media(min-width: 768px){
.ks_dashboard_item_hover .ks_dashboard_item_header_hover > .dn-setting-panel{
visibility: hidden;
}
.ks_dashboard_item_hover:hover .ks_dashboard_item_header_hover > .dn-setting-panel{
visibility: visible;
}
}
@media(max-width: 1000px){
.ks_dashboard_header {
height: 145px !important;
}
.ks_dashboard_top_menu{
margin-top: -6px;
}
}
@media(max-width: 767.8px){
.ks_dashboard_item_name{
font-size: 16px;
}
.ks_dashboard_item_hover .ks_dashboard_item_header_hover > .dn-setting-panel button {
background: transparent;
}
a.dropdown-item.ks_dashboard_item_chart_info.d-none {
display: block !important;
}
.ks_dashboard_item_fa_con {
display: none !important;
}
}
.ks_chart_inner_min_width {
min-width: 14rem;
}
.ks_info_display {
display: block !important;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,23 +2,12 @@ odoo.define('ks_dashboard_ninja.kscontroller', function (require) {
"use strict"; "use strict";
var core = require('web.core'); var core = require('web.core');
var ajax = require('web.ajax');
var QWeb = core.qweb;
var session = require('web.session');
var Dialog = require('web.Dialog');
var fieldUtils = require('web.field_utils');
var AbstractAction = require('web.AbstractAction');
var ListController = require('web.ListController');
var framework = require('web.framework');
var view_registry = require('web.view_registry');
var dom = require('web.dom'); var dom = require('web.dom');
var ListView = require('web.ListView');
var FormController =require('web.FormController');
var _t = core._t; var _t = core._t;
const { bus } = require('web.core'); const { bus } = require('web.core');
const WebClient = require('web.WebClient'); const WebClient = require('web.WebClient');
const ksMenus = require('web.Menu'); const ksMenus = require('web.Menu');
var ListView = require('web.ListRenderer');
WebClient.include({ WebClient.include({
@ -63,5 +52,5 @@ odoo.define('ks_dashboard_ninja.kscontroller', function (require) {
}); });
return ListController;
}); });

View File

@ -0,0 +1,61 @@
odoo.define('ks_dashboard_ninja.kscontroller_en', function (require) {
"use strict";
var core = require('web.core');
var dom = require('web.dom');
var _t = core._t;
const { bus } = require('web.core');
const WebClient = require('web.WebClient');
const ksMenus = require('web_enterprise.Menu');
WebClient.include({
events: _.extend({}, WebClient.prototype.events, {
'ks_reload_menu_data': '_ksonReloadMenuData',
}),
custom_events: _.extend({}, WebClient.prototype.custom_events, {
'ks_reload_menu_data': '_ksonReloadMenuData',
}),
_ksonReloadMenuData: async function (ev={}) {
var current_primary_menu =0;
if ('ks_menu' in ev.data){
current_primary_menu = ev.data.ks_menu
}
else{
current_primary_menu = this.menu.current_primary_menu;
}
bus.trigger('clear_cache');
const menuData = await this.load_menus();
await this._ksreinstanciateMenu(menuData);
this.menu.change_menu_section(current_primary_menu);
},
_ksreinstanciateMenu: async function (newMenuData) {
const oldMenu = this.menu;
this.menu = new ksMenus(this, newMenuData)
await this.menu.appendTo(document.createDocumentFragment());
dom.prepend(this.$el, this.menu.$el, {
callbacks: [{ widget: this.menu }],
in_DOM: true,
});
if (oldMenu) {
oldMenu.destroy();
}
this.el.prepend(this.menu.el);
},
});
});

View File

@ -19,7 +19,7 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_item_theme', function(require)
_render: function() { _render: function() {
var self = this; var self = this;
self.$el.empty(); self.$el.empty();
var $view = $(QWeb.render('ks_dashboard_theme_view')); var $view = $(QWeb.render('ks_dashboard_theme_view',{widget: this}));
if (self.value) { if (self.value) {
$view.find("input[value='" + self.value + "']").prop("checked", true); $view.find("input[value='" + self.value + "']").prop("checked", true);
} }

View File

@ -42,7 +42,12 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_graph_preview', function(requi
Chart.plugins.unregister(ChartDataLabels); Chart.plugins.unregister(ChartDataLabels);
return this._super(); return this._super();
}, },
on_attach_callback: function() {
var self = this;
$.when(self.ks_set_default_chart_view()).then(function(result){
self.renderChart();
});
},
ks_set_default_chart_view: function() { ks_set_default_chart_view: function() {
Chart.plugins.register({ Chart.plugins.register({
afterDraw: function(chart) { afterDraw: function(chart) {
@ -129,6 +134,46 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_graph_preview', function(requi
} }
} }
} }
if (field.ks_as_of_now){
for (var i=0; i< this.chart_data.datasets.length; i++){
if (this.chart_data.datasets[i].ks_as_of_now){
var ks_temp_com = 0
var data = []
var datasets = {}
for (var j=0; j < this.chart_data.datasets[i].data.length; j++)
{
ks_temp_com = ks_temp_com + this.chart_data.datasets[i].data[j];
data.push(ks_temp_com);
}
this.chart_data.datasets[i].data = data.slice(-field.ks_record_data_limit)
}else{
this.chart_data.datasets[i].data = this.chart_data.datasets[i].data.slice(-field.ks_record_data_limit)
}
}
this.chart_data['labels'] = this.chart_data['labels'].slice(-field.ks_record_data_limit)
}
if (field.ks_chart_is_cumulative && field.ks_chart_data_count_type == 'count' && field.ks_dashboard_item_type === 'ks_bar_chart'){
var ks_temp_com = 0
var data = []
var datasets = {}
for (var j=0; j < this.chart_data.datasets[0].data.length; j++)
{
ks_temp_com = ks_temp_com + this.chart_data.datasets[0].data[j];
data.push(ks_temp_com);
}
datasets.label = 'Cumulative' + this.chart_data.datasets[0].label;
datasets.data = data;
if (field.ks_chart_cumulative){
datasets.type = 'line';
}
this.chart_data.datasets.push(datasets);
}
var $chartContainer = $(QWeb.render('ks_chart_form_view_container', { var $chartContainer = $(QWeb.render('ks_chart_form_view_container', {
ks_chart_name: ks_chart_name ks_chart_name: ks_chart_name
@ -255,6 +300,22 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_graph_preview', function(requi
sum += data; sum += data;
}); });
let percentage = sum === 0 ? 0 + "%" : (value * 100 / sum).toFixed(2) + "%"; let percentage = sum === 0 ? 0 + "%" : (value * 100 / sum).toFixed(2) + "%";
if(self.recordData.ks_data_label_type == 'value'){
percentage = value;
var ks_self = self;
var ks_selection = self.chart_data.ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = self.chart_data.ks_currency;
var ks_data = KsGlobalFunction._onKsGlobalFormatter(value, self.recordData.ks_data_format, self.recordData.ks_precision_digits);
ks_data = KsGlobalFunction.ks_monetary(ks_data, ks_currency_id);
percentage = ks_data;
} else if (ks_selection === 'custom') {
var ks_field = self.chart_data.ks_field;
percentage = KsGlobalFunction._onKsGlobalFormatter(value, self.recordData.ks_data_format, self.recordData.ks_precision_digits) + ' ' + ks_field;
}else {
percentage = KsGlobalFunction._onKsGlobalFormatter(value, self.recordData.ks_data_format, self.recordData.ks_precision_digits);
}
}
return percentage; return percentage;
}, },
}, },
@ -270,6 +331,45 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_graph_preview', function(requi
ksHideFunction: function(options, recordData, ksChartFamily, chartType) { ksHideFunction: function(options, recordData, ksChartFamily, chartType) {
return options; return options;
}, },
ks_chart_color_pallet: function(gradient, setsCount, palette){
var chartColors = [];
var color_set = ['#F04F65', '#f69032', '#fdc233', '#53cfce', '#36a2ec', '#8a79fd', '#b1b5be', '#1c425c', '#8c2620', '#71ecef', '#0b4295', '#f2e6ce', '#1379e7'];
if (palette !== "default") {
//Get a sorted array of the gradient keys
var gradientKeys = Object.keys(gradient);
gradientKeys.sort(function(a, b) {
return +a - +b;
});
for (var i = 0; i < setsCount; i++) {
var gradientIndex = (i + 1) * (100 / (setsCount + 1)); //Find where to get a color from the gradient
for (var j = 0; j < gradientKeys.length; j++) {
var gradientKey = gradientKeys[j];
if (gradientIndex === +gradientKey) { //Exact match with a gradient key - just get that color
chartColors[i] = 'rgba(' + gradient[gradientKey].toString() + ')';
break;
} else if (gradientIndex < +gradientKey) { //It's somewhere between this gradient key and the previous
var prevKey = gradientKeys[j - 1];
var gradientPartIndex = (gradientIndex - prevKey) / (gradientKey - prevKey); //Calculate where
var color = [];
for (var k = 0; k < 4; k++) { //Loop through Red, Green, Blue and Alpha and calculate the correct color and opacity
color[k] = gradient[prevKey][k] - ((gradient[prevKey][k] - gradient[gradientKey][k]) * gradientPartIndex);
if (k < 3) color[k] = Math.round(color[k]);
}
chartColors[i] = 'rgba(' + color.toString() + ')';
break;
}
}
}
} else {
for (var i = 0, counter = 0; i < setsCount; i++, counter++) {
if (counter >= color_set.length) counter = 0; // reset back to the beginning
chartColors.push(color_set[counter]);
}
}
return chartColors;
},
ksChartColors: function(palette, ksMyChart, ksChartType, ksChartFamily, ks_show_data_value) { ksChartColors: function(palette, ksMyChart, ksChartType, ksChartFamily, ks_show_data_value) {
var self = this; var self = this;
@ -335,44 +435,44 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_graph_preview', function(requi
break; break;
} }
//Calculate colors // //Calculate colors
var chartColors = []; // var chartColors = [];
//
if (palette !== "default") { // if (palette !== "default") {
//Get a sorted array of the gradient keys // //Get a sorted array of the gradient keys
var gradientKeys = Object.keys(gradient); // var gradientKeys = Object.keys(gradient);
gradientKeys.sort(function(a, b) { // gradientKeys.sort(function(a, b) {
return +a - +b; // return +a - +b;
}); // });
for (var i = 0; i < setsCount; i++) { // for (var i = 0; i < setsCount; i++) {
var gradientIndex = (i + 1) * (100 / (setsCount + 1)); //Find where to get a color from the gradient // var gradientIndex = (i + 1) * (100 / (setsCount + 1)); //Find where to get a color from the gradient
for (var j = 0; j < gradientKeys.length; j++) { // for (var j = 0; j < gradientKeys.length; j++) {
var gradientKey = gradientKeys[j]; // var gradientKey = gradientKeys[j];
if (gradientIndex === +gradientKey) { //Exact match with a gradient key - just get that color // if (gradientIndex === +gradientKey) { //Exact match with a gradient key - just get that color
chartColors[i] = 'rgba(' + gradient[gradientKey].toString() + ')'; // chartColors[i] = 'rgba(' + gradient[gradientKey].toString() + ')';
break; // break;
} else if (gradientIndex < +gradientKey) { //It's somewhere between this gradient key and the previous // } else if (gradientIndex < +gradientKey) { //It's somewhere between this gradient key and the previous
var prevKey = gradientKeys[j - 1]; // var prevKey = gradientKeys[j - 1];
var gradientPartIndex = (gradientIndex - prevKey) / (gradientKey - prevKey); //Calculate where // var gradientPartIndex = (gradientIndex - prevKey) / (gradientKey - prevKey); //Calculate where
var color = []; // var color = [];
for (var k = 0; k < 4; k++) { //Loop through Red, Green, Blue and Alpha and calculate the correct color and opacity // for (var k = 0; k < 4; k++) { //Loop through Red, Green, Blue and Alpha and calculate the correct color and opacity
color[k] = gradient[prevKey][k] - ((gradient[prevKey][k] - gradient[gradientKey][k]) * gradientPartIndex); // color[k] = gradient[prevKey][k] - ((gradient[prevKey][k] - gradient[gradientKey][k]) * gradientPartIndex);
if (k < 3) color[k] = Math.round(color[k]); // if (k < 3) color[k] = Math.round(color[k]);
} // }
chartColors[i] = 'rgba(' + color.toString() + ')'; // chartColors[i] = 'rgba(' + color.toString() + ')';
break; // break;
} // }
} // }
} // }
} else { // } else {
for (var i = 0, counter = 0; i < setsCount; i++, counter++) { // for (var i = 0, counter = 0; i < setsCount; i++, counter++) {
if (counter >= color_set.length) counter = 0; // reset back to the beginning // if (counter >= color_set.length) counter = 0; // reset back to the beginning
//
chartColors.push(color_set[counter]); // chartColors.push(color_set[counter]);
} // }
//
} // }
var chartColors = this.ks_chart_color_pallet(gradient, setsCount, palette);
var datasets = ksMyChart.config.data.datasets; var datasets = ksMyChart.config.data.datasets;
var options = ksMyChart.config.options; var options = ksMyChart.config.options;

View File

@ -7,6 +7,7 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_item_preview', function(requir
var field_utils = require('web.field_utils'); var field_utils = require('web.field_utils');
var session = require('web.session'); var session = require('web.session');
var utils = require('web.utils'); var utils = require('web.utils');
var KsGlobalFunction = require('ks_dashboard_ninja.KsGlobalFunction');
var QWeb = core.qweb; var QWeb = core.qweb;
@ -194,6 +195,7 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_item_preview', function(requir
_render: function() { _render: function() {
var self = this; var self = this;
var field = self.recordData; var field = self.recordData;
this.tile_data = JSON.parse(field.ks_tile_data)
var $val; var $val;
var item_info; var item_info;
var ks_rgba_background_color, ks_rgba_font_color, ks_rgba_icon_color; var ks_rgba_background_color, ks_rgba_font_color, ks_rgba_icon_color;
@ -243,6 +245,27 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_item_preview', function(requir
item_info['count'] = self._onKsGlobalFormatter(field.ks_record_count, field.ks_data_format, field.ks_precision_digits); item_info['count'] = self._onKsGlobalFormatter(field.ks_record_count, field.ks_data_format, field.ks_precision_digits);
} }
if (field.ks_unit){
if (field.ks_multiplier_active){
var ks_record_count = field.ks_record_count * field.ks_multiplier
}else{
var ks_record_count = field.ks_record_count
}
var ks_selection = self.tile_data.ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = self.tile_data.ks_currency;
var ks_data = self._onKsGlobalFormatter(ks_record_count, field.ks_data_format, field.ks_precision_digits);
ks_data = KsGlobalFunction.ks_monetary(ks_data, ks_currency_id);
item_info['count'] = ks_data;
} else if (ks_selection === 'custom') {
var ks_field = self.tile_data.ks_field;
item_info['count']= ks_field+" "+self._onKsGlobalFormatter(ks_record_count, field.ks_data_format, field.ks_precision_digits);
}else {
item_info['count']= self._onKsGlobalFormatter(ks_record_count, field.ks_data_format, field.ks_precision_digits);
}
}
// count_tooltip // count_tooltip
switch (field.ks_layout) { switch (field.ks_layout) {

View File

@ -159,11 +159,40 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
var self = this; var self = this;
var count = count_1 + count_2 var count = count_1 + count_2
if (field.ks_multiplier_active){ if (field.ks_multiplier_active){
item_info['count'] = KsGlobalFunction._onKsGlobalFormatter(count* field.ks_multiplier, field.ks_data_format, field.ks_precision_digits); var data1 = KsGlobalFunction._onKsGlobalFormatter(count * field.ks_multiplier, field.ks_data_format, field.ks_precision_digits);
if (field.ks_unit){
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
data1 = KsGlobalFunction.ks_monetary(data1, ks_currency_id);
item_info['count'] = data1
} else if (ks_selection === 'custom') {
var ks_field = kpi_data[0].ks_field;
data1= ks_field+" "+data1
item_info['count']= data1
}
}else {
item_info['count']=KsGlobalFunction._onKsGlobalFormatter(count*field.ks_multiplier, field.ks_data_format, field.ks_precision_digits);
}
item_info['count_tooltip'] = field_utils.format.float(count * field.ks_multiplier, Float64Array, {digits: [0, field.ks_precision_digits]}); item_info['count_tooltip'] = field_utils.format.float(count * field.ks_multiplier, Float64Array, {digits: [0, field.ks_precision_digits]});
}else{ }else{
var data1 = KsGlobalFunction._onKsGlobalFormatter(count, field.ks_data_format, field.ks_precision_digits);
if (field.ks_unit){
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
data1 = KsGlobalFunction.ks_monetary(data1, ks_currency_id);
item_info['count'] = data1
} else if (ks_selection === 'custom') {
var ks_field = kpi_data[0].ks_field;
data1= ks_field+" "+data1
item_info['count']= data1
}
}else {
item_info['count']=KsGlobalFunction._onKsGlobalFormatter(count, field.ks_data_format, field.ks_precision_digits);
}
item_info['count_tooltip'] = field_utils.format.float(count * field.ks_multiplier, Float64Array, {digits: [0, field.ks_precision_digits]});
item_info['count'] = KsGlobalFunction._onKsGlobalFormatter(count, field.ks_data_format, field.ks_precision_digits, field.ks_precision_digits);
item_info['count_tooltip'] = field_utils.format.float(count, Float64Array, {digits: [0, field.ks_precision_digits]}); item_info['count_tooltip'] = field_utils.format.float(count, Float64Array, {digits: [0, field.ks_precision_digits]});
} }
if (field.ks_multiplier_active){ if (field.ks_multiplier_active){
@ -195,14 +224,24 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
count_1 = count_1 * field.ks_multiplier; count_1 = count_1 * field.ks_multiplier;
count_2 = count_2 * field.ks_multiplier; count_2 = count_2 * field.ks_multiplier;
} }
var count = parseInt((count_1 / count_2) * 100); if (field.ks_data_format == 'exact'){
if (field.ks_multiplier_active){ // var count = parseInt((count_1 / count_2) * 100);
count = count * field.ks_multiplier; var tool_tip = (count_1 / count_2) * 100
var count = field_utils.format.float((count_1 / count_2) * 100, Float64Array,{digits: [0, field.ks_precision_digits]});
if (field.ks_multiplier_active){
count = count * field.ks_multiplier;
}
item_info['count'] = count ? count + "%" : "0%";
item_info['count_tooltip'] = count ? String(tool_tip) + "%" : "0%";
}else {
var count = parseInt((count_1 / count_2) * 100);
if (field.ks_multiplier_active){
count = count * field.ks_multiplier;
}
item_info['count'] = count ? field_utils.format.integer(count) + "%" : "0%";
item_info['count_tooltip'] = count ? count + "%" : "0%";
} }
if (!count) count = 0;
item_info['count'] = count ? field_utils.format.integer(count) + "%" : "0%";
item_info['count_tooltip'] = count ? count + "%" : "0%";
item_info.target_progress_deviation = item_info['count'] item_info.target_progress_deviation = item_info['count']
target_1 = target_1 > 100 ? 100 : target_1; target_1 = target_1 > 100 ? 100 : target_1;
item_info.target = target_1 + "%"; item_info.target = target_1 + "%";
@ -235,7 +274,7 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
// } // }
var ks_valid_date_selection = ['l_day', 't_week', 't_month', 't_quarter', 't_year']; var ks_valid_date_selection = ['l_day', 't_week', 't_month', 't_quarter', 't_year'];
var target_view = field.ks_target_view, var target_view = field.ks_target_view,
pre_view = field.ks_prev_view; pre_view = field.ks_prev_view;
var ks_rgba_background_color = self._get_rgba_format(field.ks_background_color); var ks_rgba_background_color = self._get_rgba_format(field.ks_background_color);
var ks_rgba_font_color = self._get_rgba_format(field.ks_font_color) var ks_rgba_font_color = self._get_rgba_format(field.ks_font_color)
@ -271,6 +310,7 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
} }
var ks_rgba_icon_color = self._get_rgba_format(field.ks_default_icon_color) var ks_rgba_icon_color = self._get_rgba_format(field.ks_default_icon_color)
var item_info = { var item_info = {
count_1: self.ksNumFormatter(kpi_data[0]['record_data'], 1), count_1: self.ksNumFormatter(kpi_data[0]['record_data'], 1),
count_1_tooltip: kpi_data[0]['record_data'], count_1_tooltip: kpi_data[0]['record_data'],
count_2: kpi_data[1] ? String(kpi_data[1]['record_data']) : false, count_2: kpi_data[1] ? String(kpi_data[1]['record_data']) : false,
@ -314,7 +354,25 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
} }
item_info['target'] = KsGlobalFunction._onKsGlobalFormatter(kpi_data[0].target, field.ks_data_format, field.ks_precision_digits); item_info['target'] = KsGlobalFunction._onKsGlobalFormatter(kpi_data[0].target, field.ks_data_format, field.ks_precision_digits);
if (field.ks_unit){
if (field.ks_multiplier_active){
var ks_record_count = kpi_data[0]['record_data'] * field.ks_multiplier
}else{
var ks_record_count = kpi_data[0]['record_data']
}
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
var ks_data = KsGlobalFunction._onKsGlobalFormatter(ks_record_count, field.ks_data_format, field.ks_precision_digits);
ks_data = KsGlobalFunction.ks_monetary(ks_data, ks_currency_id);
item_info['count_1'] = ks_data;
} else if (ks_selection === 'custom') {
var ks_field = kpi_data[0].ks_field;
item_info['count_1']=ks_field+" "+KsGlobalFunction._onKsGlobalFormatter(ks_record_count, field.ks_data_format, field.ks_precision_digits);
}else {
item_info['count_1']= KsGlobalFunction._onKsGlobalFormatter(ks_record_count, field.ks_data_format, field.ks_precision_digits);
}
}
var $kpi_preview; var $kpi_preview;
if (!kpi_data[1]) { if (!kpi_data[1]) {
if (target_view === "Number" || !field.ks_goal_enable) { if (target_view === "Number" || !field.ks_goal_enable) {
@ -355,13 +413,46 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
if (field.ks_multiplier_active){ if (field.ks_multiplier_active){
var count_tooltip = String(count_1 * field.ks_multiplier) + "/" + String(count_2 * field.ks_multiplier); var count_tooltip = String(count_1 * field.ks_multiplier) + "/" + String(count_2 * field.ks_multiplier);
var count = String(self.ksNumFormatter(count_1 * field.ks_multiplier, 1)) + "/" + String(self.ksNumFormatter(count_2 * field.ks_multiplier, 1)); var count = String(self.ksNumFormatter(count_1 * field.ks_multiplier, 1)) + "/" + String(self.ksNumFormatter(count_2 * field.ks_multiplier, 1));
item_info['count'] = String(KsGlobalFunction._onKsGlobalFormatter(count_1 * field.ks_multiplier, field.ks_data_format, field.ks_precision_digits)) + "/" + String(KsGlobalFunction._onKsGlobalFormatter(count_2 * field.ks_multiplier, field.ks_data_format, field.ks_precision_digits)); var data1 = KsGlobalFunction._onKsGlobalFormatter(count_1 * field.ks_multiplier, field.ks_data_format, field.ks_precision_digits);
var data2 = KsGlobalFunction._onKsGlobalFormatter(count_2 * field.ks_multiplier, field.ks_data_format, field.ks_precision_digits);
if (field.ks_unit){
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
data1 = KsGlobalFunction.ks_monetary(data1, ks_currency_id);
data2 = KsGlobalFunction.ks_monetary(data2, ks_currency_id)
item_info['count'] = data1+"/"+data2;
} else if (ks_selection === 'custom') {
var ks_field = kpi_data[0].ks_field;
data1= ks_field+" "+data1
data2= ks_field+" "+data2
item_info['count']= data1+"/"+data2
}
}else {
item_info['count']=String(KsGlobalFunction._onKsGlobalFormatter(count_1*field.ks_multiplier, field.ks_data_format, field.ks_precision_digits)) + "/" + String(KsGlobalFunction._onKsGlobalFormatter(count_2*field.ks_multiplier, field.ks_data_format, field.ks_precision_digits));
}
}else{ }else{
var count_tooltip = String(count_1) + "/" + String(count_2); var count_tooltip = String(count_1) + "/" + String(count_2);
var count = String(self.ksNumFormatter(count_1, 1)) + "/" + String(self.ksNumFormatter(count_2, 1)); var count = String(self.ksNumFormatter(count_1, 1)) + "/" + String(self.ksNumFormatter(count_2, 1));
item_info['count'] = String(KsGlobalFunction._onKsGlobalFormatter(count_1, field.ks_data_format, field.ks_precision_digits)) + "/" + String(KsGlobalFunction._onKsGlobalFormatter(count_2, field.ks_data_format, field.ks_precision_digits)); var data1 = KsGlobalFunction._onKsGlobalFormatter(count_1 , field.ks_data_format, field.ks_precision_digits);
} var data2 = KsGlobalFunction._onKsGlobalFormatter(count_2 , field.ks_data_format, field.ks_precision_digits);
if (field.ks_unit){
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
data1 = KsGlobalFunction.ks_monetary(data1, ks_currency_id);
data2 = KsGlobalFunction.ks_monetary(data2, ks_currency_id)
item_info['count'] = data1+"/"+data2;
} else{
var ks_field = kpi_data[0].ks_field;
data1= ks_field+" "+data1
data2= ks_field+" "+data2
item_info['count']= data1+"/"+data2
}
}else {
item_info['count']=String(KsGlobalFunction._onKsGlobalFormatter(count_1, field.ks_data_format, field.ks_precision_digits)) + "/" + String(KsGlobalFunction._onKsGlobalFormatter(count_2, field.ks_data_format, field.ks_precision_digits));
}
}
item_info['count_tooltip'] = count_tooltip item_info['count_tooltip'] = count_tooltip
item_info['target_enable'] = false; item_info['target_enable'] = false;
$kpi_preview = $(Qweb.render("ks_kpi_preview_template_2", item_info)); $kpi_preview = $(Qweb.render("ks_kpi_preview_template_2", item_info));
@ -377,7 +468,24 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
if (field.ks_data_format == 'exact'){ if (field.ks_data_format == 'exact'){
if (count_1 && count_2) { if (count_1 && count_2) {
item_info['count_tooltip'] = count_1 / gcd + ":" + count_2 / gcd; item_info['count_tooltip'] = count_1 / gcd + ":" + count_2 / gcd;
var data1 = field_utils.format.float(count_1 / gcd, Float64Array,{digits: [0, field.ks_precision_digits]});
var data2 = field_utils.format.float(count_2 / gcd, Float64Array, {digits: [0, field.ks_precision_digits]});
if (field.ks_unit){
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
data1 = KsGlobalFunction.ks_monetary(data1, ks_currency_id);
data2 = KsGlobalFunction.ks_monetary(data2, ks_currency_id)
item_info['count'] = data1+":"+data2;
} else if (ks_selection === 'custom') {
var ks_field = kpi_data[0].ks_field;
data1= ks_field+" "+data1
data2= ks_field+" "+data2
item_info['count']= data1+":"+data2
}
}else {
item_info['count'] = field_utils.format.float(count_1 / gcd, Float64Array,{digits: [0, field.ks_precision_digits]}) + ":" + field_utils.format.float(count_2 / gcd, Float64Array, {digits: [0, field.ks_precision_digits]}); item_info['count'] = field_utils.format.float(count_1 / gcd, Float64Array,{digits: [0, field.ks_precision_digits]}) + ":" + field_utils.format.float(count_2 / gcd, Float64Array, {digits: [0, field.ks_precision_digits]});
}
} else { } else {
item_info['count_tooltip'] = count_1 + ":" + count_2; item_info['count_tooltip'] = count_1 + ":" + count_2;
item_info['count'] = count_1 + ":" + count_2 item_info['count'] = count_1 + ":" + count_2
@ -385,7 +493,24 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
}else{ }else{
if (count_1 && count_2) { if (count_1 && count_2) {
item_info['count_tooltip'] = count_1 / gcd + ":" + count_2 / gcd; item_info['count_tooltip'] = count_1 / gcd + ":" + count_2 / gcd;
var data1 = KsGlobalFunction.ksNumFormatter(count_1 / gcd, 1);
var data2 = KsGlobalFunction.ksNumFormatter(count_2 / gcd, 1);
if (field.ks_unit){
var ks_selection = kpi_data[0].ks_selection;
if (ks_selection === 'monetary') {
var ks_currency_id = kpi_data[0].ks_currency;
data1 = KsGlobalFunction.ks_monetary(data1, ks_currency_id);
data2 = KsGlobalFunction.ks_monetary(data2, ks_currency_id)
item_info['count'] = data1+":"+data2;
} else if (ks_selection === 'custom') {
var ks_field = kpi_data[0].ks_field;
data1= ks_field+" "+data1
data2= ks_field+" "+data2
item_info['count']= data1+":"+data2
}
}else {
item_info['count'] = KsGlobalFunction.ksNumFormatter(count_1 / gcd, 1) + ":" + KsGlobalFunction.ksNumFormatter(count_2 / gcd, 1); item_info['count'] = KsGlobalFunction.ksNumFormatter(count_1 / gcd, 1) + ":" + KsGlobalFunction.ksNumFormatter(count_2 / gcd, 1);
}
}else { }else {
item_info['count_tooltip'] = (count_1) + ":" + count_2; item_info['count_tooltip'] = (count_1) + ":" + count_2;
item_info['count'] = KsGlobalFunction.ksNumFormatter(count_1, 1) + ":" + KsGlobalFunction.ksNumFormatter(count_2, 1); item_info['count'] = KsGlobalFunction.ksNumFormatter(count_1, 1) + ":" + KsGlobalFunction.ksNumFormatter(count_2, 1);
@ -396,11 +521,19 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_kpi_preview', function(require
break; break;
} }
} }
// $kpi_preview.css({
// "background-color": ks_rgba_background_color,
// "color": ks_rgba_font_color,
// });
this.ks_kpi_preview_background_style($kpi_preview, ks_rgba_background_color, ks_rgba_font_color);
this.$el.append($kpi_preview);
},
ks_kpi_preview_background_style: function($kpi_preview, ks_rgba_background_color, ks_rgba_font_color){
$kpi_preview.css({ $kpi_preview.css({
"background-color": ks_rgba_background_color, "background-color": ks_rgba_background_color,
"color": ks_rgba_font_color, "color": ks_rgba_font_color,
}); });
this.$el.append($kpi_preview);
}, },
ks_get_gcd: function(a, b) { ks_get_gcd: function(a, b) {

View File

@ -62,7 +62,7 @@ odoo.define('ks_dashboard_ninja_list.ks_dashboard_ninja_list_view_preview', func
var date = list_view_data.data_rows[j]["data"][index] var date = list_view_data.data_rows[j]["data"][index]
if (date){ if (date){
if( list_view_data.fields_type[index] === 'date'){ if( list_view_data.fields_type[index] === 'date'){
list_view_data.data_rows[j]["data"][index] = field_utils.format.date(moment(moment(date).utc(true)._d), {}, { list_view_data.data_rows[j]["data"][index] = field_utils.format.date(moment(moment(date).utc(false)._d), {}, {
timezone: false timezone: false
});}else{ });}else{
list_view_data.data_rows[j]["data"][index] = field_utils.format.datetime(moment(moment(date).utc(true)._d), {}, { list_view_data.data_rows[j]["data"][index] = field_utils.format.datetime(moment(moment(date).utc(true)._d), {}, {

View File

@ -24,7 +24,8 @@ return KsFilterProps.include({
'change .ks_operator_option_selector': 'ksOnCustomFilterOperatorSelect', 'change .ks_operator_option_selector': 'ksOnCustomFilterOperatorSelect',
}), }),
init: function(){ init: function(state){
this._super.apply(this, arguments); this._super.apply(this, arguments);
this.ksCustomFilterData = { this.ksCustomFilterData = {
OPERATORS : FIELD_OPERATORS, OPERATORS : FIELD_OPERATORS,
@ -145,8 +146,8 @@ return KsFilterProps.include({
} }
domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data); domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data);
_(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)}); _(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)});
self.state['domain_data']=self.ks_dashboard_data.ks_dashboard_domain_data;
}, },
_ksUpdateRemoveDomainIndexData: function(action, categ, params){ _ksUpdateRemoveDomainIndexData: function(action, categ, params){
@ -185,6 +186,7 @@ return KsFilterProps.include({
domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data); domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data);
_(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)}); _(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)});
self.state['domain_data']=self.ks_dashboard_data.ks_dashboard_domain_data;
}, },
_ksMakeDomainFromDomainIndex: function(ks_domain_index_data){ _ksMakeDomainFromDomainIndex: function(ks_domain_index_data){
@ -227,7 +229,9 @@ return KsFilterProps.include({
ks_fetch_items_data: function(){ ks_fetch_items_data: function(){
var self = this; var self = this;
return this._super.apply(this, arguments).then(function(){ return this._super.apply(this, arguments).then(function(){
if (self.ks_dashboard_data.ks_dashboard_domain_data) self.ks_init_domain_data_index(); if(self.state['domain_data'] == undefined){
if (self.ks_dashboard_data.ks_dashboard_domain_data) self.ks_init_domain_data_index();
}
}); });
}, },
@ -249,6 +253,7 @@ return KsFilterProps.include({
_(temp_data).values().forEach((x)=>{ _(temp_data).values().forEach((x)=>{
self.ks_dashboard_data.ks_dashboard_domain_data[x.model].ks_domain_index_data.push(x); self.ks_dashboard_data.ks_dashboard_domain_data[x.model].ks_domain_index_data.push(x);
}) })
self.state['domain_data']=self.ks_dashboard_data.ks_dashboard_domain_data;
}, },
// Custom Filter Events and Functions ------------------------------------------------------------------- // Custom Filter Events and Functions -------------------------------------------------------------------
@ -486,6 +491,7 @@ return KsFilterProps.include({
domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data); domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data);
_(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)}); _(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)});
self.state['domain_data']=self.ks_dashboard_data.ks_dashboard_domain_data;
}) })
}, },
@ -525,9 +531,9 @@ return KsFilterProps.include({
domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data); domain_data['domain'] = self._ksMakeDomainFromDomainIndex(domain_data.ks_domain_index_data);
_(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)}); _(domain_data['item_ids']).each((x)=>{self.ksFetchUpdateItem(x)});
self.state['domain_data']=self.ks_dashboard_data.ks_dashboard_domain_data;
} }
}, },
}) })
}); });

View File

@ -0,0 +1,113 @@
odoo.define('ks_dashboard_ninja.ks_keyword_selection', function(require) {
"use strict";
var registry = require('web.field_registry');
var AbstractField = require('web.AbstractField');
var core = require('web.core');
var ajax = require('web.ajax');
var QWeb = core.qweb;
//Widget for dashboard item theme using while creating dashboard item.
var KsKeywordSelection = AbstractField.extend({
supportedFieldTypes: ['char'],
resetOnAnyFieldChange: true,
events: _.extend({}, AbstractField.prototype.events, {
'click .ks_input_custom': 'onclickvalues',
'click .ks_response_container_list': 'onResponseSelect',
'click .ks_response_container_list_zero': 'onResponseSelect',
'keyup #ks_selection_field' :'onKeyup'
}),
init: function(parent, state, params) {
this.ks_new_value = [];
this.ks_data_model = [];
this._super.apply(this, arguments);
},
_render: async function() {
var self = this;
self.ks_data_model = await ajax.jsonRpc('/web/dataset/call_kw', 'call',{
model:'ks_dashboard_ninja.arti_int',
method:'ks_get_keywords',
args:[],
kwargs: {},
})
self.ks_new_value = self.ks_data_model
self.$el.empty();
var $view = $(QWeb.render('KsKeywordSelection', {ks_values:self.ks_data_model,ks_fixed_value:self.value}));
self.$el.append($view)
if ($view.find("#ks_selection_field")[0].value == "false"){
$view.find("#ks_selection_field")[0].value = ""
}
},
onclickvalues: async function(ev){
var self = this;
if ($('.ks_response_container_list .d-block').length == 0){
_.each($('.ks_response_container_list'), function(item) {
$(item).removeClass('d-none');
$(item).addClass('d-block');
});
}
},
onKeyup: function(ev) {
var value = ev.target.value;
var self=this;
if (value.length){
var ks_value = value.toUpperCase();
self.ks_new_value =[];
if ($('.ks_response_container_list').length){
_.each($('.ks_response_container_list'),function(item){
if (item.innerText.toUpperCase().indexOf(ks_value) > -1){
$(item).addClass("d-block")
$(item).removeClass("d-none")
}else{
$(item).removeClass("d-block")
$(item).addClass("d-none")
}
})
}
$('.ks_response_container_list_zero').removeClass("d-none")
// $('.ks_response_container_list_zero').addClass("d-block")
$('.ks_response_container_list_zero .ks_response span')[0].innerText = value
}else{
if ($('.ks_response_container_list .d-block').length == 0){
_.each($('.ks_response_container_list'), function(item) {
$(item).removeClass('d-none');
$(item).addClass('d-block');
});
}
}
},
onResponseSelect: function(ev) {
var self = this;
if ($(ev.currentTarget).hasClass("ks_response_container_list_zero")){
var value = $(ev.currentTarget).find(".ks_response span")[0].innerText;
}else{
var value = $(ev.currentTarget).find(".ks_response")[0].innerText;
}
self._setValue(value);
},
});
registry.add('ks_keyword_selection', KsKeywordSelection);
return {
KsKeywordSelection: KsKeywordSelection
};
});

View File

@ -9,6 +9,7 @@ odoo.define('ks_dashboard_ninja.quick_edit_view', function(require) {
var QuickCreateFormView = require('web.QuickCreateFormView'); var QuickCreateFormView = require('web.QuickCreateFormView');
var AbstractAction = require('web.AbstractAction'); var AbstractAction = require('web.AbstractAction');
var QuickEditView = Widget.extend({ var QuickEditView = Widget.extend({
template: 'ksQuickEditViewOption', template: 'ksQuickEditViewOption',
@ -23,7 +24,7 @@ odoo.define('ks_dashboard_ninja.quick_edit_view', function(require) {
this.ksOriginalItemData = $.extend({}, options.item); this.ksOriginalItemData = $.extend({}, options.item);
this.item = options.item; this.item = options.item;
this.item_name = options.item.name; this.item_name = options.item ? options.item.name:false;
}, },
@ -90,7 +91,7 @@ odoo.define('ks_dashboard_ninja.quick_edit_view', function(require) {
self.item['ks_font_color'] = ksChanges['ks_font_color']; self.item['ks_font_color'] = ksChanges['ks_font_color'];
self.item['ks_icon_select'] = ksChanges['ks_icon_select']; self.item['ks_icon_select'] = ksChanges['ks_icon_select'];
self.item['ks_icon'] = ksChanges['ks_icon']; // self.item['ks_icon'] = ksChanges['ks_icon'];
self.item['ks_background_color'] = ksChanges['ks_background_color']; self.item['ks_background_color'] = ksChanges['ks_background_color'];
self.item['ks_default_icon_color'] = ksChanges['ks_default_icon_color']; self.item['ks_default_icon_color'] = ksChanges['ks_default_icon_color'];
self.item['ks_layout'] = ksChanges['ks_layout']; self.item['ks_layout'] = ksChanges['ks_layout'];
@ -128,7 +129,6 @@ odoo.define('ks_dashboard_ninja.quick_edit_view', function(require) {
var self = this; var self = this;
self.ksDashboardController.ksUpdateDashboardItem([self.item.id]); self.ksDashboardController.ksUpdateDashboardItem([self.item.id]);
self.item_el = $.find('#' + self.item.id + '.ks_dashboarditem_id'); self.item_el = $.find('#' + self.item.id + '.ks_dashboarditem_id');
}, },
ksDiscardChanges: function() { ksDiscardChanges: function() {

View File

@ -6,6 +6,7 @@ var core = require('web.core');
var _t = core._t; var _t = core._t;
var QWeb = core.qweb; var QWeb = core.qweb;
var Dialog = require('web.Dialog'); var Dialog = require('web.Dialog');
var config = require('web.config');
return KsDashboard.include({ return KsDashboard.include({
events: _.extend({}, KsDashboard.prototype.events, { events: _.extend({}, KsDashboard.prototype.events, {
@ -34,7 +35,12 @@ return KsDashboard.include({
var item_view = self._ksRenderDashboardTile(items[i]) var item_view = self._ksRenderDashboardTile(items[i])
if (items[i].id in self.gridstackConfig) { if (items[i].id in self.gridstackConfig) {
// self.grid.addWidget($(item_view), self.gridstackConfig[items[i].id].x, self.gridstackConfig[items[i].id].y, self.gridstackConfig[items[i].id].width, self.gridstackConfig[items[i].id].height, false, 6, null, 2, 2, items[i].id); // self.grid.addWidget($(item_view), self.gridstackConfig[items[i].id].x, self.gridstackConfig[items[i].id].y, self.gridstackConfig[items[i].id].width, self.gridstackConfig[items[i].id].height, false, 6, null, 2, 2, items[i].id);
self.grid.addWidget($(item_view)[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h,autoPosition:false,minW:2,maxW:null,minH:2,maxH:2,id:items[i].id,}); if (config.device && config.device.isMobile){
self.grid.addWidget($(item_view)[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h,autoPosition:true,minW:2,maxW:null,minH:2,maxH:2,id:items[i].id,});
}
else{
self.grid.addWidget($(item_view)[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h,autoPosition:false,minW:2,maxW:null,minH:2,maxH:2,id:items[i].id,});
}
} else { } else {
self.grid.addWidget($(item_view)[0], {x:0, y:0, w:3, h:2,autoPosition:true,minW:2,maxW:null,minH:2,maxH:2,id:items[i].id}); self.grid.addWidget($(item_view)[0], {x:0, y:0, w:3, h:2,autoPosition:true,minW:2,maxW:null,minH:2,maxH:2,id:items[i].id});
} }
@ -43,17 +49,27 @@ return KsDashboard.include({
} else if (items[i].ks_dashboard_item_type === 'ks_kpi') { } else if (items[i].ks_dashboard_item_type === 'ks_kpi') {
var $kpi_preview = self.renderKpi(items[i], self.grid) var $kpi_preview = self.renderKpi(items[i], self.grid)
if (items[i].id in self.gridstackConfig) { if (items[i].id in self.gridstackConfig) {
self.grid.addWidget($kpi_preview[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h,autoPosition:false,minW:2,maxW:null,minH:2,maxH:3,id:items[i].id}); if (config.device && config.device.isMobile){
self.grid.addWidget($kpi_preview[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h,autoPosition:true,minW:2,maxW:null,minH:2,maxH:3,id:items[i].id});
}
else{
self.grid.addWidget($kpi_preview[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h,autoPosition:false,minW:2,maxW:null,minH:2,maxH:3,id:items[i].id});
}
} else { } else {
self.grid.addWidget($kpi_preview[0], {x:0, y:0, w:3, h:2,autoPosition:true,minW:2,maxW:null,minH:2,maxH:3,id:items[i].id}); self.grid.addWidget($kpi_preview[0], {x:0, y:0, w:3, h:2,autoPosition:true,minW:2,maxW:null,minH:2,maxH:3,id:items[i].id});
} }
} else if (items[i].ks_dashboard_item_type === 'ks_to_do'){ } else if (items[i].ks_dashboard_item_type === 'ks_to_do'){
var $to_do_preview = self.ksRenderToDoDashboardView(items[i]); var $to_do_preview = self.ksRenderToDoDashboardView(items[i])[0];
if (items[i].id in self.gridstackConfig) { if (items[i].id in self.gridstackConfig) {
self.grid.addWidget($to_do_preview[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h, autoPosition:false, minW:4, maxW:null, minH:3, maxH:null, id:items[i].id}); if (config.device && config.device.isMobile){
self.grid.addWidget($to_do_preview[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h, autoPosition:true, minW:5, maxW:null, minH:2, maxH:null, id:items[i].id});
}
else{
self.grid.addWidget($to_do_preview[0], {x:self.gridstackConfig[items[i].id].x, y:self.gridstackConfig[items[i].id].y, w:self.gridstackConfig[items[i].id].w, h:self.gridstackConfig[items[i].id].h, autoPosition:false, minW:5, maxW:null, minH:2, maxH:null, id:items[i].id});
}
} else { } else {
self.grid.addWidget($to_do_preview[0], {x:0, y:0, w:5, h:4, autoPosition:true, minW:4, maxW:null, minH:3, maxH:null, id:items[i].id}) self.grid.addWidget($to_do_preview[0], {x:0, y:0, w:6, h:4, autoPosition:true, minW:5, maxW:null, minH:2, maxH:null, id:items[i].id})
} }
} else { } else {
self._renderGraph(items[i], self.grid) self._renderGraph(items[i], self.grid)
@ -66,6 +82,12 @@ return KsDashboard.include({
var self = this; var self = this;
var item_title = item.name; var item_title = item.name;
var item_id = item.id; var item_id = item.id;
if (item.ks_info){
var ks_description = item.ks_info.split('\n');
var ks_description = ks_description.filter(element => element !== '')
}else {
var ks_description = false;
}
var list_to_do_data = JSON.parse(item.ks_to_do_data) var list_to_do_data = JSON.parse(item.ks_to_do_data)
var ks_header_color = self._ks_get_rgba_format(item.ks_header_bg_color); var ks_header_color = self._ks_get_rgba_format(item.ks_header_bg_color);
var ks_font_color = self._ks_get_rgba_format(item.ks_font_color); var ks_font_color = self._ks_get_rgba_format(item.ks_font_color);
@ -74,17 +96,20 @@ return KsDashboard.include({
var $ks_gridstack_container = $(QWeb.render('ks_to_do_dashboard_container', { var $ks_gridstack_container = $(QWeb.render('ks_to_do_dashboard_container', {
ks_chart_title: item_title, ks_chart_title: item_title,
ksIsDashboardManager: self.ks_dashboard_data.ks_dashboard_manager, ksIsDashboardManager: self.ks_dashboard_data.ks_dashboard_manager,
ksIsUser: true,
ks_dashboard_list: self.ks_dashboard_data.ks_dashboard_list, ks_dashboard_list: self.ks_dashboard_data.ks_dashboard_list,
item_id: item_id, item_id: item_id,
to_do_view_data: list_to_do_data, to_do_view_data: list_to_do_data,
ks_rgba_button_color:ks_rgba_button_color, ks_rgba_button_color:ks_rgba_button_color,
ks_info: ks_description,
ks_company:item.ks_company
})).addClass('ks_dashboarditem_id') })).addClass('ks_dashboarditem_id')
$ks_gridstack_container.find('.ks_card_header').addClass('ks_bg_to_color').css({"background-color": ks_header_color }); $ks_gridstack_container.find('.ks_card_header').addClass('ks_bg_to_color').css({"background-color": ks_header_color });
$ks_gridstack_container.find('.ks_card_header').addClass('ks_bg_to_color').css({"color": ks_font_color + ' !important' }); $ks_gridstack_container.find('.ks_card_header').addClass('ks_bg_to_color').css({"color": ks_font_color + ' !important' });
$ks_gridstack_container.find('.ks_li_tab').addClass('ks_bg_to_color').css({"color": ks_font_color + ' !important' }); $ks_gridstack_container.find('.ks_li_tab').addClass('ks_bg_to_color').css({"color": ks_font_color + ' !important' });
$ks_gridstack_container.find('.ks_list_view_heading').addClass('ks_bg_to_color').css({"color": ks_font_color + ' !important' }); $ks_gridstack_container.find('.ks_list_view_heading').addClass('ks_bg_to_color').css({"color": ks_font_color + ' !important' });
$ks_gridstack_container.find('.ks_to_do_card_body').append($ksItemContainer) $ks_gridstack_container.find('.ks_to_do_card_body').append($ksItemContainer)
return $ks_gridstack_container; return [$ks_gridstack_container, $ksItemContainer];
}, },
ksRenderToDoView: function(item, ks_tv_play=false) { ksRenderToDoView: function(item, ks_tv_play=false) {

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-extend="ksDashboardNinjaHeader">
<t t-jquery="div.ks_dashboard_top_menu" t-operation="before">
<t t-if="ks_ai_dashboard">
<div class="ks_select_text" style="font-style:italic;font-size: medium;margin-left: -7em;">
<span>
Here are your generated Items, kindly select to add them in your current dashboard
</span>
</div>
</t>
</t>
<t t-jquery="li#ks_tile" t-operation="before">
<li id="ks_ai_item_dash" data-item="ks_AI_items">
<span class="df_selection_text position-relative">
Generate Items with AI
<span class="ks_new_tag p-1">
Beta
</span>
</span>
</li>
</t>
<t t-jquery="a#dashboard_create" t-operation="after">
<a class="dropdown-item" href="#" id="create_ai_dashboard">
Generate Dashboard with AI
<span class="ks_new_tag p-1" style="margin-left:3px">
Beta
</span>
</a>
</t>
<t t-jquery="div.ks_am_content_element" t-operation="after">
<t t-if="ks_ai_dashboard">
<button id="ks_ai_add_all_item" class="btn btn-primary" style="margin-right:5px">
<span class="fa fa-plus"/>
Select all
</button>
<button id="ks_ai_remove_all_item" class="btn btn-primary d-none" style="margin-right:5px">
<span class="fa fa-times"/>
Select None
</button>
<button id="ks_ai_add_item" class="btn btn-primary d-none" style="margin-right:5px">
<span class="fa fa-plus"/>
Save
</button>
<button id="ks_close_dialog" class="btn btn-primary">
<span class="fa fa-times"/>
Close
</button>
</t>
</t>
</t>
<t t-name="ksNoAIItemView">
<div class="o_view_nocontent">
<div class="o_nocontent_help">
<p class="o_view_nocontent_neutral_face">
Your AI dashboard is empty
</p>
<p>
To Generate items with AI, use
<a>
<strong class="ks_add_dashboard_item_on_empty">Generate items with AI button</strong>
</a>
under Add dropdown after closing it.
</p>
</div>
</div>
</t>
<t t-extend="ks_gridstack_container">
<t t-jquery="div.ks_dashboard_item_button_container" t-operation="before">
<img src="ks_dashboard_ninja/static/description/images/selected.svg" class="ks_img_display d-none" width="30"/>
</t>
</t>
<t t-extend="ks_gridstack_list_view_container">
<t t-jquery="div.ks_dashboard_item_button_container" t-operation="before">
<img src="ks_dashboard_ninja/static/description/images/selected.svg" class="ks_img_display d-none" width="30"/>
</t>
</t>
<t t-extend="ks_kpi_template">
<t t-jquery="div.ks_dashboard_item_button_container" t-operation="before">
<img src="ks_dashboard_ninja/static/description/images/selected.svg" class="ks_img_display d-none" width="30"/>
</t>
</t>
</templates>

View File

@ -5,7 +5,8 @@
<!-- GridStack Chart Item Container--> <!-- GridStack Chart Item Container-->
<t t-name="ks_gridstack_container"> <t t-name="ks_gridstack_container">
<div class="grid-stack-item ks_chart_container" t-att-id="chart_id"> <div class="grid-stack-item ks_chart_container" t-att-id="chart_id">
<div class="grid-stack-item-content ks_dashboarditem_chart_container ks_dashboard_item_hover card shadow"> <div class="grid-stack-item-content ks_dashboarditem_chart_container ks_dashboard_item_hover card shadow"
t-att-title="ks_info">
<div class="p-3 py-3 d-flex flex-row align-items-center justify-content-between "> <div class="p-3 py-3 d-flex flex-row align-items-center justify-content-between ">
<div class="d-flex align-items-center w-50"> <div class="d-flex align-items-center w-50">
@ -21,7 +22,7 @@
<!-- </div>--> <!-- </div>-->
<!-- Dashboard Item Move/Copy Feature --> <!-- Dashboard Item Move/Copy Feature -->
<div class="ks_dashboard_item_button_container ks_dropdown_container ks_dashboard_item_header ks_dashboard_item_header_hover chart_button_container d-flex" <div class="ks_dashboard_item_button_container ks_dropdown_container ks_dashboard_item_header ks_dashboard_item_header_hover chart_button_container d-md-flex d-none"
t-att-data-item_id="chart_id"> t-att-data-item_id="chart_id">
<t t-if="ksIsDashboardManager"> <t t-if="ksIsDashboardManager">
@ -96,7 +97,8 @@
<button class="ks_dashboard_item_delete" title="Remove Item" type="button"> <button class="ks_dashboard_item_delete" title="Remove Item" type="button">
<i class="fa fa-times"/> <i class="fa fa-times"/>
</button> </button>
</t>
<t t-if="ksIsUser">
<div class="ks_chart_inner_buttons ks_dashboard_more_action" t-att-data-item-id="chart_id"> <div class="ks_chart_inner_buttons ks_dashboard_more_action" t-att-data-item-id="chart_id">
<button title="Export Chart" data-toggle="dropdown" <button title="Export Chart" data-toggle="dropdown"
class="ks_dashboard_item_action btn dropdown-toggle btn-xs o-no-caret btn" class="ks_dashboard_item_action btn dropdown-toggle btn-xs o-no-caret btn"
@ -109,8 +111,57 @@
</div> </div>
</div> </div>
</t> </t>
<div class="ks_chart_inner_buttons dropdown">
<button title="Info" data-toggle="dropdown"
class="ks_item_description btn dropdown-toggle btn-xs o-no-caret btn"
type="button"
t-att-style="'color:'+ ks_rgba_button_color + ';'"
aria-expanded="true">
<i class="fa fa-book"/>
</button>
<div role="menu" class="dropdown-menu dropdown-menu-right" style="width:20rem">
<!--Dynamic Rendering-->
<div class="ks_chart_export_menu">
<div class="ks_chart_export_menu_header" style="margin-left:-10px">
<span>Info</span>
</div>
<div class="ks_info" style="margin-left:10px">
<span>Company: <t t-esc="ks_company"/></span>
</div>
<div class="ks_info" style="margin-left:10px">
<t t-if="ks_info">
<t t-foreach="ks_info" t-as="ks_description">
<span><t t-esc="ks_description"/></span> <br></br>
</t>
</t>
</div>
</div>
</div>
</div> </div>
</div>
<t t-if="ksIsDashboardManager">
<div class="dropdown d-md-none dn-setting-panel">
<button class="btn btn-secondary border-0" type="button" id="dropdownSettingButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" >
<i class="fa fa-cog"></i>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownSettingButton">
<t t-if="ks_show_records &amp; ks_query_type=='custom'">
<a class="dropdown-item ks_dashboard_item_chart_info ks_info_display" t-att-data-item-id="chart_id">
<i class="fa fa-info-circle"/>
More Info
</a>
</t>
<a class="dropdown-item ks_dashboard_item_customize" >
<i class="fa fa-pencil"></i> Customize Item
</a>
<a class="dropdown-item ks_dashboard_item_delete" >
<i class="fa fa-times"></i> Remove Item
</a>
</div>
</div>
</t>
</div> </div>
<div class="card-body ks_chart_card_body"/> <div class="card-body ks_chart_card_body"/>
</div> </div>
@ -166,11 +217,11 @@
</span> </span>
</div> </div>
<!-- GridStack List View Item Container--> <!-- GridStack List View Item Container-->
<t t-name="ks_gridstack_list_view_container"> <t t-name="ks_gridstack_list_view_container">
<div class="grid-stack-item" t-att-id="item_id"> <div class="grid-stack-item" t-att-id="item_id">
<div class="grid-stack-item-content ks_list_view_container ks_dashboard_item_hover card shadow"> <div class="grid-stack-item-content ks_list_view_container ks_dashboard_item_hover card shadow"
t-att-title="ks_info">
<div class="p-3 py-3 d-flex flex-row align-items-center justify-content-between "> <div class="p-3 py-3 d-flex flex-row align-items-center justify-content-between ">
<div class="d-flex align-items-center w-50"> <div class="d-flex align-items-center w-50">
<h6 class="m-0 font-weight-bold h3 mr-3 ks_list_view_heading" t-att-title="ks_chart_title"> <h6 class="m-0 font-weight-bold h3 mr-3 ks_list_view_heading" t-att-title="ks_chart_title">
@ -185,11 +236,11 @@
<t t-if="ks_pager" t-call="ks_pager_template"/> <t t-if="ks_pager" t-call="ks_pager_template"/>
</div> </div>
<t t-if="ksIsDashboardManager">
<!-- Dashboard Item Move/Copy Feature -->
<div class="ks_dashboard_item_button_container ks_dropdown_container ks_dashboard_item_header ks_dashboard_item_header_hover chart_button_container"
t-att-data-item_id="item_id">
<!-- Dashboard Item Move/Copy Feature -->
<div class="ks_dashboard_item_button_container ks_dropdown_container ks_dashboard_item_header ks_dashboard_item_header_hover chart_button_container d-md-flex d-none"
t-att-data-item_id="item_id">
<t t-if="ksIsDashboardManager">
<button title="Move/Duplicate" data-toggle="dropdown" t-att-data-item-id="item_id" <button title="Move/Duplicate" data-toggle="dropdown" t-att-data-item-id="item_id"
class="ks_dashboard_item_action btn dropdown-toggle btn-xs" type="button" class="ks_dashboard_item_action btn dropdown-toggle btn-xs" type="button"
aria-expanded="true"> aria-expanded="true">
@ -230,9 +281,11 @@
<button class="ks_dashboard_item_delete" title="Remove Item" type="button"> <button class="ks_dashboard_item_delete" title="Remove Item" type="button">
<i class="fa fa-times"/> <i class="fa fa-times"/>
</button> </button>
</t>
<t t-if="ksIsUser">
<div class="ks_chart_inner_buttons"> <div class="ks_chart_inner_buttons">
<button title="Export List" data-toggle="dropdown" <button title="Export Item" data-toggle="dropdown"
class="ks_dashboard_item_action_export btn dropdown-toggle btn-xs o-no-caret btn" class="ks_dashboard_item_action_export btn dropdown-toggle btn-xs o-no-caret btn ks_next_previous_bg_color"
type="button" type="button"
aria-expanded="true"> aria-expanded="true">
<i class="fa fa-ellipsis-v"/> <i class="fa fa-ellipsis-v"/>
@ -243,12 +296,14 @@
<div class="ks_chart_export_menu_header"> <div class="ks_chart_export_menu_header">
<span>Export</span> <span>Export</span>
</div> </div>
<div class="chart_xls_export ks_chart_xls_csv_export ks_chart_export_menu_item" t-att-data-chart-id="item_id" <div class="chart_xls_export ks_chart_xls_csv_export ks_chart_export_menu_item"
t-att-data-chart-id="item_id"
data-format="list_xls"> data-format="list_xls">
<i class="fa fa-file-excel-o"/> <i class="fa fa-file-excel-o"/>
<span>Export to Excel</span> <span>Export to Excel</span>
</div> </div>
<div class="ks_chart_xls_csv_export ks_chart_export_menu_item" t-att-data-chart-id="item_id" <div class="ks_chart_xls_csv_export ks_chart_export_menu_item"
t-att-data-chart-id="item_id"
data-format="list_csv"> data-format="list_csv">
<i class="fa fa-file-code-o"/> <i class="fa fa-file-code-o"/>
<span>Export to CSV</span> <span>Export to CSV</span>
@ -262,8 +317,51 @@
</div> </div>
</div> </div>
</div> </div>
</t>
<div class="ks_chart_inner_buttons dropdown">
<button title="Info" data-toggle="dropdown"
class="ks_item_description btn dropdown-toggle btn-xs o-no-caret btn"
type="button"
t-att-style="'color:'+ ks_rgba_button_color + ';'"
aria-expanded="true">
<i class="fa fa-book"/>
</button>
<div role="menu" class="dropdown-menu dropdown-menu-right" style="width:20rem">
<!--Dynamic Rendering-->
<div class="ks_chart_export_menu">
<div class="ks_chart_export_menu_header" style="margin-left:-10px">
<span>Info</span>
</div>
<div class="ks_info" style="margin-left:10px">
<span>Company: <t t-esc="ks_company"/></span>
</div>
<div class="ks_info" style="margin-left:10px">
<t t-if="ks_info">
<t t-foreach="ks_info" t-as="ks_description">
<span><t t-esc="ks_description"/></span> <br></br>
</t>
</t>
</div>
</div>
</div> </div>
</div>
</div>
<t t-if="ksIsDashboardManager">
<div class="dropdown d-md-none dn-setting-panel">
<button class="btn btn-secondary border-0" type="button" id="dropdownSettingButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" >
<i class="fa fa-cog"></i>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownSettingButton">
<a class="dropdown-item ks_dashboard_item_customize" >
<i class="fa fa-pencil"></i> Customize Item
</a>
<a class="dropdown-item ks_dashboard_item_delete" >
<i class="fa fa-times"></i> Remove Item
</a>
</div>
</div>
</t> </t>
</div> </div>
<div class="card-body table-responsive"/> <div class="card-body table-responsive"/>
@ -340,10 +438,10 @@
</t> </t>
<tr t-if="count"> <tr t-if="count">
<td class="ks_font"> <td class="ks_font">
<!-- <span>(--> <!-- <span>(-->
<!-- <t t-esc="count"/>--> <!-- <t t-esc="count"/>-->
<!-- records more)--> <!-- records more)-->
<!-- </span>--> <!-- </span>-->
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -361,12 +459,13 @@
<t t-name="ks_list_view_table"> <t t-name="ks_list_view_table">
<t t-if="list_view_data"> <t t-if="list_view_data">
<table id="ksListViewTable" class="table table-hover ks_list_view_layout_1" t-att-data-model="list_view_data['model']"> <table id="ksListViewTable" class="table table-hover ks_list_view_layout_1"
t-att-data-model="list_view_data['model']">
<thead> <thead>
<t t-call="ks_list_view_header"/> <t t-call="ks_list_view_header"/>
</thead> </thead>
<tbody class="ks_table_body"> <tbody class="ks_table_body">
<!-- <t t-call="ks_list_view_tmpl"/>--> <!-- <t t-call="ks_list_view_tmpl"/>-->
</tbody> </tbody>
</table> </table>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<templates> <templates>
<t t-name="ks_dn_filter_container"> <t t-name="ks_dn_filter_container">
<div class="ks_dashboard_top_menu ks_select_none"> <div class="ks_dashboard_top_menu ks_select_none ks_global_filter_padding">
<!-- Date Filter Selection Options (Hide default for no content view)--> <!-- Date Filter Selection Options (Hide default for no content view)-->
<div class="ks_dashboard_link ks_am_content_element ks_hide mr-4" <div class="ks_dashboard_link ks_am_content_element ks_hide mr-4"
@ -38,7 +38,12 @@
</li> </li>
</t> </t>
<t t-else=""> <t t-else="">
<hr/> <li class="ks_dn_separator">
<span >
<t t-esc="pre_filter['name']"/>
</span>
</li>
</t> </t>
</t> </t>
<hr t-if="_(ks_dashboard_data.ks_dashboard_custom_domain_filter).keys().length"/> <hr t-if="_(ks_dashboard_data.ks_dashboard_custom_domain_filter).keys().length"/>

View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="KsKeywordSelection">
<div>
<div class="ks_input_custom">
<input type="text" id="ks_selection_field"
class="o_input input_bar" t-att-value="ks_fixed_value"
/>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M7 10L12 15L17 10H7Z" fill="#797979"/>
</svg>
</div>
<div class="ks_search_result search_style">
<t t-debug="pdb"/>
<div class="ks_response_container_list_zero ks_border_class d-none">
<div class="ks_response d-flex align-items-center justify-content-between">
<span></span>
<div class="ks_dashboard_option_category">
<span class="ks_dashboard_option">Generate With AI</span>
</div>
</div>
</div>
<t t-foreach="ks_values" t-as="val" t-key="val.id">
<div class="ks_response_container_list d-none">
<div class="ks_response d-flex align-items-center justify-content-between">
<t t-esc="val['value']"/>
<t t-if="val.id !=0">
<t t-if="val['type'] == 'bar' || val['type'] == 'pie' || val['type'] == 'area' || val['type'] == 'line'">
<div class="ks_dashboard_ai_chart_icons">
<span t-att-class="'fa fa-' + val['type']+'-chart'"></span>
</div>
</t>
<t t-if="val['type'] == 'horizontalbar'">
<svg style="margin:0px 10px" xmlns="http://www.w3.org/2000/svg" width="16"
height="14"
viewBox="0 0 13 12" fill="none">
<line x1="1" y1="4.37113e-08" x2="0.999999" y2="12" stroke="#A8A8A8"
stroke-width="2"/>
<line x1="1" y1="11" x2="13" y2="11" stroke="#A8A8A8" stroke-width="2"/>
<line x1="3" y1="8.5" x2="11" y2="8.5" stroke="#A8A8A8"/>
<line x1="3" y1="6.5" x2="7" y2="6.5" stroke="#A8A8A8"/>
<line x1="3" y1="2.5" x2="6" y2="2.5" stroke="#A8A8A8"/>
<line x1="3" y1="4.5" x2="9" y2="4.5" stroke="#A8A8A8"/>
</svg>
</t>
<t t-if="val['type'] == 'polar'">
<svg style="margin:0px 10px" xmlns="http://www.w3.org/2000/svg" width="16"
height="14"
viewBox="0 0 13 13" fill="none">
<mask id="path-1-inside-1_80_18" fill="white">
<path d="M11.874 4.7818C11.5881 3.41108 10.8314 2.18369 9.73509 1.31259C8.63882 0.441493 7.2722 -0.0183539 5.87233 0.0128348L5.9121 1.79799C6.89499 1.77609 7.85452 2.09896 8.62424 2.71058C9.39396 3.3222 9.92528 4.18398 10.126 5.14639L11.874 4.7818Z"/>
</mask>
<path d="M11.874 4.7818C11.5881 3.41108 10.8314 2.18369 9.73509 1.31259C8.63882 0.441493 7.2722 -0.0183539 5.87233 0.0128348L5.9121 1.79799C6.89499 1.77609 7.85452 2.09896 8.62424 2.71058C9.39396 3.3222 9.92528 4.18398 10.126 5.14639L11.874 4.7818Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-1-inside-1_80_18)"/>
<mask id="path-2-inside-2_80_18" fill="white">
<path d="M9.97614 10.5177C10.6791 9.89933 11.2274 9.12491 11.5772 8.25648C11.927 7.38806 12.0685 6.44978 11.9904 5.51682L10.211 5.66578C10.2658 6.32083 10.1665 6.97962 9.9209 7.58936C9.67531 8.19911 9.29031 8.74285 8.79676 9.17702L9.97614 10.5177Z"/>
</mask>
<path d="M9.97614 10.5177C10.6791 9.89933 11.2274 9.12491 11.5772 8.25648C11.927 7.38806 12.0685 6.44978 11.9904 5.51682L10.211 5.66578C10.2658 6.32083 10.1665 6.97962 9.9209 7.58936C9.67531 8.19911 9.29031 8.74285 8.79676 9.17702L9.97614 10.5177Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-2-inside-2_80_18)"/>
<mask id="path-3-inside-3_80_18" fill="white">
<path d="M3.33893 11.3743C4.29238 11.8479 5.35478 12.0591 6.4169 11.9861C7.47902 11.9131 8.50253 11.5586 9.38222 10.9589L8.37411 9.48001C7.75708 9.90062 7.03916 10.1493 6.29417 10.2005C5.54918 10.2517 4.80399 10.1036 4.13521 9.77137L3.33893 11.3743Z"/>
</mask>
<path d="M3.33893 11.3743C4.29238 11.8479 5.35478 12.0591 6.4169 11.9861C7.47902 11.9131 8.50253 11.5586 9.38222 10.9589L8.37411 9.48001C7.75708 9.90062 7.03916 10.1493 6.29417 10.2005C5.54918 10.2517 4.80399 10.1036 4.13521 9.77137L3.33893 11.3743Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-3-inside-3_80_18)"/>
<mask id="path-4-inside-4_80_18" fill="white">
<path d="M0.101548 4.97018C-0.102251 6.13211 0.0413121 7.32834 0.514258 8.40905C0.987204 9.48976 1.76851 10.4069 2.76031 11.0456L3.72936 9.54082C3.03369 9.09282 2.48566 8.44952 2.15393 7.69148C1.8222 6.93345 1.7215 6.09439 1.86445 5.27939L0.101548 4.97018Z"/>
</mask>
<path d="M0.101548 4.97018C-0.102251 6.13211 0.0413121 7.32834 0.514258 8.40905C0.987204 9.48976 1.76851 10.4069 2.76031 11.0456L3.72936 9.54082C3.03369 9.09282 2.48566 8.44952 2.15393 7.69148C1.8222 6.93345 1.7215 6.09439 1.86445 5.27939L0.101548 4.97018Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-4-inside-4_80_18)"/>
<mask id="path-5-inside-5_80_18" fill="white">
<path d="M5.12537 0.0763639C3.96937 0.248022 2.88876 0.753849 2.01648 1.53162C1.14419 2.30939 0.518285 3.32517 0.215751 4.45401L1.94455 4.91734C2.15675 4.12554 2.59578 3.41305 3.20762 2.86751C3.81946 2.32196 4.57742 1.96717 5.38827 1.84676L5.12537 0.0763639Z"/>
</mask>
<path d="M5.12537 0.0763639C3.96937 0.248022 2.88876 0.753849 2.01648 1.53162C1.14419 2.30939 0.518285 3.32517 0.215751 4.45401L1.94455 4.91734C2.15675 4.12554 2.59578 3.41305 3.20762 2.86751C3.81946 2.32196 4.57742 1.96717 5.38827 1.84676L5.12537 0.0763639Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-5-inside-5_80_18)"/>
<mask id="path-6-inside-6_80_18" fill="white">
<path d="M9.24227 5.53929C9.24227 5.17557 9.17063 4.81542 9.03144 4.47939C8.89225 4.14337 8.68825 3.83804 8.43106 3.58086C8.17388 3.32368 7.86856 3.11967 7.53253 2.98048C7.1965 2.84129 6.83635 2.76965 6.47264 2.76965L6.47264 5.53929H9.24227Z"/>
</mask>
<path d="M9.24227 5.53929C9.24227 5.17557 9.17063 4.81542 9.03144 4.47939C8.89225 4.14337 8.68825 3.83804 8.43106 3.58086C8.17388 3.32368 7.86856 3.11967 7.53253 2.98048C7.1965 2.84129 6.83635 2.76965 6.47264 2.76965L6.47264 5.53929H9.24227Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-6-inside-6_80_18)"/>
<mask id="path-7-inside-7_80_18" fill="white">
<path d="M9.24227 6.46242C9.24227 6.82614 9.17063 7.18629 9.03144 7.52232C8.89225 7.85834 8.68825 8.16367 8.43106 8.42085C8.17388 8.67803 7.86856 8.88204 7.53253 9.02123C7.1965 9.16042 6.83635 9.23206 6.47264 9.23206L6.47264 6.46242H9.24227Z"/>
</mask>
<path d="M9.24227 6.46242C9.24227 6.82614 9.17063 7.18629 9.03144 7.52232C8.89225 7.85834 8.68825 8.16367 8.43106 8.42085C8.17388 8.67803 7.86856 8.88204 7.53253 9.02123C7.1965 9.16042 6.83635 9.23206 6.47264 9.23206L6.47264 6.46242H9.24227Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-7-inside-7_80_18)"/>
<mask id="path-8-inside-8_80_18" fill="white">
<path d="M5.54949 2.78007C5.18579 2.78142 4.82591 2.8544 4.49041 2.99483C4.15491 3.13526 3.85036 3.3404 3.59414 3.59854C3.33792 3.85667 3.13505 4.16274 2.99712 4.49927C2.85918 4.83581 2.78889 5.19622 2.79024 5.55992L5.55979 5.54962L5.54949 2.78007Z"/>
</mask>
<path d="M5.54949 2.78007C5.18579 2.78142 4.82591 2.8544 4.49041 2.99483C4.15491 3.13526 3.85036 3.3404 3.59414 3.59854C3.33792 3.85667 3.13505 4.16274 2.99712 4.49927C2.85918 4.83581 2.78889 5.19622 2.79024 5.55992L5.55979 5.54962L5.54949 2.78007Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-8-inside-8_80_18)"/>
<mask id="path-9-inside-9_80_18" fill="white">
<path d="M5.54949 9.22195C5.18579 9.22061 4.82591 9.14817 4.49041 9.00878C4.15491 8.86938 3.85036 8.66575 3.59414 8.40953C3.33792 8.1533 3.13505 7.84949 2.99712 7.51543C2.85918 7.18138 2.78889 6.82363 2.79024 6.46261L5.55979 6.47284L5.54949 9.22195Z"/>
</mask>
<path d="M5.54949 9.22195C5.18579 9.22061 4.82591 9.14817 4.49041 9.00878C4.15491 8.86938 3.85036 8.66575 3.59414 8.40953C3.33792 8.1533 3.13505 7.84949 2.99712 7.51543C2.85918 7.18138 2.78889 6.82363 2.79024 6.46261L5.55979 6.47284L5.54949 9.22195Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-9-inside-9_80_18)"/>
</svg>
</t>
<t t-if="val['type'] == 'donut'">
<svg style="margin:0px 10px" xmlns="http://www.w3.org/2000/svg" width="16"
height="14" viewBox="0 0 12 12" fill="none">
<mask id="path-1-inside-1_68_17" fill="white">
<path d="M2.18445 1.3695C1.22446 2.16053 0.534062 3.23037 0.20878 4.431C-0.116503 5.63162 -0.0605855 6.90367 0.368794 8.07112C0.798174 9.23857 1.57979 10.2437 2.60548 10.9474C3.63118 11.6512 4.85024 12.0188 6.094 11.9993L6.066 10.2122C5.19273 10.2259 4.33679 9.96784 3.61663 9.47373C2.89646 8.97961 2.34767 8.27388 2.04619 7.45418C1.74471 6.63449 1.70545 5.74135 1.93384 4.89837C2.16223 4.05538 2.64698 3.30421 3.32101 2.74881L2.18445 1.3695Z"/>
</mask>
<path d="M2.18445 1.3695C1.22446 2.16053 0.534062 3.23037 0.20878 4.431C-0.116503 5.63162 -0.0605855 6.90367 0.368794 8.07112C0.798174 9.23857 1.57979 10.2437 2.60548 10.9474C3.63118 11.6512 4.85024 12.0188 6.094 11.9993L6.066 10.2122C5.19273 10.2259 4.33679 9.96784 3.61663 9.47373C2.89646 8.97961 2.34767 8.27388 2.04619 7.45418C1.74471 6.63449 1.70545 5.74135 1.93384 4.89837C2.16223 4.05538 2.64698 3.30421 3.32101 2.74881L2.18445 1.3695Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-1-inside-1_68_17)"/>
<mask id="path-2-inside-2_68_17" fill="white">
<path d="M8.67954 0.631568C7.7261 0.155676 6.66311 -0.0577065 5.59987 0.0133566C4.53663 0.0844197 3.5115 0.437365 2.62987 1.03591L3.63612 2.51808C4.25451 2.09825 4.97356 1.85069 5.71934 1.80084C6.46512 1.75099 7.21072 1.90067 7.87949 2.23447L8.67954 0.631568Z"/>
</mask>
<path d="M8.67954 0.631568C7.7261 0.155676 6.66311 -0.0577065 5.59987 0.0133566C4.53663 0.0844197 3.5115 0.437365 2.62987 1.03591L3.63612 2.51808C4.25451 2.09825 4.97356 1.85069 5.71934 1.80084C6.46512 1.75099 7.21072 1.90067 7.87949 2.23447L8.67954 0.631568Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-2-inside-2_68_17)"/>
<mask id="path-3-inside-3_68_17" fill="white">
<path d="M11.9078 7.04772C12.114 5.8851 11.9726 4.68749 11.5012 3.60489C11.0299 2.52229 10.2496 1.60282 9.25808 0.961654L8.28528 2.466C8.98075 2.91572 9.52807 3.56066 9.85868 4.32002C10.1893 5.07938 10.2885 5.91941 10.1439 6.7349L11.9078 7.04772Z"/>
</mask>
<path d="M11.9078 7.04772C12.114 5.8851 11.9726 4.68749 11.5012 3.60489C11.0299 2.52229 10.2496 1.60282 9.25808 0.961654L8.28528 2.466C8.98075 2.91572 9.52807 3.56066 9.85868 4.32002C10.1893 5.07938 10.2885 5.91941 10.1439 6.7349L11.9078 7.04772Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-3-inside-3_68_17)"/>
<mask id="path-4-inside-4_68_17" fill="white">
<path d="M6.87009 11.9366C8.02748 11.7669 9.11005 11.2627 9.98461 10.4859C10.8592 9.70901 11.4876 8.69347 11.7925 7.56416L10.063 7.09713C9.84911 7.88926 9.40833 8.60158 8.79489 9.14647C8.18146 9.69137 7.42212 10.0451 6.6103 10.164L6.87009 11.9366Z"/>
</mask>
<path d="M6.87009 11.9366C8.02748 11.7669 9.11005 11.2627 9.98461 10.4859C10.8592 9.70901 11.4876 8.69347 11.7925 7.56416L10.063 7.09713C9.84911 7.88926 9.40833 8.60158 8.79489 9.14647C8.18146 9.69137 7.42212 10.0451 6.6103 10.164L6.87009 11.9366Z"
stroke="#A8A8A8" stroke-width="4" mask="url(#path-4-inside-4_68_17)"/>
</svg>
</t>
</t>
</div>
</div>
</t>
</div>
</div>
</t>
</templates>

View File

@ -385,7 +385,8 @@
<t t-name="ks_to_do_dashboard_container"> <t t-name="ks_to_do_dashboard_container">
<div class="grid-stack-item" t-att-id="item_id"> <div class="grid-stack-item" t-att-id="item_id">
<div class="grid-stack-item-content ks_list_view_container ks_dashboard_item_hover card shadow"> <div class="grid-stack-item-content ks_list_view_container ks_dashboard_item_hover card shadow"
t-att-title="ks_info">
<div class="ks_card_header"> <div class="ks_card_header">
<div class="p-3 py-3 d-flex flex-row align-items-center justify-content-between "> <div class="p-3 py-3 d-flex flex-row align-items-center justify-content-between ">
<div class="d-flex align-items-center w-50"> <div class="d-flex align-items-center w-50">
@ -393,11 +394,11 @@
<t t-esc="ks_chart_title"/> <t t-esc="ks_chart_title"/>
</h6> </h6>
</div> </div>
<t t-if="ksIsDashboardManager">
<!-- Dashboard Item Move/Copy Feature -->
<div class="ks_dashboard_item_button_container ks_dropdown_container ks_dashboard_item_header ks_dashboard_item_header_hover chart_button_container"
t-att-data-item_id="item_id">
<!-- Dashboard Item Move/Copy Feature -->
<div class="ks_dashboard_item_button_container ks_dropdown_container ks_dashboard_item_header ks_dashboard_item_header_hover chart_button_container d-md-flex d-none"
t-att-data-item_id="item_id">
<t t-if="ksIsDashboardManager">
<button title="Move/Duplicate" data-toggle="dropdown" <button title="Move/Duplicate" data-toggle="dropdown"
t-att-data-item-id="item_id" t-att-data-item-id="item_id"
t-att-style="'color:'+ ks_rgba_button_color + ' !important' + ';'" t-att-style="'color:'+ ks_rgba_button_color + ' !important' + ';'"
@ -447,31 +448,75 @@
title="Remove Item" type="button"> title="Remove Item" type="button">
<i class="fa fa-times"/> <i class="fa fa-times"/>
</button> </button>
</t>
<t t-if="ksIsUser">
<div class="ks_chart_inner_buttons"> <div class="ks_chart_inner_buttons">
<button title="Export List" data-toggle="dropdown" <button title="Export List" data-toggle="dropdown"
class="ks_dashboard_item_action_export text-white btn dropdown-toggle btn-xs o-no-caret btn" class="ks_dashboard_item_action_export text-white btn dropdown-toggle btn-xs o-no-caret btn"
t-att-style="'color:'+ ks_rgba_button_color + ' !important' + ';'" t-att-style="'color:'+ ks_rgba_button_color + ' !important' + ';'"
type="button" type="button"
aria-expanded="true"> aria-expanded="true">
<i class="fa fa-ellipsis-v"/> <i class="fa fa-ellipsis-v"/>
</button> </button>
<div role="menu" class="dropdown-menu dropdown-menu-right"> <div role="menu" class="dropdown-menu dropdown-menu-right">
<!--Dynamic Rendering--> <!--Dynamic Rendering-->
<div class="ks_chart_export_menu"> <div class="ks_chart_export_menu">
<div class="ks_chart_export_menu_header"> <div class="ks_chart_export_menu_header">
<span>Export</span> <span>Export</span>
</div> </div>
<div class="ks_chart_json_export ks_chart_export_menu_item" <div class="ks_chart_json_export ks_chart_export_menu_item"
t-att-data-item-id="item_id" t-att-data-item-id="item_id"
data-format="chart_xls"> data-format="chart_xls">
<i class="fa fa-file-code-o"/> <i class="fa fa-file-code-o"/>
<span>Export Item</span> <span>Export Item</span>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</t>
<div class="ks_chart_inner_buttons dropdown">
<button title="Info" data-toggle="dropdown"
class="ks_item_description btn dropdown-toggle btn-xs o-no-caret btn"
type="button"
t-att-style="'color:'+ ks_rgba_button_color + ';'"
aria-expanded="true">
<i class="fa fa-book"/>
</button>
<div role="menu" class="dropdown-menu dropdown-menu-right" style="width:20rem">
<!--Dynamic Rendering-->
<div class="ks_chart_export_menu">
<div class="ks_chart_export_menu_header" style="margin-left:-10px">
<span>Info</span>
</div>
<div class="ks_info" style="margin-left:10px">
<span>Company: <t t-esc="ks_company"/></span>
</div>
<div class="ks_info" style="margin-left:10px">
<t t-if="ks_info">
<t t-foreach="ks_info" t-as="ks_description">
<span><t t-esc="ks_description"/></span> <br></br>
</t>
</t>
</div>
</div>
</div>
</div>
</div>
<t t-if="ksIsDashboardManager">
<div class="dropdown d-md-none dn-setting-panel">
<button class="btn btn-secondary border-0" type="button" id="dropdownSettingButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" >
<i class="fa fa-cog"></i>
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownSettingButton">
<a class="dropdown-item ks_dashboard_item_customize" >
<i class="fa fa-pencil"></i> Customize Item
</a>
<a class="dropdown-item ks_dashboard_item_delete" >
<i class="fa fa-times"></i> Remove Item
</a>
</div>
</div>
</t> </t>
</div> </div>

View File

@ -0,0 +1,65 @@
<odoo>
<data>
<record id="ks_dashboard_ninja_ai_form_view" model="ir.ui.view">
<field name="name">ks_dashboard_ninja.arti_int form</field>
<field name="model">ks_dashboard_ninja.arti_int</field>
<field name="arch" type="xml">
<form string="AI Dashboard" class="ks_import_dashboard_d_none">
<group>
<group>
<field name="ks_type" string="Generate with" required="1"/>
</group>
<group>
<field name="ks_import_model_id"
string="Model" attrs="{'invisible': [('ks_type','=','ks_keyword')],
'required': [('ks_type','=','ks_model')]}"/>
<field name="ks_import_model" string="Model" attrs="{'invisible':[('ks_model_show','=',False)],
'required':[('ks_model_show','=',True)]}"/>
</group>
<group>
<field name="ks_input_keywords"
string="Keywords"
widget="ks_keyword_selection"
attrs="{'invisible': [('ks_type','=','ks_model')],
'required': [('ks_type','=','ks_keyword')]}"/>
<field name="ks_model_show"
attrs="{'invisible': ['|',('ks_type','=','ks_keyword'),('ks_type','=','ks_model')]}"/>
<!-- <div attrs="{'invisible':[('ks_model_show','=',False)],'required':[('ks_model_show','=',True)]}">-->
<!-- Please select model first.-->
<!-- </div>-->
</group>
</group>
<footer>
<button name="ks_do_action"
string="Generate with AI"
type="object"
attrs="{'invisible': [('ks_type','=','ks_keyword')]}"
class="btn-primary"/>
<button name="ks_generate_item"
string="Generate Item"
attrs="{'invisible': [('ks_type','=','ks_model')]}"
type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="ks_dashboard_ninja_ai_action" model="ir.actions.act_window">
<field name="name">AI Dashboard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ks_dashboard_ninja.arti_int</field>
<field name="view_mode">form</field>
<field name="view_id" ref="ks_dashboard_ninja_ai_form_view"/>
<field name="target">new</field>
</record>
</data>
</odoo>

View File

@ -9,12 +9,15 @@
<link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_dn_filter.css"/> <link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_dn_filter.css"/>
<link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_toggle_icon.css"/> <link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_toggle_icon.css"/>
<link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_dashboard_options.css"/> <link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_dashboard_options.css"/>
<link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_input_bar.css"/>
<link rel="stylesheet" href="/ks_dashboard_ninja/static/src/css/ks_ai_dash.css"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_global_functions.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_global_functions.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_to_do_dashboard.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_filter_props.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_filter_props.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_color_picker.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_color_picker.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_create_dashboard_dialog.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_item_preview.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_item_preview.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_image_basic_widget.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_image_basic_widget.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_item_theme.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_item_theme.js"/>
@ -23,6 +26,8 @@
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_domain_fix.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_domain_fix.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_quick_edit_view.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_quick_edit_view.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_kpi_preview.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_kpi_preview.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_keyword_selection.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_ai_dash_action.js"/>
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_date_picker.js"/> <script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_date_picker.js"/>
<!-- for some reason gridstack css is not laoding from the js. #FIXME--> <!-- for some reason gridstack css is not laoding from the js. #FIXME-->
@ -51,4 +56,16 @@
</xpath> </xpath>
</template> </template>
<template id="ks_dn_load_assets_en" priority="100" active="False" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_create_dashboard_dialog_en.js"/>
</xpath>
</template>
<template id="ks_dn_load_assets" priority="101" active="False" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/ks_dashboard_ninja/static/src/js/ks_create_dashboard_dialog.js"/>
</xpath>
</template>
</odoo> </odoo>

View File

@ -17,7 +17,6 @@
<field name="ks_item_end_date"/> <field name="ks_item_end_date"/>
<field name="ks_compare_period"/> <field name="ks_compare_period"/>
<field name="ks_year_period"/> <field name="ks_year_period"/>
<field name="ks_update_items_data"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -104,7 +103,6 @@
['ks_kpi','ks_tile','ks_bar_chart','ks_horizontalBar_chart','ks_line_chart','ks_area_chart','ks_pie_chart', ['ks_kpi','ks_tile','ks_bar_chart','ks_horizontalBar_chart','ks_line_chart','ks_area_chart','ks_pie_chart',
'ks_doughnut_chart','ks_polarArea_chart','ks_list_view'])]}"/> 'ks_doughnut_chart','ks_polarArea_chart','ks_list_view'])]}"/>
<field name="ks_dashboard_item_type" invisible="1"/> <field name="ks_dashboard_item_type" invisible="1"/>
<field name="ks_update_items_data" attrs="{'invisible':[('ks_dashboard_item_type','=', 'ks_to_do')]}" placeholder="Item Update Interval.."/>
</group> </group>
<group attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_tile'),('ks_dashboard_item_type','!=','ks_kpi')]}" <group attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_tile'),('ks_dashboard_item_type','!=','ks_kpi')]}"
@ -190,12 +188,14 @@
<field name="ks_domain_extension" invisible="1"/> <field name="ks_domain_extension" invisible="1"/>
<field name="ks_data_calculation_type" invisible="1"/> <field name="ks_data_calculation_type" invisible="1"/>
<field name="ks_kpi_data" invisible="1"/> <field name="ks_kpi_data" invisible="1"/>
<field name="ks_tile_data" invisible="1"/>
<field name="ks_many2many_field_ordering" invisible="1"/> <field name="ks_many2many_field_ordering" invisible="1"/>
<field name="ks_many2many_field_ordering" invisible="1"/> <field name="ks_many2many_field_ordering" invisible="1"/>
<field name="ks_export_all_records" invisible="1"/> <field name="ks_export_all_records" invisible="1"/>
<!-- <field name="ks_company_id" invisible="1"/>--> <!-- <field name="ks_company_id" invisible="1"/>-->
<!-- <field name="ks_hide_legend" invisible="1"/>--> <!-- <field name="ks_hide_legend" invisible="1"/>-->
<field name="name"/> <field name="name"/>
<!-- <field name="ks_info"/>-->
<field name="ks_model_id" <field name="ks_model_id"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}" options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"
context="{'current_id': id}" context="{'current_id': id}"
@ -332,6 +332,9 @@
<field name="ks_fill_temporal" <field name="ks_fill_temporal"
context="{'current_id': id}" context="{'current_id': id}"
attrs="{'invisible':['|','|','|',('ks_dashboard_item_type','in',['ks_list_view','ks_kpi', 'ks_tile']),('ks_chart_groupby_type','!=','date_type'),('ks_chart_date_groupby','in',['minute','hour']),('ks_chart_relation_sub_groupby','!=',False)]}"/> attrs="{'invisible':['|','|','|',('ks_dashboard_item_type','in',['ks_list_view','ks_kpi', 'ks_tile']),('ks_chart_groupby_type','!=','date_type'),('ks_chart_date_groupby','in',['minute','hour']),('ks_chart_relation_sub_groupby','!=',False)]}"/>
<field name="ks_as_of_now"
context="{'current_id': id}"
attrs="{'invisible':['|','|','|',('ks_dashboard_item_type','in',['ks_list_view','ks_kpi', 'ks_tile']),('ks_chart_groupby_type','!=','date_type'),('ks_chart_date_groupby','in',['minute','hour']),('ks_chart_relation_sub_groupby','!=',False)]}"/>
<field name="ks_chart_relation_sub_groupby" <field name="ks_chart_relation_sub_groupby"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}" options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"
@ -346,7 +349,8 @@
<field name="ks_sort_by_order" <field name="ks_sort_by_order"
context="{'current_id': id}" context="{'current_id': id}"
attrs="{'invisible':['|',('ks_fill_temporal','=',True),'&amp;',('ks_goal_lines','!=',[]),('ks_goal_enable','=',True)]}"/> attrs="{'invisible':['|',('ks_fill_temporal','=',True),'&amp;',('ks_goal_lines','!=',[]),('ks_goal_enable','=',True)]}"/>
<field name="ks_record_data_limit_visibility" attrs="{'invisible':[('ks_goal_lines','!=',[]),('ks_goal_enable','=',True)]}"/> <field name="ks_record_data_limit_visibility"
attrs="{'invisible':[('ks_goal_lines','!=',[]),('ks_goal_enable','=',True)]}"/>
<field name="ks_record_data_limit" <field name="ks_record_data_limit"
context="{'current_id': id}" context="{'current_id': id}"
attrs="{'invisible':['|','|','&amp;',('ks_chart_relation_sub_groupby','!=',False),('ks_dashboard_item_type','not in', ['ks_bar_chart','ks_horizontalBar_chart','ks_line_chart','ks_area_chart', attrs="{'invisible':['|','|','&amp;',('ks_chart_relation_sub_groupby','!=',False),('ks_dashboard_item_type','not in', ['ks_bar_chart','ks_horizontalBar_chart','ks_line_chart','ks_area_chart',
@ -426,6 +430,11 @@
context="{'current_id':id}" context="{'current_id':id}"
attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_list_view', 'ks_pie_chart', 'ks_doughnut_chart', 'ks_polarArea_chart'])]}" attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_list_view', 'ks_pie_chart', 'ks_doughnut_chart', 'ks_polarArea_chart'])]}"
/> />
<field name="ks_unit"/>
<field name="ks_unit_selection" attrs="{'invisible':[('ks_unit','=',False)],
'required':[('ks_unit','=',True)]}"/>
<field name="ks_currency_id" attrs="{'invisible':['|','|',('ks_unit_selection','!=','custom'),('ks_unit','=',False),('ks_dashboard_item_type', 'not in', ['ks_tile','ks_kpi'])],
'required':[('ks_unit_selection','=','custom'),('ks_unit','=',True),('ks_dashboard_item_type', 'in', ['ks_tile','ks_kpi'])]}"/>
<field name="ks_layout" <field name="ks_layout"
attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_tile')]}"/> attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_tile')]}"/>
@ -449,7 +458,7 @@
attrs="{'invisible':['|','|','|',('ks_dashboard_item_type','=','ks_tile'),('ks_dashboard_item_type','=','ks_to_do'),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','=','ks_kpi')]}"> attrs="{'invisible':['|','|','|',('ks_dashboard_item_type','=','ks_tile'),('ks_dashboard_item_type','=','ks_to_do'),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','=','ks_kpi')]}">
<field name="ks_data_format" <field name="ks_data_format"
context="{'current_id':id}" context="{'current_id':id}"
attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_list_view', 'ks_pie_chart', 'ks_doughnut_chart', 'ks_polarArea_chart'])]}" attrs="{'invisible':['!',('ks_dashboard_item_type','in',['ks_list_view']),('ks_data_label_type','=','percent')]}"
/> />
<field name="ks_chart_item_color" string="Chart Color Palette" <field name="ks_chart_item_color" string="Chart Color Palette"
context="{'current_id': id}" context="{'current_id': id}"
@ -458,11 +467,13 @@
context="{'current_id': id}" context="{'current_id': id}"
attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_dashboard_item_type','!=','ks_horizontalBar_chart')]}"/> attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_dashboard_item_type','!=','ks_horizontalBar_chart')]}"/>
<field name="ks_show_data_value"/> <field name="ks_show_data_value"/>
<field name="ks_data_label_type"
attrs="{'invisible': ['|',('ks_show_data_value', '=', False), ('ks_dashboard_item_type', 'not in', ['ks_pie_chart', 'ks_doughnut_chart', 'ks_polarArea_chart'])]}"/>
<field name="ks_unit"/> <field name="ks_unit"/>
<field name="ks_unit_selection" attrs="{'invisible':[('ks_unit','=',False)], <field name="ks_unit_selection" attrs="{'invisible':[('ks_unit','=',False)],
'required':[('ks_unit','=',True)]}"/> 'required':[('ks_unit','=',True)]}"/>
<field name="ks_chart_unit" attrs="{'invisible':['|',('ks_unit_selection','!=','custom'),('ks_unit','=',False)], <field name="ks_chart_unit" attrs="{'invisible':['|','|',('ks_unit_selection','!=','custom'),('ks_unit','=',False),('ks_dashboard_item_type', 'in', ['ks_tile','ks_kpi'])],
'required':[('ks_unit_selection','=','custom'),('ks_unit','=',True)]}"/> 'required':[('ks_unit_selection','=','custom'),('ks_unit','=',True),('ks_dashboard_item_type', 'not in', ['ks_tile','ks_kpi'])]}"/>
</group> </group>
<group> <group>
<field name="ks_header_bg_color" widget="ks_color_dashboard_picker" <field name="ks_header_bg_color" widget="ks_color_dashboard_picker"
@ -515,8 +526,8 @@
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}" options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"
attrs="{'invisible':['|',('ks_dashboard_item_type','=','ks_list_view'),('ks_is_client_action','=',False)], 'required':[('ks_is_client_action','=', True)]}"/> attrs="{'invisible':['|',('ks_dashboard_item_type','=','ks_list_view'),('ks_is_client_action','=',False)], 'required':[('ks_is_client_action','=', True)]}"/>
<!-- <field name="ks_show_records" force_save="1"--> <!-- <field name="ks_show_records" force_save="1"-->
<!-- attrs="{'invisible': [('ks_data_calculation_type','!=','custom')]}"/>--> <!-- attrs="{'invisible': [('ks_data_calculation_type','!=','custom')]}"/>-->
</group> </group>
</page> </page>
<page string="Target" name="target_settings" <page string="Target" name="target_settings"
@ -532,7 +543,8 @@
attrs="{'invisible' : ['|',('ks_goal_enable','=',False),('ks_dashboard_item_type','!=','ks_kpi')]}"/> attrs="{'invisible' : ['|',('ks_goal_enable','=',False),('ks_dashboard_item_type','!=','ks_kpi')]}"/>
</group> </group>
<div attrs="{'invisible' : ['|','|',('ks_goal_enable','=',False),('ks_dashboard_item_type','=','ks_kpi'),('ks_chart_relation_sub_groupby','!=',False)]}"> <div attrs="{'invisible' : ['|','|',('ks_goal_enable','=',False),('ks_dashboard_item_type','=','ks_kpi'),('ks_chart_relation_sub_groupby','!=',False)]}">
All Target Lines Changes Will be reflected on Chart after saving the record and pagination will be ignore . All Target Lines Changes Will be reflected on Chart after saving the record and
pagination will be ignore .
</div> </div>
<field name="ks_goal_lines" <field name="ks_goal_lines"
attrs="{'invisible' : ['|','|',('ks_goal_enable','=',False),('ks_dashboard_item_type','=','ks_kpi'),('ks_chart_relation_sub_groupby','!=',False)]}"> attrs="{'invisible' : ['|','|',('ks_goal_enable','=',False),('ks_dashboard_item_type','=','ks_kpi'),('ks_chart_relation_sub_groupby','!=',False)]}">
@ -547,46 +559,52 @@
</tree> </tree>
</field> </field>
</page> </page>
<page string="Auto Update" attrs="{'invisible': [('ks_dashboard_item_type','=','ks_to_do')]}">
<group> <page string="Advance Configuration" name="adv_conf"
<field name="ks_auto_update_type" widget="radio"/> attrs="{'invisible':[('ks_dashboard_item_type','=','ks_to_do')]}">
<field name="ks_update_items_data" string="Set Update Interval"
context="{'current_id': id}"
attrs="{'invisible':[('ks_auto_update_type','!=','ks_update_interval')], 'required':[('ks_auto_update_type','=','ks_update_interval')]}"/>
<field name="ks_show_live_pop_up"
attrs="{'invisible':[('ks_auto_update_type','!=','ks_live_update')]}"/>
</group>
</page>
<page string="Advance Configuration" attrs="{'invisible':[('ks_dashboard_item_type','=','ks_to_do')]}">
<group attrs="{'invisible':['|','|',('ks_dashboard_item_type','=','ks_to_do'),('ks_dashboard_item_type','=','ks_tile'),('ks_dashboard_item_type','=','ks_kpi')]}"> <group attrs="{'invisible':['|','|',('ks_dashboard_item_type','=','ks_to_do'),('ks_dashboard_item_type','=','ks_tile'),('ks_dashboard_item_type','=','ks_kpi')]}">
<field name="ks_hide_legend" context="{'current_id': id}" <field name="ks_hide_legend" context="{'current_id': id}"
attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_tile', 'ks_kpi', 'ks_list_view'])]}"/> attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_tile', 'ks_kpi', 'ks_list_view'])]}"/>
<field name="ks_chart_cumulative_field" widget='many2many_tags' <field name="ks_chart_cumulative_field" widget='many2many_tags'
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}" options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"
attrs="{'invisible':['|','|','|','|','|',('ks_chart_data_count_type','=','count'),('ks_chart_relation_sub_groupby','!=',False),('ks_model_id','=',False),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_data_calculation_type','!=','custom')], 'required': [('ks_chart_cumulative','=',True)]}" attrs="{'invisible':['|','|','|','|','|',('ks_chart_data_count_type','=','count'),('ks_chart_relation_sub_groupby','!=',False),('ks_model_id','=',False),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_data_calculation_type','!=','custom')]}"
domain="[('id', 'in', ks_chart_measure_field)]"/> domain="[('id', 'in', ks_chart_measure_field)]"/>
<field name="ks_chart_is_cumulative"
attrs="{'invisible':['|','|','|','|','|',('ks_chart_data_count_type','!=','count'),('ks_chart_relation_sub_groupby','!=',False),('ks_model_id','=',False),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_data_calculation_type','!=','custom')], 'required': [('ks_chart_cumulative','=',True)]}"
/>
<field name="ks_chart_cumulative" <field name="ks_chart_cumulative"
attrs="{'invisible':['|','|','|','|','|',('ks_chart_data_count_type','=','count'),('ks_chart_relation_sub_groupby','!=',False),('ks_model_id','=',False),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_data_calculation_type','!=','custom')]}"/> attrs="{'invisible':['|','|','|','|',('ks_chart_relation_sub_groupby','!=',False),('ks_model_id','=',False),('ks_dashboard_item_type','=','ks_list_view'),('ks_dashboard_item_type','!=','ks_bar_chart'),('ks_data_calculation_type','!=','custom')]}"/>
<field name="ks_pagination_limit" <field name="ks_pagination_limit"
attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_list_view')],'required':[('ks_dashboard_item_type','=','ks_list_view')]}"/> attrs="{'invisible':[('ks_dashboard_item_type','!=','ks_list_view')],'required':[('ks_dashboard_item_type','=','ks_list_view')]}"/>
<field name="ks_show_records" force_save="1" <!-- <field name="ks_show_records" force_save="1"-->
attrs="{'invisible': [('ks_data_calculation_type','=','query')]}"/> <!-- attrs="{'invisible': [('ks_data_calculation_type','=','query')]}"/>-->
<field name="ks_multiplier_active" force_save="1" <field name="ks_multiplier_active" force_save="1"
attrs="{'invisible': ['|','|','&amp;',('ks_dashboard_item_type','=','ks_list_view'),('ks_list_view_type','=','ungrouped'),('ks_data_calculation_type','=','query'),'&amp;',('ks_dashboard_item_type','in',['ks_list_view','ks_bar_chart','ks_pie_chart','ks_to_do','ks_line_chart', 'ks_area_chart', 'ks_horizontalBar_chart','ks_doughnut_chart','ks_polarArea_chart']),('ks_chart_data_count_type', '=', 'count')]}"/> attrs="{'invisible': ['|','|','&amp;',('ks_dashboard_item_type','=','ks_list_view'),('ks_list_view_type','=','ungrouped'),('ks_data_calculation_type','=','query'),'&amp;',('ks_dashboard_item_type','in',['ks_list_view','ks_bar_chart','ks_pie_chart','ks_to_do','ks_line_chart', 'ks_area_chart', 'ks_horizontalBar_chart','ks_doughnut_chart','ks_polarArea_chart']),('ks_chart_data_count_type', '=', 'count')]}"/>
<field name="ks_multiplier_lines" attrs="{'invisible':[('ks_multiplier_active','=',False)]}"> <field name="ks_multiplier_lines"
<tree editable="bottom" create="false" delete="false"> attrs="{'invisible':[('ks_multiplier_active','=',False)]}">
<tree editable="bottom" create="false" delete="false">
<field name="ks_model_id" invisible="1"/> <field name="ks_model_id" invisible="1"/>
<field name="ks_multiplier_fields" readonly="1" options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/> <field name="ks_multiplier_fields" readonly="1"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
<field name="ks_multiplier_value"/> <field name="ks_multiplier_value"/>
</tree> </tree>
</field> </field>
</group> </group>
<group>
<field name="ks_show_records" force_save="1"
attrs="{'invisible': [('ks_data_calculation_type','=','query')]}"/>
</group>
<group attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_list_view','ks_bar_chart','ks_pie_chart','ks_to_do','ks_line_chart', 'ks_area_chart', 'ks_horizontalBar_chart','ks_doughnut_chart','ks_polarArea_chart'])]}"> <group attrs="{'invisible':[('ks_dashboard_item_type','in',['ks_list_view','ks_bar_chart','ks_pie_chart','ks_to_do','ks_line_chart', 'ks_area_chart', 'ks_horizontalBar_chart','ks_doughnut_chart','ks_polarArea_chart'])]}">
<field name="ks_multiplier_active" force_save="1"/> <field name="ks_multiplier_active" force_save="1"/>
<field name="ks_multiplier" attrs="{'invisible':[('ks_multiplier_active','=',False)]}"/> <field name="ks_multiplier" attrs="{'invisible':[('ks_multiplier_active','=',False)]}"/>
</group> </group>
</page> </page>
<page string="Item Description" name="ks_item_description">
<group>
<field name="ks_info"/>
</group>
</page>
</notebook> </notebook>
</form> </form>
</field> </field>

View File

@ -5,7 +5,7 @@
<field name="name">ks_dashboard_ninja View</field> <field name="name">ks_dashboard_ninja View</field>
<field name="model">ks_dashboard_ninja.board</field> <field name="model">ks_dashboard_ninja.board</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Dashboards"> <form string="Dashboards" duplicate="false">
<sheet> <sheet>
<group> <group>
<group> <group>
@ -64,7 +64,6 @@
</group> </group>
<group> <group>
<field name="ks_date_filter_selection" required="1"/> <field name="ks_date_filter_selection" required="1"/>
<field name="ks_set_interval"/>
<field name="ks_dashboard_start_date" <field name="ks_dashboard_start_date"
attrs="{'invisible':[('ks_date_filter_selection','!=','l_custom')],'required':[('ks_date_filter_selection','=','l_custom')]}"/> attrs="{'invisible':[('ks_date_filter_selection','!=','l_custom')],'required':[('ks_date_filter_selection','=','l_custom')]}"/>
<field name="ks_dashboard_end_date" <field name="ks_dashboard_end_date"
@ -72,6 +71,12 @@
</group> </group>
</group> </group>
</page> </page>
<page string="Auto Update" name="update_settings" >
<group>
<field name="ks_set_interval"/>
</group>
</page>
</notebook> </notebook>
</sheet> </sheet>
</form> </form>

View File

@ -0,0 +1,37 @@
<odoo>
<data>
<record id="ks_fetch_key_form_view" model="ir.ui.view">
<field name="name">ks_dashboard_ninja.fetch_key_form</field>
<field name="model">ks_dashboard_ninja.fetch_key</field>
<field name="arch" type="xml">
<form string="Fetch API key">
<group>
<group>
<field name="ks_email_id" required="1"/>
<field name="ks_api_key" attrs="{'invisible':[('ks_show_api_key','=',False)]}" widget="CopyClipboardChar"/>
<field name="ks_show_api_key" invisible="1"/>
</group>
</group>
<footer>
<button name="ks_fetch_details" string="Fetch Key" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="ks_fetch_key" model="ir.actions.act_window">
<field name="name">Fetch API key</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ks_dashboard_ninja.fetch_key</field>
<field name="view_mode">form</field>
<field name="view_id" ref="ks_fetch_key_form_view"></field>
<field name="target">new</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,42 @@
<odoo>
<data>
<record id="ks_ai_whole_dashboard_form_view" model="ir.ui.view">
<field name="name">ks_dashboard_ninja.ai.dashboard form</field>
<field name="model">ks_dashboard_ninja.ai_dashboard</field>
<field name="arch" type="xml">
<form string="AI Dashboard" class="ks_import_dashboard_d_none">
<group>
<group>
<field name="ks_import_model_id" string="Model"/>
<field name='ks_dash_name'/>
</group>
<group>
<field name="ks_menu_name"/>
<field name="ks_top_menu_id"/>
<field name="ks_template" invisible="1"/>
</group>
</group>
<footer>
<button name="ks_do_action" string="Generate dashboard with AI" type="object"
class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="ks_dashboard_ninja_ai_dashboardaction" model="ir.actions.act_window">
<field name="name">AI whole Dashboard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ks_dashboard_ninja.ai_dashboard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="ks_ai_whole_dashboard_form_view"/>
<field name="target">new</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="res_config_settings_inherit_view" model="ir.ui.view">
<field name="name">res.config.settings.inherit.view</field>
<field name="model">res.config.settings</field>
<field name="inherit_id"
ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='invite_users']" position="after">
<div id="dashboard_api_key">
<h2>Dashboard API Key</h2>
<div class="row mt16 o_settings_container" name="dn_ai_api_key_container">
<div class="col-12 col-lg-6 o_setting_box" id="dn_ai_api_key">
<div class="o_setting_right_pane">
<label for="dn_api_key" class="col-sm-5 col-form-label">
Dashboard Ninja Api Key
</label>
<field name="dn_api_key"/>
<label for="ks_email_id" class="col-sm-5 col-form-label">
Email ID
</label>
<field name="ks_email_id"/>
<label for="url" class="col-sm-5 col-form-label">
URL
</label>
<field name="url"/>
<button name="Open_wizard" string="Get API key" type="object"
class="btn-primary"/>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@ -10,7 +10,7 @@ class KSCreateDashboardWizard(models.TransientModel):
name = fields.Char(string="Dashboard Name", required=True) name = fields.Char(string="Dashboard Name", required=True)
ks_menu_name = fields.Char(string="Menu Name", required=True) ks_menu_name = fields.Char(string="Menu Name", required=True)
ks_top_menu_id = fields.Many2one('ir.ui.menu', ks_top_menu_id = fields.Many2one('ir.ui.menu',
domain="['|',('action','=',False),('parent_id','=',False)]", domain="[('parent_id','=',False)]",
string="Show Under Menu", required=True, string="Show Under Menu", required=True,
default=lambda self: self.env['ir.ui.menu'].search( default=lambda self: self.env['ir.ui.menu'].search(
[('name', '=', 'My Dashboard')])) [('name', '=', 'My Dashboard')]))

View File

@ -7,7 +7,8 @@ class KSCreateDashboardWizard(models.TransientModel):
_name = 'ks.dashboard.duplicate.wizard' _name = 'ks.dashboard.duplicate.wizard'
_description = 'Duplicate Dashboard Wizard' _description = 'Duplicate Dashboard Wizard'
ks_top_menu_id = fields.Many2one('ir.ui.menu', string="Show Under Menu", required=True, ks_top_menu_id = fields.Many2one('ir.ui.menu', domain="[('parent_id','=',False)]", string="Show Under Menu",
required=True,
default=lambda self: self.env['ir.ui.menu'].search( default=lambda self: self.env['ir.ui.menu'].search(
[('name', '=', 'My Dashboard')])) [('name', '=', 'My Dashboard')]))
@ -19,9 +20,10 @@ class KSCreateDashboardWizard(models.TransientModel):
return action return action
def ks_duplicate_record(self): def ks_duplicate_record(self):
'''this function creats record of ks_dashboard_ninja.board and return dashboard action_id''' '''this function duplicates record of ks_dashboard_ninja.board and return dashboard action_id'''
dashboard_id = self._context.get('dashboard_id') dashboard_id = self._context.get('dashboard_id')
dup_dash = self.env['ks_dashboard_ninja.board'].browse(dashboard_id).copy({'ks_dashboard_top_menu_id': self.ks_top_menu_id.id}) dup_dash = self.env['ks_dashboard_ninja.board'].browse(dashboard_id).copy(
{'ks_dashboard_top_menu_id': self.ks_top_menu_id.id})
if dup_dash.ks_dashboard_menu_id.parent_id.parent_id: if dup_dash.ks_dashboard_menu_id.parent_id.parent_id:
top_menu_id = dup_dash.ks_dashboard_menu_id.parent_id.parent_id.id top_menu_id = dup_dash.ks_dashboard_menu_id.parent_id.parent_id.id
else: else:
@ -31,6 +33,8 @@ class KSCreateDashboardWizard(models.TransientModel):
if not dup_dash.ks_dashboard_items_ids: if not dup_dash.ks_dashboard_items_ids:
for item in dash_id.ks_dashboard_items_ids: for item in dash_id.ks_dashboard_items_ids:
item.sudo().copy({'ks_dashboard_ninja_board_id': dup_dash.id}) item.sudo().copy({'ks_dashboard_ninja_board_id': dup_dash.id})
# if self._context.get('gridstack_config'):
# dup_dash.ks_gridstack_config = json.dumps(self._context.get('gridstack_config'))
return { return {
'type': 'ir.actions.client', 'type': 'ir.actions.client',
'name': "Dashboard Ninja", 'name': "Dashboard Ninja",
@ -45,7 +49,6 @@ class KSDeleteDashboardWizard(models.TransientModel):
_name = 'ks.dashboard.delete.wizard' _name = 'ks.dashboard.delete.wizard'
_description = 'Delete Dashboard Wizard' _description = 'Delete Dashboard Wizard'
def DeleteDashBoard(self): def DeleteDashBoard(self):
'''this function returns acion id of ks.dashboard.duplicate.wizard''' '''this function returns acion id of ks.dashboard.duplicate.wizard'''
action = self.env['ir.actions.act_window']._for_xml_id( action = self.env['ir.actions.act_window']._for_xml_id(
@ -57,7 +60,8 @@ class KSDeleteDashboardWizard(models.TransientModel):
'''this function creats record of ks_dashboard_ninja.board and return dashboard action_id''' '''this function creats record of ks_dashboard_ninja.board and return dashboard action_id'''
dashboard_id = self._context.get('dashboard_id') dashboard_id = self._context.get('dashboard_id')
self.env['ks_dashboard_ninja.board'].browse(dashboard_id).unlink() self.env['ks_dashboard_ninja.board'].browse(dashboard_id).unlink()
context = {'ks_reload_menu': True, 'ks_top_menu_id': self.env['ir.ui.menu'].search([('name', '=', 'My Dashboard')]).id} context = {'ks_reload_menu': True,
'ks_top_menu_id': self.env['ir.ui.menu'].search([('name', '=', 'My Dashboard')], limit=1).id}
return { return {
'type': 'ir.actions.client', 'type': 'ir.actions.client',
'name': "Dashboard Ninja", 'name': "Dashboard Ninja",
@ -66,4 +70,3 @@ class KSDeleteDashboardWizard(models.TransientModel):
'tag': 'ks_dashboard_ninja', 'tag': 'ks_dashboard_ninja',
'context': self.with_context(context)._context 'context': self.with_context(context)._context
} }

View File

@ -1 +1,11 @@
from . import models from . import models
from odoo.api import Environment, SUPERUSER_ID
def ks_dna_uninstall_hook(cr, registry):
env = Environment(cr, SUPERUSER_ID, {})
for rec in env['ks_dashboard_ninja.item'].search([]):
if rec.ks_data_calculation_type == 'query':
rec.unlink()

View File

@ -93,7 +93,7 @@
'currency': 'EUR', 'currency': 'EUR',
'price': '111.75', 'price': '119.2',
'website': 'https://store.ksolves.com/', 'website': 'https://store.ksolves.com/',
@ -103,15 +103,20 @@
'category': 'Tools', 'category': 'Tools',
'version': '14.0.1.3.3', 'version': '14.0.1.5.1',
'support': 'sales@ksolves.com', 'support': 'sales@ksolves.com',
'images': ['static/description/banner.gif'], 'images': ['static/description/Independence_sale.jpg'],
'depends': ['ks_dashboard_ninja'], 'depends': ['ks_dashboard_ninja','mail'],
'data': ['views/ks_dashboard_tv_assets.xml', 'views/ks_dashboard_ninja_item_view_inherit.xml', 'views/ks_dashboard_form_view_inherit.xml'], 'data': ['views/ks_dashboard_tv_assets.xml',
'views/ks_dashboard_ninja_item_view_inherit.xml',
'views/ks_dashboard_form_view_inherit.xml',
'views/ks_mail_template.xml', ],
'qweb': ['static/src/xml/ks_dashboard_tv_ninja.xml', 'static/src/xml/ks_query_templates.xml', 'static/src/xml/ks_dna_to_template.xml'], 'qweb': ['static/src/xml/ks_dashboard_tv_ninja.xml', 'static/src/xml/ks_query_templates.xml', 'static/src/xml/ks_dna_to_template.xml'],
'uninstall_hook': 'ks_dna_uninstall_hook',
} }

Some files were not shown because too many files have changed in this diff Show More