1
15
ks_dashboard_ninja/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from . import controllers
|
||||||
|
from . import common_lib
|
||||||
|
from . import wizard
|
||||||
|
|
||||||
|
from odoo.api import Environment, SUPERUSER_ID
|
||||||
|
|
||||||
|
|
||||||
|
def uninstall_hook(env):
|
||||||
|
# env = Environment(cr, SUPERUSER_ID, {})
|
||||||
|
for rec in env['ks_dashboard_ninja.board'].search([]):
|
||||||
|
rec.ks_dashboard_client_action_id.unlink()
|
||||||
|
rec.ks_dashboard_menu_id.unlink()
|
||||||
197
ks_dashboard_ninja/__manifest__.py
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
{
|
||||||
|
'name': 'Dashboard Ninja with AI',
|
||||||
|
|
||||||
|
'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.
|
||||||
|
""",
|
||||||
|
|
||||||
|
'description': """
|
||||||
|
Dashboard Ninja v18.0,
|
||||||
|
Odoo Dashboard,
|
||||||
|
Dashboard,
|
||||||
|
Dashboards,
|
||||||
|
Odoo apps,
|
||||||
|
Dashboard app,
|
||||||
|
HR Dashboard,
|
||||||
|
Sales Dashboard,
|
||||||
|
inventory Dashboard,
|
||||||
|
Lead Dashboard,
|
||||||
|
Opportunity Dashboard,
|
||||||
|
CRM Dashboard,
|
||||||
|
POS,
|
||||||
|
POS Dashboard,
|
||||||
|
Connectors,
|
||||||
|
Web Dynamic,
|
||||||
|
Report Import/Export,
|
||||||
|
Date Filter,
|
||||||
|
HR,
|
||||||
|
Sales,
|
||||||
|
Theme,
|
||||||
|
Tile Dashboard,
|
||||||
|
Dashboard Widgets,
|
||||||
|
Dashboard Manager,
|
||||||
|
Debranding,
|
||||||
|
Customize Dashboard,
|
||||||
|
Graph Dashboard,
|
||||||
|
Charts Dashboard,
|
||||||
|
Invoice Dashboard,
|
||||||
|
Project management,
|
||||||
|
ksolves,
|
||||||
|
ksolves apps,
|
||||||
|
Ksolves India Ltd.
|
||||||
|
Ksolves India Limited,
|
||||||
|
odoo dashboard apps
|
||||||
|
odoo dashboard app
|
||||||
|
odoo dashboard module
|
||||||
|
odoo modules
|
||||||
|
dashboards
|
||||||
|
powerful dashboards
|
||||||
|
beautiful odoo dashboard
|
||||||
|
odoo dynamic dashboard
|
||||||
|
all in one dashboard
|
||||||
|
multiple dashboard menu
|
||||||
|
odoo dashboard portal
|
||||||
|
beautiful odoo dashboard
|
||||||
|
odoo best dashboard
|
||||||
|
dashboard for management
|
||||||
|
Odoo custom dashboard
|
||||||
|
odoo dashboard management
|
||||||
|
odoo dashboard apps
|
||||||
|
create odoo dashboard
|
||||||
|
odoo dashboard extension
|
||||||
|
odoo dashboard module
|
||||||
|
""",
|
||||||
|
|
||||||
|
'author': 'Ksolves India Ltd.',
|
||||||
|
|
||||||
|
'license': 'OPL-1',
|
||||||
|
|
||||||
|
'currency': 'EUR',
|
||||||
|
|
||||||
|
'price': '518.62',
|
||||||
|
|
||||||
|
'website': 'https://store.ksolves.com/',
|
||||||
|
|
||||||
|
'maintainer': 'Ksolves India Ltd.',
|
||||||
|
|
||||||
|
'live_test_url': 'https://ksdndemo18.kappso.com/web/demo_login',
|
||||||
|
|
||||||
|
'category': 'Services',
|
||||||
|
'version': '18.0.1.0.1',
|
||||||
|
|
||||||
|
|
||||||
|
'support': 'sales@ksolves.com',
|
||||||
|
|
||||||
|
'images': ['static/description/DN 5.gif'],
|
||||||
|
|
||||||
|
'depends': ['base', 'web', 'base_setup', 'bus', 'base_geolocalize', 'mail'],
|
||||||
|
|
||||||
|
'data': [
|
||||||
|
'security/ir.model.access.csv',
|
||||||
|
'security/ks_security_groups.xml',
|
||||||
|
'data/ks_default_data.xml',
|
||||||
|
'data/ks_mail_cron.xml',
|
||||||
|
'data/dn_data.xml',
|
||||||
|
'data/sequence.xml',
|
||||||
|
'views/res_settings.xml',
|
||||||
|
'views/ks_dashboard_ninja_view.xml',
|
||||||
|
'views/ks_dashboard_ninja_item_view.xml',
|
||||||
|
'views/ks_dashboard_group_by.xml',
|
||||||
|
'views/ks_dashboard_csv_group_by.xml',
|
||||||
|
'views/ks_dashboard_action.xml',
|
||||||
|
'views/ks_import_dashboard_view.xml',
|
||||||
|
'wizard/ks_create_dashboard_wiz_view.xml',
|
||||||
|
'wizard/ks_duplicate_dashboard_wiz_view.xml',
|
||||||
|
'views/ks_ai_dashboard.xml',
|
||||||
|
'views/ks_whole_ai_dashboard.xml',
|
||||||
|
'views/ks_key_fetch.xml',
|
||||||
|
'views/webExtend.xml'
|
||||||
|
],
|
||||||
|
|
||||||
|
'demo': ['demo/ks_dashboard_ninja_demo.xml'],
|
||||||
|
|
||||||
|
'assets': {
|
||||||
|
'web.assets_backend': [
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_dashboard_ninja.scss',
|
||||||
|
'/ks_dashboard_ninja/static/lib/css/gridstack.min.css',
|
||||||
|
'/ks_dashboard_ninja/static/lib/css/awesomplete.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_dashboard_ninja_item.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_icon_container_modal.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_dashboard_item_theme.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_input_bar.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_ai_dash.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_dn_filter.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_toggle_icon.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_flower_view.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_map_view.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_funnel_view.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_dashboard_options.css',
|
||||||
|
'/ks_dashboard_ninja/static/lib/js/gridstack-h5.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_new.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_global_functions.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/index.js',
|
||||||
|
'/ks_dashboard_ninja/static/lib/js/pdfmake.min.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/percent.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/pdf.min.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/print.min.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/Dataviz.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/Material.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/Moonrise.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/exporting.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/percent.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/Animated.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/worldLow.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/map.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/awesomplete.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dashboard_ninja_new.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_global_functions.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/xy.js',
|
||||||
|
'ks_dashboard_ninja/static/lib/js/radar.js',
|
||||||
|
'ks_dashboard_ninja/static/src/css/style.css',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_filter_props_new.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/domainfix.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_custom_dialog.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dashboard_graph_ai.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dashboard_kpi_ai.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dashboard_tile_ai.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dashboard_todo_ai.js',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_dashboard_ninja_pro.css',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_to_do_item.css',
|
||||||
|
'ks_dashboard_ninja/static/src/xml/**/*',
|
||||||
|
'ks_dashboard_ninja/static/src/css/ks_radial_chart.css',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_ai_dash_action.js',
|
||||||
|
'ks_dashboard_ninja/static/src/components/**/*',
|
||||||
|
'ks_dashboard_ninja/static/src/widgets/**/*',
|
||||||
|
'ks_dashboard_ninja/static/src/scss/variable.scss',
|
||||||
|
'ks_dashboard_ninja/static/src/scss/create_dashboard.scss',
|
||||||
|
'ks_dashboard_ninja/static/src/scss/common.scss',
|
||||||
|
'ks_dashboard_ninja/static/src/scss/header.scss',
|
||||||
|
'ks_dashboard_ninja/static/src/scss/overview.scss',
|
||||||
|
'ks_dashboard_ninja/static/src/scss/screen.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/explainAi.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/chartInsight.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/recentSearches.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/Generate-ai.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/chartScreen.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/generateAI.scss',
|
||||||
|
'/ks_dashboard_ninja/static/src/scss/form_view.scss',
|
||||||
|
'ks_dashboard_ninja/static/src/js/file_uploader_extend.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/formView&NotificationExtend.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/modalsExtend.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/loader_screen.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/dashboards_overview.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/chatWizard.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/dnNavBarExtend.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/chatWizardIntegration.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/custom_filter.js',
|
||||||
|
'ks_dashboard_ninja/static/src/js/ks_dropdown.js',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
'external_dependencies': {
|
||||||
|
'python': ['pandas', 'xlrd', 'openpyxl', 'gTTS', 'SQLAlchemy']
|
||||||
|
},
|
||||||
|
|
||||||
|
'uninstall_hook': 'uninstall_hook',
|
||||||
|
}
|
||||||
BIN
ks_dashboard_ninja/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
ks_dashboard_ninja/__pycache__/__init__.cpython-311.pyc
Normal file
1
ks_dashboard_ninja/common_lib/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from . import ks_date_filter_selections
|
||||||
343
ks_dashboard_ninja/common_lib/ks_date_filter_selections.py
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo.fields import datetime
|
||||||
|
from odoo import _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from datetime import timedelta
|
||||||
|
import pytz
|
||||||
|
import os
|
||||||
|
import ast
|
||||||
|
import os.path
|
||||||
|
from dateutil import rrule
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def ks_get_date(ks_date_filter_selection, self, type):
|
||||||
|
try:
|
||||||
|
timezone = self._context.get('tz')
|
||||||
|
except Exception as e:
|
||||||
|
timezone = self.env.user.tz
|
||||||
|
|
||||||
|
if not timezone:
|
||||||
|
ks_tzone = os.environ.get('TZ')
|
||||||
|
if ks_tzone:
|
||||||
|
timezone = ks_tzone
|
||||||
|
elif os.path.exists('/etc/timezone'):
|
||||||
|
ks_tzone = open('/etc/timezone').read()
|
||||||
|
timezone = ks_tzone[0:-1]
|
||||||
|
try:
|
||||||
|
datetime.now(pytz.timezone(timezone))
|
||||||
|
except Exception as e:
|
||||||
|
raise ValidationError(_("Please set the local timezone."))
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValidationError(_("Please set the local timezone."))
|
||||||
|
|
||||||
|
series = ks_date_filter_selection
|
||||||
|
if ks_date_filter_selection in ['t_fiscal_year', 'n_fiscal_year', 'ls_fiscal_year']:
|
||||||
|
function_name = globals()["ks_date_series_" + series.split("_")[0]]
|
||||||
|
return function_name(series.split("_")[1], timezone, type,self)
|
||||||
|
else:
|
||||||
|
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
|
||||||
|
def ks_date_series_l(ks_date_selection, timezone, type, self=None):
|
||||||
|
ks_date_data = {}
|
||||||
|
date_filter_options = {
|
||||||
|
'day': 0,
|
||||||
|
'week': 7,
|
||||||
|
'month': 30,
|
||||||
|
'quarter': 90,
|
||||||
|
'year': 365,
|
||||||
|
'past': False,
|
||||||
|
'future': False
|
||||||
|
}
|
||||||
|
end_time = datetime.strptime(datetime.now(pytz.timezone(timezone)).strftime("%Y-%m-%d 23:59:59"),
|
||||||
|
'%Y-%m-%d %H:%M:%S')
|
||||||
|
start_time = datetime.strptime((datetime.now(pytz.timezone(timezone)) - timedelta(
|
||||||
|
days=date_filter_options[ks_date_selection])).strftime("%Y-%m-%d 00:00:00"), '%Y-%m-%d %H:%M:%S')
|
||||||
|
if type == 'date':
|
||||||
|
ks_date_data["selected_end_date"] = datetime.strptime(end_time.strftime("%Y-%m-%d"), '%Y-%m-%d')
|
||||||
|
ks_date_data["selected_start_date"] = datetime.strptime(start_time.strftime("%Y-%m-%d"), '%Y-%m-%d')
|
||||||
|
else:
|
||||||
|
ks_date_data["selected_end_date"] = ks_convert_into_utc(end_time, timezone)
|
||||||
|
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_time, timezone)
|
||||||
|
|
||||||
|
return ks_date_data
|
||||||
|
|
||||||
|
|
||||||
|
# Current Date Ranges : Week, Month, Quarter, year
|
||||||
|
def ks_date_series_t(ks_date_selection, timezone, type, self=None):
|
||||||
|
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
|
||||||
|
def ks_date_series_ls(ks_date_selection, timezone, type,self=None):
|
||||||
|
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
|
||||||
|
def ks_date_series_n(ks_date_selection, timezone, type,self=None):
|
||||||
|
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):
|
||||||
|
ks_date_data = {}
|
||||||
|
|
||||||
|
date = datetime.now(pytz.timezone(timezone))
|
||||||
|
|
||||||
|
if date_state == "previous":
|
||||||
|
date = date - timedelta(days=1)
|
||||||
|
elif date_state == "next":
|
||||||
|
date = date + timedelta(days=1)
|
||||||
|
start_date = datetime(date.year, date.month, date.day)
|
||||||
|
end_date = datetime(date.year, date.month, date.day) + timedelta(days=1, seconds=-1)
|
||||||
|
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_week(date_state, timezone, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
|
||||||
|
# date = datetime.now(pytz.timezone(timezone))
|
||||||
|
# ks_week = 0
|
||||||
|
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))
|
||||||
|
if date_state == "previous":
|
||||||
|
start_date = datetime.today() - relativedelta(weeks=1, weekday=start_Date(-1))
|
||||||
|
elif date_state == "next":
|
||||||
|
start_date = datetime.today() - relativedelta(weeks=-1, weekday=start_Date(-1))
|
||||||
|
|
||||||
|
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 = start_date + timedelta(days=6, hours=23, minutes=59, seconds=59, milliseconds=59)
|
||||||
|
ks_date_data["selected_end_date"] = end_date
|
||||||
|
else:
|
||||||
|
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, timezone)
|
||||||
|
end_date = start_date + timedelta(days=6, hours=23, minutes=59, seconds=59, milliseconds=59)
|
||||||
|
ks_date_data["selected_end_date"] = ks_convert_into_utc(end_date, timezone)
|
||||||
|
return ks_date_data
|
||||||
|
|
||||||
|
def ks_get_date_range_from_month(date_state, timezone, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
|
||||||
|
date = datetime.now(pytz.timezone(timezone))
|
||||||
|
year = date.year
|
||||||
|
month = date.month
|
||||||
|
|
||||||
|
if date_state == "previous":
|
||||||
|
month -= 1
|
||||||
|
if month == 0:
|
||||||
|
month = 12
|
||||||
|
year -= 1
|
||||||
|
elif date_state == "next":
|
||||||
|
month += 1
|
||||||
|
if month == 13:
|
||||||
|
month = 1
|
||||||
|
year += 1
|
||||||
|
|
||||||
|
end_year = year
|
||||||
|
end_month = month
|
||||||
|
if month == 12:
|
||||||
|
end_year += 1
|
||||||
|
end_month = 1
|
||||||
|
else:
|
||||||
|
end_month += 1
|
||||||
|
start_date = datetime(year, month, 1)
|
||||||
|
end_date = datetime(end_year, end_month, 1) - timedelta(seconds=1)
|
||||||
|
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_quarter(date_state, timezone, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
|
||||||
|
date = datetime.now(pytz.timezone(timezone))
|
||||||
|
year = date.year
|
||||||
|
quarter = int((date.month - 1) / 3) + 1
|
||||||
|
|
||||||
|
if date_state == "previous":
|
||||||
|
quarter -= 1
|
||||||
|
if quarter == 0:
|
||||||
|
quarter = 4
|
||||||
|
year -= 1
|
||||||
|
elif date_state == "next":
|
||||||
|
quarter += 1
|
||||||
|
if quarter == 5:
|
||||||
|
quarter = 1
|
||||||
|
year += 1
|
||||||
|
|
||||||
|
start_date = datetime(year, 3 * quarter - 2, 1)
|
||||||
|
|
||||||
|
month = 3 * quarter
|
||||||
|
remaining = int(month / 12)
|
||||||
|
end_date = datetime(year + remaining, month % 12 + 1, 1) - timedelta(seconds=1)
|
||||||
|
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_year(date_state, timezone, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
|
||||||
|
date = datetime.now(pytz.timezone(timezone))
|
||||||
|
year = date.year
|
||||||
|
|
||||||
|
if date_state == "previous":
|
||||||
|
year -= 1
|
||||||
|
elif date_state == "next":
|
||||||
|
year += 1
|
||||||
|
start_date = datetime(year, 1, 1)
|
||||||
|
end_date = datetime(year + 1, 1, 1) - timedelta(seconds=1)
|
||||||
|
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_past(date_state, self_tz, type, self):
|
||||||
|
ks_date_data = {}
|
||||||
|
date = datetime.now(pytz.timezone(self_tz))
|
||||||
|
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_pastwithout(date_state, self_tz, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
date = datetime.now(pytz.timezone(self_tz))
|
||||||
|
hour = date.hour + 1
|
||||||
|
date = date - timedelta(hours=hour)
|
||||||
|
date = datetime.strptime(date.strftime("%Y-%m-%d 23:59:59"), '%Y-%m-%d %H:%M:%S')
|
||||||
|
ks_date_data["selected_start_date"] = False
|
||||||
|
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)
|
||||||
|
return ks_date_data
|
||||||
|
|
||||||
|
|
||||||
|
def ks_get_date_range_from_future(date_state, self_tz, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
date = datetime.now(pytz.timezone(self_tz))
|
||||||
|
ks_date_data["selected_end_date"] = False
|
||||||
|
if type == 'date':
|
||||||
|
ks_date_data["selected_start_date"] = date.strptime(date.strftime("%Y-%m-%d"), '%Y-%m-%d')
|
||||||
|
else:
|
||||||
|
ks_date_data["selected_start_date"] = ks_convert_into_utc(date,self_tz)
|
||||||
|
return ks_date_data
|
||||||
|
|
||||||
|
|
||||||
|
def ks_get_date_range_from_futurestarting(date_state, self_tz, type,self):
|
||||||
|
ks_date_data = {}
|
||||||
|
date = datetime.now(pytz.timezone(self_tz))
|
||||||
|
date = date + timedelta(days=1)
|
||||||
|
start_date = datetime.strptime(date.strftime("%Y-%m-%d 00:00:00"), '%Y-%m-%d %H:%M:%S')
|
||||||
|
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"] = False
|
||||||
|
else:
|
||||||
|
ks_date_data["selected_start_date"] = ks_convert_into_utc(start_date, self_tz)
|
||||||
|
ks_date_data["selected_end_date"] = False
|
||||||
|
return ks_date_data
|
||||||
|
|
||||||
|
def ks_convert_into_utc(datetime, timezone):
|
||||||
|
ks_tz = timezone and pytz.timezone(timezone) or pytz.UTC
|
||||||
|
return ks_tz.localize(datetime.replace(tzinfo=None), is_dst=False).astimezone(pytz.UTC).replace(tzinfo=None)
|
||||||
|
|
||||||
|
def ks_convert_into_local(datetime, timezone):
|
||||||
|
ks_tz = timezone and pytz.timezone(timezone) or pytz.UTC
|
||||||
|
return pytz.UTC.localize(datetime.replace(tzinfo=None), is_dst=False).astimezone(ks_tz).replace(tzinfo=None)
|
||||||
4
ks_dashboard_ninja/controllers/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from . import ks_chart_export
|
||||||
|
from . import ks_list_export
|
||||||
|
from . import ks_dashboard_export
|
||||||
|
from . import ks_domain_fix
|
||||||
128
ks_dashboard_ninja/controllers/ks_chart_export.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import io
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import operator
|
||||||
|
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from odoo.http import content_disposition, request
|
||||||
|
from odoo.tools import pycompat
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
|
from odoo import http
|
||||||
|
from odoo.addons.web.controllers.export import ExportXlsxWriter
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class KsChartExport(http.Controller):
|
||||||
|
|
||||||
|
def base(self, data):
|
||||||
|
params = json.loads(data)
|
||||||
|
if not params.get('chart_data'):
|
||||||
|
raise ValidationError("Chart data not present")
|
||||||
|
|
||||||
|
header,chart_data = operator.itemgetter('header','chart_data')(params)
|
||||||
|
chart_data = json.loads(chart_data)
|
||||||
|
|
||||||
|
if isinstance(chart_data['labels'], list):
|
||||||
|
chart_data['labels'] = [str(label) for label in chart_data['labels']]
|
||||||
|
|
||||||
|
chart_data['labels'].insert(0,'Measure')
|
||||||
|
columns_headers = chart_data['labels']
|
||||||
|
import_data = []
|
||||||
|
excel_fields = []
|
||||||
|
|
||||||
|
for dataset in chart_data['datasets']:
|
||||||
|
dataset['data'].insert(0, dataset['label'])
|
||||||
|
import_data.append(dataset['data'])
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(len(columns_headers)):
|
||||||
|
ks_type_obj = {}
|
||||||
|
if (len(import_data)):
|
||||||
|
if isinstance(import_data[0][i],float):
|
||||||
|
ks_type_obj['type'] = 'float'
|
||||||
|
else:
|
||||||
|
ks_type_obj['type'] = ''
|
||||||
|
excel_fields.append((ks_type_obj))
|
||||||
|
|
||||||
|
|
||||||
|
return request.make_response(self.from_data(excel_fields,columns_headers,import_data),
|
||||||
|
headers=[('Content-Disposition',
|
||||||
|
content_disposition(self.filename(header))),
|
||||||
|
('Content-Type', self.content_type)],
|
||||||
|
# cookies={'fileToken': token}
|
||||||
|
)
|
||||||
|
|
||||||
|
class KsChartExcelExport(KsChartExport, http.Controller):
|
||||||
|
|
||||||
|
# Excel needs raw data to correctly handle numbers and date values
|
||||||
|
raw_data = True
|
||||||
|
|
||||||
|
@http.route('/ks_dashboard_ninja/export/chart_xls', type='http', auth="user")
|
||||||
|
def index(self, data):
|
||||||
|
try:
|
||||||
|
return self.base(data)
|
||||||
|
except Exception as exc:
|
||||||
|
_logger.exception("Exception during request handling.")
|
||||||
|
payload = json.dumps({
|
||||||
|
'code': 200,
|
||||||
|
'message': "Odoo Server Error",
|
||||||
|
'data': http.serialize_exception(exc)
|
||||||
|
})
|
||||||
|
raise InternalServerError(payload) from exc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content_type(self):
|
||||||
|
return 'application/vnd.ms-excel'
|
||||||
|
|
||||||
|
def filename(self, base):
|
||||||
|
return base + '.xlsx'
|
||||||
|
|
||||||
|
def from_data(self, fields, columns_headers, rows):
|
||||||
|
with ExportXlsxWriter(fields, columns_headers, len(rows)) as xlsx_writer:
|
||||||
|
for row_index, row in enumerate(rows):
|
||||||
|
for cell_index, cell_value in enumerate(row):
|
||||||
|
xlsx_writer.write_cell(row_index + 1, cell_index, cell_value)
|
||||||
|
|
||||||
|
return xlsx_writer.value
|
||||||
|
|
||||||
|
|
||||||
|
class KsChartCsvExport(KsChartExport, http.Controller):
|
||||||
|
|
||||||
|
@http.route('/ks_dashboard_ninja/export/chart_csv', type='http', auth="user")
|
||||||
|
def index(self, data):
|
||||||
|
try:
|
||||||
|
return self.base(data)
|
||||||
|
except Exception as exc:
|
||||||
|
_logger.exception("Exception during request handling.")
|
||||||
|
payload = json.dumps({
|
||||||
|
'code': 200,
|
||||||
|
'message': "Odoo Server Error",
|
||||||
|
'data': http.serialize_exception(exc)
|
||||||
|
})
|
||||||
|
raise InternalServerError(payload) from exc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content_type(self):
|
||||||
|
return 'text/csv;charset=utf8'
|
||||||
|
|
||||||
|
def filename(self, base):
|
||||||
|
return base + '.csv'
|
||||||
|
|
||||||
|
def from_data(self, fields,columns_headers, rows):
|
||||||
|
fp = io.BytesIO()
|
||||||
|
writer = pycompat.csv_writer(fp, quoting=1)
|
||||||
|
|
||||||
|
writer.writerow(columns_headers)
|
||||||
|
|
||||||
|
for data in rows:
|
||||||
|
row = []
|
||||||
|
for d in data:
|
||||||
|
# Spreadsheet apps tend to detect formulas on leading =, + and -
|
||||||
|
if isinstance(d, str) and d.startswith(('=', '-', '+')):
|
||||||
|
d = "'" + d
|
||||||
|
|
||||||
|
row.append(pycompat.to_text(d))
|
||||||
|
writer.writerow(row)
|
||||||
|
|
||||||
|
return fp.getvalue()
|
||||||
84
ks_dashboard_ninja/controllers/ks_dashboard_export.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import io
|
||||||
|
import json
|
||||||
|
import operator
|
||||||
|
import logging
|
||||||
|
from odoo import http
|
||||||
|
from odoo.http import request
|
||||||
|
from odoo.http import content_disposition,request
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardExport(http.Controller):
|
||||||
|
|
||||||
|
def base(self, data):
|
||||||
|
params = json.loads(data)
|
||||||
|
header, dashboard_data = operator.itemgetter('header', 'dashboard_data')(params)
|
||||||
|
return request.make_response(self.from_data(dashboard_data),
|
||||||
|
headers=[('Content-Disposition',
|
||||||
|
content_disposition(self.filename(header))),
|
||||||
|
('Content-Type', self.content_type)],
|
||||||
|
# cookies={'fileToken': token}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardJsonExport(KsDashboardExport, http.Controller):
|
||||||
|
|
||||||
|
@http.route('/ks_dashboard_ninja/export/dashboard_json', type='http', auth="user")
|
||||||
|
def index(self, data):
|
||||||
|
try:
|
||||||
|
return self.base(data)
|
||||||
|
except Exception as exc:
|
||||||
|
_logger.exception("Exception during request handling.")
|
||||||
|
payload = json.dumps({
|
||||||
|
'code': 200,
|
||||||
|
'message': "Odoo Server Error",
|
||||||
|
'data': http.serialize_exception(exc)
|
||||||
|
})
|
||||||
|
raise InternalServerError(payload) from exc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content_type(self):
|
||||||
|
return 'text/csv;charset=utf8'
|
||||||
|
|
||||||
|
def filename(self, base):
|
||||||
|
return base + '.json'
|
||||||
|
|
||||||
|
def from_data(self, dashboard_data):
|
||||||
|
fp = io.StringIO()
|
||||||
|
fp.write(json.dumps(dashboard_data))
|
||||||
|
|
||||||
|
return fp.getvalue()
|
||||||
|
|
||||||
|
class KsItemJsonExport(KsDashboardExport, http.Controller):
|
||||||
|
|
||||||
|
@http.route('/ks_dashboard_ninja/export/item_json', type='http', auth="user")
|
||||||
|
def index(self, data):
|
||||||
|
try:
|
||||||
|
data = json.loads(data)
|
||||||
|
item_id = data["item_id"]
|
||||||
|
data['dashboard_data'] = request.env['ks_dashboard_ninja.board'].ks_export_item(item_id)
|
||||||
|
data = json.dumps(data)
|
||||||
|
return self.base(data)
|
||||||
|
except Exception as exc:
|
||||||
|
_logger.exception("Exception during request handling.")
|
||||||
|
payload = json.dumps({
|
||||||
|
'code': 200,
|
||||||
|
'message': "Odoo Server Error",
|
||||||
|
'data': http.serialize_exception(exc)
|
||||||
|
})
|
||||||
|
raise InternalServerError(payload) from exc
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content_type(self):
|
||||||
|
return 'text/csv;charset=utf8'
|
||||||
|
|
||||||
|
def filename(self, base):
|
||||||
|
return base + '.json'
|
||||||
|
|
||||||
|
def from_data(self, dashboard_data):
|
||||||
|
fp = io.StringIO()
|
||||||
|
fp.write(json.dumps(dashboard_data))
|
||||||
|
|
||||||
|
return fp.getvalue()
|
||||||
21
ks_dashboard_ninja/controllers/ks_domain_fix.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from odoo.addons.web.controllers.domain import Domain
|
||||||
|
|
||||||
|
from odoo import http, _
|
||||||
|
from odoo.http import Controller, request
|
||||||
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
|
|
||||||
|
class ksdomainfix(Domain):
|
||||||
|
# to validate our uid and mycompany based domain
|
||||||
|
@http.route('/web/domain/validate', type='json', auth="user")
|
||||||
|
def validate(self, model, domain):
|
||||||
|
ks_uid_domain = str(domain)
|
||||||
|
if ks_uid_domain and "%UID" in ks_uid_domain:
|
||||||
|
ks_domain = ks_uid_domain.replace("%UID", str(request.env.user.id))
|
||||||
|
return super().validate(model,safe_eval(ks_domain))
|
||||||
|
elif ks_uid_domain and "%MYCOMPANY" in ks_uid_domain:
|
||||||
|
ks_domain = ks_uid_domain.replace("%MYCOMPANY", str(request.env.company.id))
|
||||||
|
return super().validate(model,safe_eval(ks_domain))
|
||||||
|
else:
|
||||||
|
return super().validate(model, domain)
|
||||||
|
|
||||||
213
ks_dashboard_ninja/controllers/ks_list_export.py
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
|
||||||
|
import re
|
||||||
|
import io
|
||||||
|
import json
|
||||||
|
import operator
|
||||||
|
import logging
|
||||||
|
from odoo.addons.web.controllers.export import ExportXlsxWriter
|
||||||
|
from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT , xlsxwriter
|
||||||
|
import datetime
|
||||||
|
from odoo import http
|
||||||
|
from odoo.http import content_disposition, request
|
||||||
|
from odoo.tools import pycompat
|
||||||
|
from ..common_lib.ks_date_filter_selections import ks_get_date, ks_convert_into_utc, ks_convert_into_local
|
||||||
|
import os
|
||||||
|
import pytz
|
||||||
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class KsListExport(http.Controller):
|
||||||
|
|
||||||
|
def base(self, data):
|
||||||
|
params = json.loads(data)
|
||||||
|
# header,list_data = operator.itemgetter('header','chart_data')(params)
|
||||||
|
header, list_data, item_id, ks_export_boolean, context, params = operator.itemgetter('header', 'chart_data',
|
||||||
|
'ks_item_id',
|
||||||
|
'ks_export_boolean',
|
||||||
|
'context', 'params')(
|
||||||
|
params)
|
||||||
|
list_data = json.loads(list_data)
|
||||||
|
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
|
||||||
|
if not ks_timezone:
|
||||||
|
ks_tzone = os.environ.get('TZ')
|
||||||
|
if ks_tzone:
|
||||||
|
ks_timezone = ks_tzone
|
||||||
|
elif os.path.exists('/etc/timezone'):
|
||||||
|
ks_tzone = open('/etc/timezone').read()
|
||||||
|
ks_timezone = ks_tzone[0:-1]
|
||||||
|
try:
|
||||||
|
datetime.now(pytz.timezone(ks_timezone))
|
||||||
|
except Exception as e:
|
||||||
|
_logger.info('Please set the local timezone')
|
||||||
|
|
||||||
|
else:
|
||||||
|
_logger.info('Please set the local timezone')
|
||||||
|
orderby = item.ks_sort_by_field.id
|
||||||
|
sort_order = item.ks_sort_by_order
|
||||||
|
ks_start_date = context.get('ksDateFilterStartDate', False)
|
||||||
|
ks_end_date = context.get('ksDateFilterEndDate', False)
|
||||||
|
ksDateFilterSelection = context.get('ksDateFilterSelection', False)
|
||||||
|
if context.get('allowed_company_ids', False):
|
||||||
|
item = item.with_context(allowed_company_ids=context.get('allowed_company_ids'))
|
||||||
|
if item.ks_data_calculation_type == 'query':
|
||||||
|
query_start_date = item.ks_query_start_date
|
||||||
|
query_end_date = item.ks_query_end_date
|
||||||
|
ks_query = str(item.ks_custom_query)
|
||||||
|
if ks_start_date and ks_end_date:
|
||||||
|
ks_start_date = datetime.datetime.strptime(ks_start_date,DEFAULT_SERVER_DATETIME_FORMAT)
|
||||||
|
ks_end_date = datetime.datetime.strptime(ks_end_date,DEFAULT_SERVER_DATETIME_FORMAT)
|
||||||
|
item = item.with_context(ksDateFilterStartDate=ks_start_date)
|
||||||
|
item = item.with_context(ksDateFilterEndDate=ks_end_date)
|
||||||
|
item = item.with_context(ksDateFilterSelection=ksDateFilterSelection)
|
||||||
|
|
||||||
|
if item._context.get('ksDateFilterSelection', False):
|
||||||
|
ks_date_filter_selection = item._context['ksDateFilterSelection']
|
||||||
|
if ks_date_filter_selection == 'l_custom':
|
||||||
|
item = item.with_context(ksDateFilterStartDate=ks_start_date)
|
||||||
|
item = item.with_context(ksDateFilterEndDate=ks_end_date)
|
||||||
|
item = item.with_context(ksIsDefultCustomDateFilter=False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
ks_date_filter_selection = item.ks_dashboard_ninja_board_id.ks_date_filter_selection
|
||||||
|
item = item.with_context(ksDateFilterStartDate=item.ks_dashboard_ninja_board_id.ks_dashboard_start_date)
|
||||||
|
item = item.with_context(ksDateFilterEndDate=item.ks_dashboard_ninja_board_id.ks_dashboard_end_date)
|
||||||
|
item = item.with_context(ksDateFilterSelection=ks_date_filter_selection)
|
||||||
|
item = item.with_context(ksIsDefultCustomDateFilter=True)
|
||||||
|
|
||||||
|
if ks_date_filter_selection not in ['l_custom', 'l_none']:
|
||||||
|
ks_date_data = ks_get_date(ks_date_filter_selection, request, 'datetime')
|
||||||
|
item = item.with_context(ksDateFilterStartDate=ks_date_data["selected_start_date"])
|
||||||
|
item = item.with_context(ksDateFilterEndDate=ks_date_data["selected_end_date"])
|
||||||
|
|
||||||
|
item_domain = params.get('ks_domain_1', [])
|
||||||
|
ks_chart_domain = item.ks_convert_into_proper_domain(item.ks_domain, item,item_domain)
|
||||||
|
# list_data = item.ks_fetch_list_view_data(item,ks_chart_domain, ks_export_all=
|
||||||
|
if list_data['type'] == 'ungrouped':
|
||||||
|
list_data = item.ks_fetch_list_view_data(item, ks_chart_domain, ks_export_all=True)
|
||||||
|
elif list_data['type'] == 'grouped':
|
||||||
|
list_data = item.get_list_view_record(orderby, sort_order, ks_chart_domain, ks_export_all=True)
|
||||||
|
elif item.ks_data_calculation_type == 'query':
|
||||||
|
if ks_start_date or ks_end_date:
|
||||||
|
query_start_date = ks_start_date
|
||||||
|
query_end_date = ks_end_date
|
||||||
|
ks_query_result = item.ks_get_list_query_result(ks_query, query_start_date, query_end_date, ks_offset=0,
|
||||||
|
ks_export_all=True)
|
||||||
|
list_data = item.ks_format_query_result(ks_query_result)
|
||||||
|
|
||||||
|
# chart_data['labels'].insert(0,'Measure')
|
||||||
|
columns_headers = list_data['label']
|
||||||
|
import_data = []
|
||||||
|
|
||||||
|
for dataset in list_data['data_rows']:
|
||||||
|
if not list_data['type'] == 'grouped':
|
||||||
|
for count, index in enumerate(dataset['ks_column_type']):
|
||||||
|
if index == 'datetime':
|
||||||
|
ks_converted_date = False
|
||||||
|
date_string = dataset['data'][count]
|
||||||
|
if dataset['data'][count]:
|
||||||
|
ks_converted_date = ks_convert_into_local(datetime.datetime.strptime(date_string, '%m/%d/%y %H:%M:%S'),ks_timezone)
|
||||||
|
dataset['data'][count] = ks_converted_date
|
||||||
|
for ks_count, val in enumerate(dataset['data']):
|
||||||
|
if isinstance(val, (float, int)):
|
||||||
|
if val >= 0:
|
||||||
|
try:
|
||||||
|
ks_precision = item.sudo().env.ref('ks_dashboard_ninja.ks_dashboard_ninja_precision').digits
|
||||||
|
except Exception as e:
|
||||||
|
ks_precision = 2
|
||||||
|
dataset['data'][ks_count] = item.env['ir.qweb.field.float'].sudo().value_to_html(val,
|
||||||
|
{'precision': ks_precision})
|
||||||
|
import_data.append(dataset['data'])
|
||||||
|
excel_fields = []
|
||||||
|
for i in range(len(columns_headers)):
|
||||||
|
ks_type_obj = {}
|
||||||
|
if (len(import_data)):
|
||||||
|
if isinstance(import_data[0][i], float):
|
||||||
|
ks_type_obj['type'] = 'float'
|
||||||
|
else:
|
||||||
|
ks_type_obj['type'] = ''
|
||||||
|
excel_fields.append((ks_type_obj))
|
||||||
|
|
||||||
|
return request.make_response(self.from_data(excel_fields,columns_headers, import_data),
|
||||||
|
headers=[('Content-Disposition',
|
||||||
|
content_disposition(self.filename(header))),
|
||||||
|
('Content-Type', self.content_type)],
|
||||||
|
# cookies={'fileToken': token}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class KsListExcelExport(KsListExport, http.Controller):
|
||||||
|
|
||||||
|
# Excel needs raw data to correctly handle numbers and date values
|
||||||
|
raw_data = True
|
||||||
|
|
||||||
|
@http.route('/ks_dashboard_ninja/export/list_xls', type='http', auth="user")
|
||||||
|
def index(self, data):
|
||||||
|
try:
|
||||||
|
return self.base(data)
|
||||||
|
except Exception as exc:
|
||||||
|
_logger.exception("Exception during request handling.")
|
||||||
|
payload = json.dumps({
|
||||||
|
'code': 200,
|
||||||
|
'message': "Odoo Server Error",
|
||||||
|
'data': http.serialize_exception(exc)
|
||||||
|
})
|
||||||
|
raise InternalServerError(payload) from exc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content_type(self):
|
||||||
|
return 'application/vnd.ms-excel'
|
||||||
|
|
||||||
|
def filename(self, base):
|
||||||
|
return base + '.xlsx'
|
||||||
|
|
||||||
|
def from_data(self, fields, columns_headers, rows):
|
||||||
|
with ExportXlsxWriter(fields, columns_headers, len(rows)) as xlsx_writer:
|
||||||
|
for row_index, row in enumerate(rows):
|
||||||
|
for cell_index, cell_value in enumerate(row):
|
||||||
|
xlsx_writer.write_cell(row_index + 1, cell_index, cell_value)
|
||||||
|
|
||||||
|
return xlsx_writer.value
|
||||||
|
|
||||||
|
|
||||||
|
class KsListCsvExport(KsListExport, http.Controller):
|
||||||
|
|
||||||
|
@http.route('/ks_dashboard_ninja/export/list_csv', type='http', auth="user")
|
||||||
|
def index(self, data):
|
||||||
|
try:
|
||||||
|
return self.base(data)
|
||||||
|
except Exception as exc:
|
||||||
|
_logger.exception("Exception during request handling.")
|
||||||
|
payload = json.dumps({
|
||||||
|
'code': 200,
|
||||||
|
'message': "Odoo Server Error",
|
||||||
|
'data': http.serialize_exception(exc)
|
||||||
|
})
|
||||||
|
raise InternalServerError(payload) from exc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def content_type(self):
|
||||||
|
return 'text/csv;charset=utf8'
|
||||||
|
|
||||||
|
def filename(self, base):
|
||||||
|
return base + '.csv'
|
||||||
|
|
||||||
|
def from_data(self, fields, column_headers,rows):
|
||||||
|
fp = io.BytesIO()
|
||||||
|
writer = pycompat.csv_writer(fp, quoting=1)
|
||||||
|
|
||||||
|
writer.writerow(column_headers)
|
||||||
|
|
||||||
|
for data in rows:
|
||||||
|
row = []
|
||||||
|
for d in data:
|
||||||
|
# Spreadsheet apps tend to detect formulas on leading =, + and -
|
||||||
|
if isinstance(d, str) and d.startswith(('=', '-', '+')):
|
||||||
|
d = "'" + d
|
||||||
|
|
||||||
|
row.append(pycompat.to_text(d))
|
||||||
|
writer.writerow(row)
|
||||||
|
|
||||||
|
return fp.getvalue()
|
||||||
9
ks_dashboard_ninja/data/dn_data.xml
Normal 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>
|
||||||
605
ks_dashboard_ninja/data/ks_default_data.xml
Normal file
@ -0,0 +1,605 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<data>
|
||||||
|
<!-- Default Templates -->
|
||||||
|
<record id="ks_blank" model="ks_dashboard_ninja.board_template">
|
||||||
|
<field name="name">Blank</field>
|
||||||
|
<field name="ks_item_count">0</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_template_1" model="ks_dashboard_ninja.board_template">
|
||||||
|
<field name="name">Template 1</field>
|
||||||
|
<field name="ks_gridstack_config">[
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_1", "data": {"x": 0, "y": 10, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_2", "data": {"x": 0, "y": 8, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_3", "data": {"x": 3, "y": 0, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_4", "data": {"x": 0, "y": 2, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_5", "data": {"x": 6, "y": 12, "w": 6, "h": 6}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_6", "data": {"x": 0, "y": 28, "w": 12, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_7", "data": {"x": 0, "y": 43, "w": 5, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_8", "data": {"x": 6, "y": 6, "w": 6, "h": 6}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_9", "data": {"x": 5, "y": 36, "w": 7, "h": 7}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_10", "data": {"x": 4, "y": 23, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_11", "data": {"x": 6, "y": 18, "w": 6, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_12", "data": {"x": 0, "y": 6, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_13", "data": {"x": 3, "y": 8, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_15", "data": {"x": 0, "y": 18, "w": 6, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_16", "data": {"x": 0, "y": 0, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_17", "data": {"x": 3, "y": 6, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_18", "data": {"x": 3, "y": 4, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_19", "data": {"x": 3, "y": 10, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_20", "data": {"x": 5, "y": 43, "w": 7, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_21", "data": {"x": 0, "y": 12, "w": 6, "h":
|
||||||
|
6}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_22", "data": {"x": 0, "y": 36, "w": 5, "h":
|
||||||
|
7}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_23", "data": {"x": 0, "y": 32, "w": 12, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_24", "data": {"x": 8, "y": 23, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_25", "data": {"x": 0, "y": 23, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_26", "data": {"x": 0, "y": 4, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_27", "data": {"x": 3, "y": 3, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_28", "data": {"x": 6, "y": 0, "w": 6, "h":
|
||||||
|
6}}
|
||||||
|
]
|
||||||
|
</field>
|
||||||
|
<field name="ks_item_count">7</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_template_2" model="ks_dashboard_ninja.board_template">
|
||||||
|
<field name="name">Template 2</field>
|
||||||
|
<field name="ks_gridstack_config">[
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_1", "data": {"x": 0, "y": 0, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_2", "data": {"x": 4, "y": 0, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_3", "data": {"x": 2, "y": 0, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_4", "data": {"x": 8, "y": 0, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_5", "data": {"x": 4, "y": 18, "w": 8, "h": 5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_6", "data": {"x": 8, "y": 27, "w": 4, "h":
|
||||||
|
6}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_7", "data": {"x": 0, "y": 18, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_8", "data": {"x": 4, "y": 27, "w": 4, "h":
|
||||||
|
6}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_9", "data": {"x": 4, "y": 13, "w": 8, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_10", "data": {"x": 0, "y": 23, "w": 4, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_11", "data": {"x": 0, "y": 4, "w": 4, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_12", "data": {"x": 6, "y": 0, "w": 2, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_13", "data": {"x": 10, "y": 2, "w": 2, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_15", "data": {"x":0, "y": 33, "w": 6, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_16", "data": {"x": 2, "y": 2, "w": 2, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_17", "data": {"x": 8, "y": 2, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_18", "data": {"x": 6, "y": 2, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_19", "data": {"x": 0, "y": 2, "w": 2, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_20", "data": {"x": 4, "y": 8, "w": 8, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_21", "data": {"x": 0, "y": 13, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_22", "data": {"x": 4, "y": 23, "w": 8, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_23", "data": {"x": 6, "y": 33, "w": 6, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_24", "data": {"x": 4, "y": 4, "w": 8, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_25", "data": {"x": 0, "y": 8, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_26", "data": {"x": 4, "y": 2, "w": 2, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_27", "data": {"x": 10, "y": 2, "w": 2, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_28", "data": {"x": 0, "y": 27, "w": 4, "h":
|
||||||
|
6}}
|
||||||
|
]
|
||||||
|
</field>
|
||||||
|
<field name="ks_item_count">7</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_template_3" model="ks_dashboard_ninja.board_template">
|
||||||
|
<field name="name">Template 3</field>
|
||||||
|
<field name="ks_gridstack_config">[
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_1", "data": {"x": 0, "y": 0, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_2", "data": {"x": 6, "y": 0, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_3", "data": {"x": 3, "y": 0, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_4", "data": {"x": 0, "y": 2, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_5", "data": {"x": 7, "y": 2, "w": 5, "h": 4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_6", "data": {"x": 0, "y": 28, "w": 12, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_7", "data": {"x": 4, "y": 14, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_8", "data": {"x": 0, "y": 33, "w": 3, "h": 5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_9", "data": {"x": 8, "y": 23, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_10", "data": {"x": 8, "y": 14, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_11", "data": {"x": 0, "y": 23, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_12", "data": {"x": 9, "y": 0, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_13", "data": {"x": 3, "y": 2, "w": 4, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_15", "data": {"x":0, "y": 19, "w": 12, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_16", "data": {"x": 0, "y": 8, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_17", "data": {"x": 3, "y": 4, "w": 4, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_18", "data": {"x": 0, "y": 12, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_19", "data": {"x": 0, "y": 4, "w": 3, "h": 2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_20", "data": {"x": 3, "y": 6, "w": 9, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_21", "data": {"x": 0, "y": 14, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_22", "data": {"x": 6, "y": 33, "w": 6, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_23", "data": {"x": 0, "y": 19, "w": 12, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_24", "data": {"x": 3, "y": 10, "w": 9, "h":
|
||||||
|
4}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_25", "data": {"x": 4, "y": 23, "w": 4, "h":
|
||||||
|
5}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_26", "data": {"x": 0, "y": 8, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_27", "data": {"x": 0, "y": 6, "w": 3, "h":
|
||||||
|
2}},
|
||||||
|
{"item_id":"ks_dashboard_ninja.ks_default_item_28", "data": {"x": 3, "y": 33, "w": 3, "h":
|
||||||
|
5}}
|
||||||
|
]
|
||||||
|
</field>
|
||||||
|
<field name="ks_item_count">7</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<!--Default items (7 right now) created here that will be used for default templates in future dashboards-->
|
||||||
|
|
||||||
|
<record id="ks_default_item_1" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Tile (layout 1)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_tile</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id",">",150]]</field>
|
||||||
|
<field name="ks_default_icon">bar-chart</field>
|
||||||
|
<field name="ks_dashboard_item_theme">blue</field>
|
||||||
|
<field name="ks_background_color">#FFE2E5,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_layout">layout1</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_default_item_2" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Tile (layout 3)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_tile</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_default_icon">users</field>
|
||||||
|
<field name="ks_dashboard_item_theme">red</field>
|
||||||
|
<field name="ks_background_color">#FFF4DE,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_layout">layout3</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_default_item_3" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Tile (layout 2)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_tile</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id","<",50]]</field>
|
||||||
|
<field name="ks_default_icon">money</field>
|
||||||
|
<field name="ks_dashboard_item_theme">green</field>
|
||||||
|
<field name="ks_background_color">#DCFCE7,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_layout">layout2</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_default_item_4" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Tile (layout 5)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_tile</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_default_icon">paper-plane</field>
|
||||||
|
<field name="ks_dashboard_item_theme">yellow</field>
|
||||||
|
<field name="ks_background_color">#F3E8FF,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_layout">layout5</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_default_item_5" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Bar Chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<!-- <field name="ks_chart_measure_field" eval="[ref('base.field_res_country__phone_code')]"/>-->
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__currency_id')"/>
|
||||||
|
<field name="ks_domain">[["id","<",40]]</field>
|
||||||
|
<field name="ks_chart_item_color">dark</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_bar_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="ks_default_item_6" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Line Chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<!-- <field name="ks_chart_measure_field" eval="[ref('base.field_res_country__phone_code')]"/>-->
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__currency_id')"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_chart_item_color">dark</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_line_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_default_item_7" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Pie Chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__currency_id')"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_pie_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_8" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">list view (Un-Grouped)</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_list_view_type">grouped</field>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__phone_code')"/>
|
||||||
|
<field name="ks_list_view_group_fields" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_list_view</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_9" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Horizontal Bar</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__currency_id')"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_chart_item_color">material</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_horizontalBar_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_10" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Polar Area</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__currency_id')"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_chart_item_color">moonrise</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_polarArea_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_11" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Doughnut chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_chart_item_color">moonrise</field>
|
||||||
|
<field name="ks_record_data_limit">100</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_doughnut_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_12" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Tile (layout 4)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_tile</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id","<",50]]</field>
|
||||||
|
<field name="ks_default_icon">shopping-cart</field>
|
||||||
|
<field name="ks_dashboard_item_theme">red</field>
|
||||||
|
<field name="ks_background_color">#FFE2E5,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_layout">layout4</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_13" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Tile (layout 6)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_tile</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_default_icon">car</field>
|
||||||
|
<field name="ks_dashboard_item_theme">red</field>
|
||||||
|
<field name="ks_background_color">#FFF4DE,0.53</field>
|
||||||
|
<field name="ks_font_color">#000000,0.70</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_layout">layout6</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_14" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Pie Chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__currency_id')"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_chart_item_color">dark</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_pie_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_15" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Area Chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__code')"/>
|
||||||
|
<field name="ks_chart_item_color">default</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_area_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
<record id="ks_default_item_16" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Kpi Ratio</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_kpi</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_record_count_type_2">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_model_id_2" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_data_comparison">Ratio</field>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_default_icon">user</field>
|
||||||
|
<field name="ks_dashboard_item_theme">blue</field>
|
||||||
|
<field name="ks_background_color">#DCFCE7,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_17" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Kpi ( Percentage)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_kpi</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_record_count_type_2">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_model_id_2" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_data_comparison">Percentage</field>
|
||||||
|
<field name="ks_default_icon">paper-plane</field>
|
||||||
|
<field name="ks_dashboard_item_theme">red</field>
|
||||||
|
<field name="ks_background_color">#F3E8FF,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_18" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Kpi ( Number)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_kpi</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_record_count_type_2">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_model_id_2" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_target_view">Number</field>
|
||||||
|
<field name="ks_goal_enable">1</field>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_data_comparison">Sum</field>
|
||||||
|
<field name="ks_default_icon">money</field>
|
||||||
|
<field name="ks_dashboard_item_theme">green</field>
|
||||||
|
<field name="ks_background_color">#F3E8FF,0.63</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_19" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Kpi (sum)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_kpi</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_record_count_type_2">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_model_id_2" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_data_comparison">Sum</field>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_default_icon">bar-chart</field>
|
||||||
|
<field name="ks_dashboard_item_theme">yellow</field>
|
||||||
|
<field name="ks_background_color">#FFF4DE,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_20" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Bar Chart With Data Values</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_domain">[["id","<",40]]</field>
|
||||||
|
<field name="ks_chart_item_color">default</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_bar_chart</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_21" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Semi Circle Pie Chart</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_semi_circle_chart">1</field>
|
||||||
|
<field name="ks_chart_item_color">material</field>
|
||||||
|
<field name="ks_record_data_limit">10</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_pie_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_22" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Horizontal Bar(sub-group)</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_chart_relation_sub_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_chart_item_color">default</field>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_horizontalBar_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_23" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Area Chart with data values</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__code')"/>
|
||||||
|
<field name="ks_chart_item_color">material</field>
|
||||||
|
<field name="ks_record_data_limit">25</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_area_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_24" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Line Chart with values</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_chart_item_color">moonrise</field>
|
||||||
|
<field name="ks_record_data_limit">10</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_line_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_25" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Doughnut semi circle</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_measure_field" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_chart_item_color">default</field>
|
||||||
|
<field name="ks_semi_circle_chart">1</field>
|
||||||
|
<field name="ks_record_data_limit">25</field>
|
||||||
|
<field name="ks_show_data_value">1</field>
|
||||||
|
<field name="ks_unit_selection">monetary</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_doughnut_chart</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_26" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Kpi 26(Average)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_kpi</field>
|
||||||
|
<field name="ks_record_field" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_record_field_2" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_data_format">indian</field>
|
||||||
|
<field name="ks_record_count_type">average</field>
|
||||||
|
<field name="ks_record_count_type_2">average</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_model_id_2" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_target_view">Number</field>
|
||||||
|
<field name="ks_goal_enable">1</field>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_data_comparison">Sum</field>
|
||||||
|
<field name="ks_default_icon">money</field>
|
||||||
|
<field name="ks_dashboard_item_theme">blue</field>
|
||||||
|
<field name="ks_background_color">#DCFCE7,0.99</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_27" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">Kpi (previous)</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_kpi</field>
|
||||||
|
<field name="ks_record_count_type">count</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_domain">[["id","<",100]]</field>
|
||||||
|
<field name="ks_previous_period">1</field>
|
||||||
|
<field name="ks_date_filter_selection">t_week</field>
|
||||||
|
<field name="ks_default_icon">money</field>
|
||||||
|
<field name="ks_dashboard_item_theme">green</field>
|
||||||
|
<field name="ks_background_color">#FFE2E5,0.59</field>
|
||||||
|
<field name="ks_font_color">#000000,0.99</field>
|
||||||
|
<field name="ks_default_icon_color">#000000,0.99</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_28" model="ks_dashboard_ninja.item">
|
||||||
|
<field name="name">list view (grouped)</field>
|
||||||
|
<field name="ks_chart_data_count_type">sum</field>
|
||||||
|
<field name="ks_chart_groupby_type">relational_type</field>
|
||||||
|
<field name="ks_model_id" eval="ref('base.model_res_country')"/>
|
||||||
|
<field name="ks_chart_relation_groupby" eval="ref('base.field_res_country__name')"/>
|
||||||
|
<field name="ks_list_view_type">ungrouped</field>
|
||||||
|
<field name="ks_list_view_group_fields" eval="[(6, 0, [ref('base.field_res_country__phone_code')])]"/>
|
||||||
|
<field name="ks_list_view_fields"
|
||||||
|
eval="[(6, 0, [ref('base.field_res_country__phone_code'),ref('base.field_res_country__name')])]"/>
|
||||||
|
<field name="ks_domain">[["id","<",10]]</field>
|
||||||
|
<field name="ks_dashboard_item_type">ks_list_view</field>
|
||||||
|
<field name="ks_company_id" eval="0"/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_10_action" model="ks_dashboard_ninja.item_action">
|
||||||
|
<field name="ks_dashboard_item_id" ref="ks_default_item_10"/>
|
||||||
|
<field name="ks_chart_type">ks_bar_chart</field>
|
||||||
|
<field name="ks_item_action_field" ref='base.field_res_country__phone_code'/>
|
||||||
|
</record>
|
||||||
|
<record id="ks_default_item_10_action1" model="ks_dashboard_ninja.item_action">
|
||||||
|
<field name="ks_dashboard_item_id" ref="ks_default_item_10"/>
|
||||||
|
<field name="ks_chart_type">ks_pie_chart</field>
|
||||||
|
<field name="ks_item_action_field" ref='base.field_res_country__name'/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Default dashboard Data -->
|
||||||
|
<data noupdate="1">
|
||||||
|
|
||||||
|
<record forcecreate="True" id="ks_dashboard_ninja_precision" model="decimal.precision">
|
||||||
|
<field name="name">Dashboard Ninja Decimal Precision</field>
|
||||||
|
<field name="digits" eval="2"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
11
ks_dashboard_ninja/data/ks_mail_cron.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record id="ir_cron_send_target_email" model="ir.cron">
|
||||||
|
<field name="name">Kpi mail cron</field>
|
||||||
|
<field name="interval_number">1</field>
|
||||||
|
<field name="interval_type">days</field>
|
||||||
|
<field name="model_id" ref="model_ks_dashboard_ninja_item"/>
|
||||||
|
<field name="code">model.check_target()</field>
|
||||||
|
<field name="state">code</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
11
ks_dashboard_ninja/data/sequence.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="ks_dashboard_item_seq" model="ir.sequence">
|
||||||
|
<field name="name">Dashboard Seq</field>
|
||||||
|
<field name="code">ks_dashboard_ninja.item</field>
|
||||||
|
<field name="padding">2</field>
|
||||||
|
<field name="company_id" eval="False"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
44
ks_dashboard_ninja/demo/ks_dashboard_ninja_demo.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<!-- Three Default Demo Dashboard with Templates : Template1, Template2, Template3-->
|
||||||
|
|
||||||
|
<record id="demo_template1_dashboard" model="ks_dashboard_ninja.board">
|
||||||
|
<field name="name">Template1 Dashboard</field>
|
||||||
|
<field name="ks_dashboard_menu_name">模版1</field>
|
||||||
|
<field name="ks_dashboard_top_menu_id" eval="ref('ks_dashboard_ninja.dashboards_menu_root')"/>
|
||||||
|
<field name="ks_dashboard_default_template" eval="ref('ks_dashboard_ninja.ks_template_1')"/>
|
||||||
|
<field name="ks_dashboard_active">1</field>
|
||||||
|
<field name="ks_dashboard_group_access" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ks_my_default_dashboard_board" model="ks_dashboard_ninja.board">
|
||||||
|
<field name="name">My Dashboard</field>
|
||||||
|
<field name="ks_dashboard_state">Locked</field>
|
||||||
|
<field name="ks_dashboard_menu_name">My Dashboard</field>
|
||||||
|
<field name="ks_dashboard_top_menu_id" eval="ref('ks_dashboard_ninja.dashboards_menu_root')"/>
|
||||||
|
<field name="ks_dashboard_active">1</field>
|
||||||
|
<field name="ks_dashboard_default_template" ref="ks_dashboard_ninja.ks_blank"/>
|
||||||
|
<field name="ks_dashboard_group_access" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="demo_template2_dashboard" model="ks_dashboard_ninja.board">
|
||||||
|
<field name="name">Template2 Dashboard</field>
|
||||||
|
<field name="ks_dashboard_menu_name">模版2</field>
|
||||||
|
<field name="ks_dashboard_top_menu_id" eval="ref('ks_dashboard_ninja.dashboards_menu_root')"/>
|
||||||
|
<field name="ks_dashboard_default_template" eval="ref('ks_dashboard_ninja.ks_template_2')"/>
|
||||||
|
<field name="ks_dashboard_active">1</field>
|
||||||
|
<field name="ks_dashboard_group_access" eval="False"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="demo_template3_dashboard" model="ks_dashboard_ninja.board">
|
||||||
|
<field name="name">Template3 Dashboard</field>
|
||||||
|
<field name="ks_dashboard_menu_name">模版3</field>
|
||||||
|
<field name="ks_dashboard_top_menu_id" eval="ref('ks_dashboard_ninja.dashboards_menu_root')"/>
|
||||||
|
<field name="ks_dashboard_default_template" eval="ref('ks_dashboard_ninja.ks_template_3')"/>
|
||||||
|
<field name="ks_dashboard_active">1</field>
|
||||||
|
<field name="ks_dashboard_group_access" eval="False"/>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
3070
ks_dashboard_ninja/i18n/en_US.po
Normal file
5190
ks_dashboard_ninja/i18n/zh_CN.po
Normal file
9
ks_dashboard_ninja/models/Kpi_mail.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class KpSendMail(models.Model):
|
||||||
|
_name = 'ks_dashboard_ninja.kpi_mail'
|
||||||
|
_description = 'Dashboard Ninja Kpi mail'
|
||||||
|
|
||||||
|
|
||||||
|
name = fields.Char(string="Email To:")
|
||||||
16
ks_dashboard_ninja/models/__init__.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from . import ks_dashboard_ninja
|
||||||
|
from . import ks_dashboard_ninja_items
|
||||||
|
from . import ks_item_action
|
||||||
|
from . import ks_child_dashboard
|
||||||
|
from . import ks_dashboard_filters
|
||||||
|
from . import ks_dashboard_templates
|
||||||
|
from . import ks_dn_to_do_item
|
||||||
|
from . import ks_import_dashboard
|
||||||
|
from . import Kpi_mail
|
||||||
|
from . import res_settings
|
||||||
|
from . import ks_ai_ninja_dashboard
|
||||||
|
from . import ks_ai_whole_dashboard
|
||||||
|
from . import ks_key_fetch
|
||||||
|
from . import ks_chat_channel
|
||||||
|
|
||||||
|
|
||||||
BIN
ks_dashboard_ninja/models/__pycache__/Kpi_mail.cpython-310.pyc
Normal file
BIN
ks_dashboard_ninja/models/__pycache__/Kpi_mail.cpython-311.pyc
Normal file
BIN
ks_dashboard_ninja/models/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
ks_dashboard_ninja/models/__pycache__/__init__.cpython-311.pyc
Normal file
397
ks_dashboard_ninja/models/ks_ai_ninja_dashboard.py
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
import base64
|
||||||
|
import io
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
# import osgit
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import requests
|
||||||
|
from gtts import gTTS
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from odoo.tools import config
|
||||||
|
|
||||||
|
from odoo import api, fields, models, _
|
||||||
|
|
||||||
|
_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 ID',
|
||||||
|
domain="[('access_ids','!=',False),('transient','=',False),"
|
||||||
|
"('model','not ilike','base_import%'),'|',('model','not ilike','ir.%'),('model','=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 val['name'] != 'id' and val['name'] != 'sequence' and val['store'] == True}
|
||||||
|
ks_fields_name = {val['name']:val['type'] for val in ks_filtered_fields.values()}
|
||||||
|
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,
|
||||||
|
'type': self.ks_type,
|
||||||
|
'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 Dashboards')])[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': 'Generate items with AI',
|
||||||
|
'params': {'ks_dashboard_id': ks_create_record.id, 'explain_ai_whole': True},
|
||||||
|
'tag': 'ks_ai_dashboard_ninja',
|
||||||
|
'context': context,
|
||||||
|
'target':'new'
|
||||||
|
}
|
||||||
|
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 val[
|
||||||
|
'name'] != 'id' and val['name'] != 'sequence' and val['store'] == True}
|
||||||
|
ks_fields_name = {val['name']: val['type'] for val in ks_filtered_fields.values()}
|
||||||
|
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"))
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def ks_generate_analysis(self, ks_items_explain, ks_rest_items, dashboard_id):
|
||||||
|
if ks_items_explain:
|
||||||
|
result = []
|
||||||
|
api_key = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'ks_dashboard_ninja.dn_api_key')
|
||||||
|
ks_url = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'ks_dashboard_ninja.url')
|
||||||
|
words = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'ks_dashboard_ninja.ks_analysis_word_length')
|
||||||
|
url = ks_url + "/api/v1/ks_dn_main_api"
|
||||||
|
for i in range(0, len(ks_items_explain)):
|
||||||
|
if api_key and url:
|
||||||
|
json_data = {'name': api_key,
|
||||||
|
'items': json.dumps(ks_items_explain[i]),
|
||||||
|
'type': 'ks_ai_explain',
|
||||||
|
'url': self.env['ir.config_parameter'].sudo().get_param('web.base.url'),
|
||||||
|
'db_name': self.env.cr.dbname,
|
||||||
|
'words': words if words else 100
|
||||||
|
}
|
||||||
|
ks_response = requests.post(url, data=json_data)
|
||||||
|
if ks_response.status_code == 200 and json.loads(ks_response.text):
|
||||||
|
ks_ai_response = json.loads(ks_response.text)
|
||||||
|
item = ks_ai_response[0]
|
||||||
|
if item['analysis'] or item['insights']:
|
||||||
|
try:
|
||||||
|
self.env['ks_dashboard_ninja.item'].browse(item['id']).write({
|
||||||
|
'ks_ai_analysis': item['analysis'] + 'ks_gap' + item['insights']
|
||||||
|
})
|
||||||
|
result.append(True)
|
||||||
|
except:
|
||||||
|
result
|
||||||
|
else:
|
||||||
|
result
|
||||||
|
|
||||||
|
else:
|
||||||
|
result
|
||||||
|
else:
|
||||||
|
raise ValidationError(_("Please put API key and URL"))
|
||||||
|
if len(result):
|
||||||
|
if self.env.context.get('explain_items_with_ai', False):
|
||||||
|
self.env['ks_dashboard_ninja.board'].browse(dashboard_id).write({
|
||||||
|
'ks_ai_explain_dash': False
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self.env['ks_dashboard_ninja.board'].browse(dashboard_id).write({
|
||||||
|
'ks_ai_explain_dash': True
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise ValidationError(_("AI Responds with the wrong analysis. Please try again "))
|
||||||
|
elif ks_rest_items:
|
||||||
|
if self.env.context.get('explain_items_with_ai', False):
|
||||||
|
self.env['ks_dashboard_ninja.board'].browse(dashboard_id).write({
|
||||||
|
'ks_ai_explain_dash': False
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self.env['ks_dashboard_ninja.board'].browse(dashboard_id).write({
|
||||||
|
'ks_ai_explain_dash': True
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_ai_explain(self, item_id):
|
||||||
|
res = self.env['ks_dashboard_ninja.item'].browse(item_id).ks_ai_analysis
|
||||||
|
return res
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def ks_switch_default_dashboard(self, dashboard_id):
|
||||||
|
self.env['ks_dashboard_ninja.board'].browse(dashboard_id).write({
|
||||||
|
'ks_ai_explain_dash': False
|
||||||
|
})
|
||||||
|
return True
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def ks_generatetext_to_speech(self, item_id):
|
||||||
|
if (item_id):
|
||||||
|
try:
|
||||||
|
ks_text = self.env['ks_dashboard_ninja.item'].browse(item_id).ks_ai_analysis
|
||||||
|
if ks_text:
|
||||||
|
language = 'en'
|
||||||
|
ks_myobj = gTTS(text=ks_text, lang=language, slow=False)
|
||||||
|
audio_data = io.BytesIO()
|
||||||
|
ks_myobj.write_to_fp(audio_data)
|
||||||
|
audio_data.seek(0)
|
||||||
|
binary_data = audio_data.read()
|
||||||
|
wav_file = base64.b64encode(binary_data).decode('UTF-8')
|
||||||
|
data = {"snd": wav_file}
|
||||||
|
return json.dumps(data)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
_logger.error(e)
|
||||||
|
raise ValidationError(_("Some problem in audio generation."))
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def ks_gen_chat_res(self,**kwargs):
|
||||||
|
ks_question = kwargs.get('ks_question')
|
||||||
|
url = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'ks_dashboard_ninja.url') + "/api/v1/get_sql_query"
|
||||||
|
data = {
|
||||||
|
"question": ks_question,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
ks_response = requests.post(url,data=data)
|
||||||
|
if (ks_response.status_code == 200):
|
||||||
|
ks_response = json.loads(ks_response.text)['response']['Query']
|
||||||
|
return self.ks_gen_dataframe(ks_response,ks_question)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
_logger.error(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def ks_gen_dataframe(self,ks_query,question):
|
||||||
|
host = config.get('db_host', False)
|
||||||
|
user = quote(config.get('db_user', False))
|
||||||
|
port = config.get('db_port', False) or 5432
|
||||||
|
password = quote(config.get('db_password', False))
|
||||||
|
db = config.get('db_name', False) or self.env.cr.dbname
|
||||||
|
if not all([host, user, port, password, db]):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
sql_uri = f"postgresql+psycopg2://{user}:{password}@{host}:{port}/{db}"
|
||||||
|
ks_fixed_url = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'ks_dashboard_ninja.url') + "/api/v1/get_fixed_query"
|
||||||
|
try:
|
||||||
|
df = pd.read_sql(ks_query, sql_uri)
|
||||||
|
except Exception as e:
|
||||||
|
ks_query_data = {
|
||||||
|
'query':ks_query,
|
||||||
|
'error':e
|
||||||
|
}
|
||||||
|
fixed_query = requests.post(ks_fixed_url, data=ks_query_data)
|
||||||
|
if fixed_query.status_code == 200:
|
||||||
|
ks_corrected_query = fixed_query.text
|
||||||
|
df = pd.read_sql(ks_corrected_query, sql_uri)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if any(df.dtypes == 'datetime64[ns]'):
|
||||||
|
datetime_columns = [col for col in df.columns if df[col].dtype == 'datetime64[ns]']
|
||||||
|
df[datetime_columns] = df[datetime_columns].astype(str)
|
||||||
|
|
||||||
|
# Convert DataFrame to JSON
|
||||||
|
if len(df) >= 100:
|
||||||
|
df = df.head(100)
|
||||||
|
partial_data = True
|
||||||
|
|
||||||
|
df_json = df.to_json(orient='records')
|
||||||
|
|
||||||
|
ans = "As dataframe having more data to analyse we are not showing dataframe summary"
|
||||||
|
# Generate answer
|
||||||
|
if len(df) < 13:
|
||||||
|
ks_ans_url = self.env['ir.config_parameter'].sudo().get_param(
|
||||||
|
'ks_dashboard_ninja.url') + "/api/v1/get_answer"
|
||||||
|
ks_ans_data = {'df':df.to_dict(orient='records'),'question':question}
|
||||||
|
ans = requests.post(ks_ans_url, json = ks_ans_data)
|
||||||
|
if ans.status_code == 200:
|
||||||
|
ans = ans.text
|
||||||
|
response_json = {
|
||||||
|
"Dataframe": df_json,
|
||||||
|
"Answer": ans,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
response_json = {
|
||||||
|
"Dataframe": df_json,
|
||||||
|
"Answer": ans,
|
||||||
|
}
|
||||||
|
return response_json
|
||||||
90
ks_dashboard_ninja/models/ks_ai_whole_dashboard.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
from odoo import fields, models, _
|
||||||
|
|
||||||
|
_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 Dashboards')])[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 val['name'] != 'id' and val['name'] != 'sequence' and val['store'] == True}
|
||||||
|
ks_fields_name = {val['name']:val['type'] for val in ks_filtered_fields.values()}
|
||||||
|
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',
|
||||||
|
'tag': 'reload',
|
||||||
|
}
|
||||||
|
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"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
29
ks_dashboard_ninja/models/ks_chat_channel.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class ChatChannel(models.Model):
|
||||||
|
_inherit = 'discuss.channel'
|
||||||
|
|
||||||
|
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board')
|
||||||
|
ks_dashboard_item_id = fields.Many2one('ks_dashboard_ninja.item')
|
||||||
|
|
||||||
|
def ks_chat_wizard_channel_id(self, **kwargs):
|
||||||
|
item_id = kwargs.get('item_id')
|
||||||
|
dashboard_id = kwargs.get('dashboard_id')
|
||||||
|
item_name = kwargs.get('item_name')
|
||||||
|
dashboard_name = kwargs.get('dashboard_name')
|
||||||
|
|
||||||
|
channel = self.search([('ks_dashboard_item_id', '=', item_id)], limit=1)
|
||||||
|
|
||||||
|
if not channel:
|
||||||
|
users = self.env['res.users'].search([
|
||||||
|
('active', '=', True), ('groups_id', 'in', self.env.ref('base.group_user').id)]).mapped('partner_id.id')
|
||||||
|
|
||||||
|
channel = self.sudo().create({
|
||||||
|
'name': f"{dashboard_name} - {item_name}",
|
||||||
|
'ks_dashboard_board_id': dashboard_id,
|
||||||
|
'ks_dashboard_item_id': item_id,
|
||||||
|
'channel_member_ids': [(0, 0, {'partner_id': partner_id}) for partner_id in users]
|
||||||
|
})
|
||||||
|
|
||||||
|
return channel.id if channel else None
|
||||||
25
ks_dashboard_ninja/models/ks_child_dashboard.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNinjaBoardItemAction(models.Model):
|
||||||
|
_name = 'ks_dashboard_ninja.child_board'
|
||||||
|
_description = 'Dashboard Ninja Child Board'
|
||||||
|
|
||||||
|
name = fields.Char()
|
||||||
|
ks_dashboard_ninja_id = fields.Many2one("ks_dashboard_ninja.board", string="Select Dashboard")
|
||||||
|
ks_gridstack_config = fields.Char('Item Configurations')
|
||||||
|
# ks_board_active_user_ids = fields.Many2many('res.users')
|
||||||
|
ks_active = fields.Boolean("Is Selected")
|
||||||
|
ks_dashboard_menu_name = fields.Char(string="Menu Name", related='ks_dashboard_ninja_id.ks_dashboard_menu_name', store=True)
|
||||||
|
board_type = fields.Selection([('default', 'Default'), ('child', 'Child')])
|
||||||
|
company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company)
|
||||||
|
ks_computed_group_access = fields.Many2many('res.groups', compute='_compute_ks_computed_group_access', store=True)
|
||||||
|
|
||||||
|
@api.depends('ks_dashboard_ninja_id.ks_dashboard_group_access')
|
||||||
|
def _compute_ks_computed_group_access(self):
|
||||||
|
for record in self:
|
||||||
|
record.ks_computed_group_access = record.ks_dashboard_ninja_id.ks_dashboard_group_access
|
||||||
|
|
||||||
|
|
||||||
|
def write(self,vals):
|
||||||
|
return super(KsDashboardNinjaBoardItemAction, self).write(vals)
|
||||||
182
ks_dashboard_ninja/models/ks_country_bounds.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
country = {
|
||||||
|
'AF': ('Afghanistan', (60.5284298033, 29.318572496, 75.1580277851, 38.4862816432)),
|
||||||
|
'AO': ('Angola', (11.6400960629, -17.9306364885, 24.0799052263, -4.43802336998)),
|
||||||
|
'AL': ('Albania', (19.3044861183, 39.624997667, 21.0200403175, 42.6882473822)),
|
||||||
|
'AE': ('United Arab Emirates', (51.5795186705, 22.4969475367, 56.3968473651, 26.055464179)),
|
||||||
|
'AR': ('Argentina', (-73.4154357571, -55.25, -53.628348965, -21.8323104794)),
|
||||||
|
'AM': ('Armenia', (43.5827458026, 38.7412014837, 46.5057198423, 41.2481285671)),
|
||||||
|
'AQ': ('Antarctica', (-180.0, -90.0, 180.0, -63.2706604895)),
|
||||||
|
'TF': ('Fr. S. and Antarctic Lands', (68.72, -49.775, 70.56, -48.625)),
|
||||||
|
'AU': ('Australia', (113.338953078, -43.6345972634, 153.569469029, -10.6681857235)),
|
||||||
|
'AT': ('Austria', (9.47996951665, 46.4318173285, 16.9796667823, 49.0390742051)),
|
||||||
|
'AZ': ('Azerbaijan', (44.7939896991, 38.2703775091, 50.3928210793, 41.8606751572)),
|
||||||
|
'BI': ('Burundi', (29.0249263852, -4.49998341229, 30.752262811, -2.34848683025)),
|
||||||
|
'BE': ('Belgium', (2.51357303225, 49.5294835476, 6.15665815596, 51.4750237087)),
|
||||||
|
'BJ': ('Benin', (0.772335646171, 6.14215770103, 3.79711225751, 12.2356358912)),
|
||||||
|
'BF': ('Burkina Faso', (-5.47056494793, 9.61083486576, 2.17710778159, 15.1161577418)),
|
||||||
|
'BD': ('Bangladesh', (88.0844222351, 20.670883287, 92.6727209818, 26.4465255803)),
|
||||||
|
'BG': ('Bulgaria', (22.3805257504, 41.2344859889, 28.5580814959, 44.2349230007)),
|
||||||
|
'BS': ('Bahamas', (-78.98, 23.71, -77.0, 27.04)),
|
||||||
|
'BA': ('Bosnia and Herz.', (15.7500260759, 42.65, 19.59976, 45.2337767604)),
|
||||||
|
'BY': ('Belarus', (23.1994938494, 51.3195034857, 32.6936430193, 56.1691299506)),
|
||||||
|
'BZ': ('Belize', (-89.2291216703, 15.8869375676, -88.1068129138, 18.4999822047)),
|
||||||
|
'BO': ('Bolivia', (-69.5904237535, -22.8729187965, -57.4983711412, -9.76198780685)),
|
||||||
|
'BR': ('Brazil', (-73.9872354804, -33.7683777809, -34.7299934555, 5.24448639569)),
|
||||||
|
'BN': ('Brunei', (114.204016555, 4.007636827, 115.450710484, 5.44772980389)),
|
||||||
|
'BT': ('Bhutan', (88.8142484883, 26.7194029811, 92.1037117859, 28.2964385035)),
|
||||||
|
'BW': ('Botswana', (19.8954577979, -26.8285429827, 29.4321883481, -17.6618156877)),
|
||||||
|
'CF': ('Central African Rep.', (14.4594071794, 2.2676396753, 27.3742261085, 11.1423951278)),
|
||||||
|
'CA': ('Canada', (-140.99778, 41.6751050889, -52.6480987209, 83.23324)),
|
||||||
|
'CH': ('Switzerland', (6.02260949059, 45.7769477403, 10.4427014502, 47.8308275417)),
|
||||||
|
'CL': ('Chile', (-75.6443953112, -55.61183, -66.95992, -17.5800118954)),
|
||||||
|
'CN': ('China', (73.6753792663, 18.197700914, 135.026311477, 53.4588044297)),
|
||||||
|
'CI': ('Ivory Coast', (-8.60288021487, 4.33828847902, -2.56218950033, 10.5240607772)),
|
||||||
|
'CM': ('Cameroon', (8.48881554529, 1.72767263428, 16.0128524106, 12.8593962671)),
|
||||||
|
'CD': ('Congo (Kinshasa)', (12.1823368669, -13.2572266578, 31.1741492042, 5.25608775474)),
|
||||||
|
'CG': ('Congo (Brazzaville)', (11.0937728207, -5.03798674888, 18.4530652198, 3.72819651938)),
|
||||||
|
'CO': ('Colombia', (-78.9909352282, -4.29818694419, -66.8763258531, 12.4373031682)),
|
||||||
|
'CR': ('Costa Rica', (-85.94172543, 8.22502798099, -82.5461962552, 11.2171192489)),
|
||||||
|
'CU': ('Cuba', (-84.9749110583, 19.8554808619, -74.1780248685, 23.1886107447)),
|
||||||
|
'CY': ('Cyprus', (32.2566671079, 34.5718694118, 34.0048808123, 35.1731247015)),
|
||||||
|
'CZ': ('Czech Rep.', (12.2401111182, 48.5553052842, 18.8531441586, 51.1172677679)),
|
||||||
|
'DE': ('Germany', (5.98865807458, 47.3024876979, 15.0169958839, 54.983104153)),
|
||||||
|
'DJ': ('Djibouti', (41.66176, 10.9268785669, 43.3178524107, 12.6996385767)),
|
||||||
|
'DK': ('Denmark', (8.08997684086, 54.8000145534, 12.6900061378, 57.730016588)),
|
||||||
|
'DO': ('Dominican Rep.', (-71.9451120673, 17.598564358, -68.3179432848, 19.8849105901)),
|
||||||
|
'DZ': ('Algeria', (-8.68439978681, 19.0573642034, 11.9995056495, 37.1183806422)),
|
||||||
|
'EC': ('Ecuador', (-80.9677654691, -4.95912851321, -75.2337227037, 1.3809237736)),
|
||||||
|
'EG': ('Egypt', (24.70007, 22.0, 36.86623, 31.58568)),
|
||||||
|
'ER': ('Eritrea', (36.3231889178, 12.4554157577, 43.0812260272, 17.9983074)),
|
||||||
|
'ES': ('Spain', (-9.39288367353, 35.946850084, 3.03948408368, 43.7483377142)),
|
||||||
|
'EE': ('Estonia', (23.3397953631, 57.4745283067, 28.1316992531, 59.6110903998)),
|
||||||
|
'ET': ('Ethiopia', (32.95418, 3.42206, 47.78942, 14.95943)),
|
||||||
|
'FI': ('Finland', (20.6455928891, 59.846373196, 31.5160921567, 70.1641930203)),
|
||||||
|
'FJ': ('Fiji', (-180.0, -18.28799, 180.0, -16.0208822567)),
|
||||||
|
'FK': ('Falkland Is.', (-61.2, -52.3, -57.75, -51.1)),
|
||||||
|
'FR': ('France', (-54.5247541978, 2.05338918702, 9.56001631027, 51.1485061713)),
|
||||||
|
'GA': ('Gabon', (8.79799563969, -3.97882659263, 14.4254557634, 2.32675751384)),
|
||||||
|
'GB': ('United Kingdom', (-7.57216793459, 49.959999905, 1.68153079591, 58.6350001085)),
|
||||||
|
'GE': ('Georgia', (39.9550085793, 41.0644446885, 46.6379081561, 43.553104153)),
|
||||||
|
'GH': ('Ghana', (-3.24437008301, 4.71046214438, 1.0601216976, 11.0983409693)),
|
||||||
|
'GN': ('Guinea', (-15.1303112452, 7.3090373804, -7.83210038902, 12.5861829696)),
|
||||||
|
'GM': ('Gambia', (-16.8415246241, 13.1302841252, -13.8449633448, 13.8764918075)),
|
||||||
|
'GW': ('Guinea Bissau', (-16.6774519516, 11.0404116887, -13.7004760401, 12.6281700708)),
|
||||||
|
'GQ': ('Eq. Guinea', (9.3056132341, 1.01011953369, 11.285078973, 2.28386607504)),
|
||||||
|
'GR': ('Greece', (20.1500159034, 34.9199876979, 26.6041955909, 41.8269046087)),
|
||||||
|
'GL': ('Greenland', (-73.297, 60.03676, -12.20855, 83.64513)),
|
||||||
|
'GT': ('Guatemala', (-92.2292486234, 13.7353376327, -88.2250227526, 17.8193260767)),
|
||||||
|
'GY': ('Guyana', (-61.4103029039, 1.26808828369, -56.5393857489, 8.36703481692)),
|
||||||
|
'HN': ('Honduras', (-89.3533259753, 12.9846857772, -83.147219001, 16.0054057886)),
|
||||||
|
'HR': ('Croatia', (13.6569755388, 42.47999136, 19.3904757016, 46.5037509222)),
|
||||||
|
'HT': ('Haiti', (-74.4580336168, 18.0309927434, -71.6248732164, 19.9156839055)),
|
||||||
|
'HU': ('Hungary', (16.2022982113, 45.7594811061, 22.710531447, 48.6238540716)),
|
||||||
|
'ID': ('Indonesia', (95.2930261576, -10.3599874813, 141.03385176, 5.47982086834)),
|
||||||
|
'IN': ('India', (68.1766451354, 7.96553477623, 97.4025614766, 35.4940095078)),
|
||||||
|
'IE': ('Ireland', (-9.97708574059, 51.6693012559, -6.03298539878, 55.1316222195)),
|
||||||
|
'IR': ('Iran', (44.1092252948, 25.0782370061, 63.3166317076, 39.7130026312)),
|
||||||
|
'IQ': ('Iraq', (38.7923405291, 29.0990251735, 48.5679712258, 37.3852635768)),
|
||||||
|
'IS': ('Iceland', (-24.3261840479, 63.4963829617, -13.609732225, 66.5267923041)),
|
||||||
|
'IL': ('Israel', (34.2654333839, 29.5013261988, 35.8363969256, 33.2774264593)),
|
||||||
|
'IT': ('Italy', (6.7499552751, 36.619987291, 18.4802470232, 47.1153931748)),
|
||||||
|
'JM': ('Jamaica', (-78.3377192858, 17.7011162379, -76.1996585761, 18.5242184514)),
|
||||||
|
'JO': ('Jordan', (34.9226025734, 29.1974946152, 39.1954683774, 33.3786864284)),
|
||||||
|
'JP': ('Japan', (129.408463169, 31.0295791692, 145.543137242, 45.5514834662)),
|
||||||
|
'KZ': ('Kazakhstan', (46.4664457538, 40.6623245306, 87.3599703308, 55.3852501491)),
|
||||||
|
'KE': ('Kenya', (33.8935689697, -4.67677, 41.8550830926, 5.506)),
|
||||||
|
'KG': ('Kyrgyzstan', (69.464886916, 39.2794632025, 80.2599902689, 43.2983393418)),
|
||||||
|
'KH': ('Cambodia', (102.3480994, 10.4865436874, 107.614547968, 14.5705838078)),
|
||||||
|
'KR': ('S. Korea', (126.117397903, 34.3900458847, 129.468304478, 38.6122429469)),
|
||||||
|
'KW': ('Kuwait', (46.5687134133, 28.5260627304, 48.4160941913, 30.0590699326)),
|
||||||
|
'LA': ('Laos', (100.115987583, 13.88109101, 107.564525181, 22.4647531194)),
|
||||||
|
'LB': ('Lebanon', (35.1260526873, 33.0890400254, 36.6117501157, 34.6449140488)),
|
||||||
|
'LR': ('Liberia', (-11.4387794662, 4.35575511313, -7.53971513511, 8.54105520267)),
|
||||||
|
'LY': ('Libya', (9.31941084152, 19.58047, 25.16482, 33.1369957545)),
|
||||||
|
'LK': ('Sri Lanka', (79.6951668639, 5.96836985923, 81.7879590189, 9.82407766361)),
|
||||||
|
'LS': ('Lesotho', (26.9992619158, -30.6451058896, 29.3251664568, -28.6475017229)),
|
||||||
|
'LT': ('Lithuania', (21.0558004086, 53.9057022162, 26.5882792498, 56.3725283881)),
|
||||||
|
'LU': ('Luxembourg', (5.67405195478, 49.4426671413, 6.24275109216, 50.1280516628)),
|
||||||
|
'LV': ('Latvia', (21.0558004086, 55.61510692, 28.1767094256, 57.9701569688)),
|
||||||
|
'MA': ('Morocco', (-17.0204284327, 21.4207341578, -1.12455115397, 35.7599881048)),
|
||||||
|
'MD': ('Moldova', (26.6193367856, 45.4882831895, 30.0246586443, 48.4671194525)),
|
||||||
|
'MG': ('Madagascar', (43.2541870461, -25.6014344215, 50.4765368996, -12.0405567359)),
|
||||||
|
'MX': ('Mexico', (-117.12776, 14.5388286402, -86.811982388, 32.72083)),
|
||||||
|
'MK': ('Macedonia', (20.46315, 40.8427269557, 22.9523771502, 42.3202595078)),
|
||||||
|
'ML': ('Mali', (-12.1707502914, 10.0963607854, 4.27020999514, 24.9745740829)),
|
||||||
|
'MM': ('Myanmar', (92.3032344909, 9.93295990645, 101.180005324, 28.335945136)),
|
||||||
|
'ME': ('Montenegro', (18.45, 41.87755, 20.3398, 43.52384)),
|
||||||
|
'MN': ('Mongolia', (87.7512642761, 41.5974095729, 119.772823928, 52.0473660345)),
|
||||||
|
'MZ': ('Mozambique', (30.1794812355, -26.7421916643, 40.7754752948, -10.3170960425)),
|
||||||
|
'MR': ('Mauritania', (-17.0634232243, 14.6168342147, -4.92333736817, 27.3957441269)),
|
||||||
|
'MW': ('Malawi', (32.6881653175, -16.8012997372, 35.7719047381, -9.23059905359)),
|
||||||
|
'MY': ('Malaysia', (100.085756871, 0.773131415201, 119.181903925, 6.92805288332)),
|
||||||
|
'NA': ('Namibia', (11.7341988461, -29.045461928, 25.0844433937, -16.9413428687)),
|
||||||
|
'NC': ('New Caledonia', (164.029605748, -22.3999760881, 167.120011428, -20.1056458473)),
|
||||||
|
'NE': ('Niger', (0.295646396495, 11.6601671412, 15.9032466977, 23.4716684026)),
|
||||||
|
'NG': ('Nigeria', (2.69170169436, 4.24059418377, 14.5771777686, 13.8659239771)),
|
||||||
|
'NI': ('Nicaragua', (-87.6684934151, 10.7268390975, -83.147219001, 15.0162671981)),
|
||||||
|
'NL': ('Netherlands', (3.31497114423, 50.803721015, 7.09205325687, 53.5104033474)),
|
||||||
|
'NO': ('Norway', (4.99207807783, 58.0788841824, 31.29341841, 80.6571442736)),
|
||||||
|
'NP': ('Nepal', (80.0884245137, 26.3978980576, 88.1748043151, 30.4227169866)),
|
||||||
|
'NZ': ('New Zealand', (166.509144322, -46.641235447, 178.517093541, -34.4506617165)),
|
||||||
|
'OM': ('Oman', (52.0000098, 16.6510511337, 59.8080603372, 26.3959343531)),
|
||||||
|
'PK': ('Pakistan', (60.8742484882, 23.6919650335, 77.8374507995, 37.1330309108)),
|
||||||
|
'PA': ('Panama', (-82.9657830472, 7.2205414901, -77.2425664944, 9.61161001224)),
|
||||||
|
'PE': ('Peru', (-81.4109425524, -18.3479753557, -68.6650797187, -0.0572054988649)),
|
||||||
|
'PH': ('Philippines', (117.17427453, 5.58100332277, 126.537423944, 18.5052273625)),
|
||||||
|
'PG': ('Papua New Guinea', (141.000210403, -10.6524760881, 156.019965448, -2.50000212973)),
|
||||||
|
'PL': ('Poland', (14.0745211117, 49.0273953314, 24.0299857927, 54.8515359564)),
|
||||||
|
'PR': ('Puerto Rico', (-67.2424275377, 17.946553453, -65.5910037909, 18.5206011011)),
|
||||||
|
'KP': ('N. Korea', (124.265624628, 37.669070543, 130.780007359, 42.9853868678)),
|
||||||
|
'PT': ('Portugal', (-9.52657060387, 36.838268541, -6.3890876937, 42.280468655)),
|
||||||
|
'PY': ('Paraguay', (-62.6850571357, -27.5484990374, -54.2929595608, -19.3427466773)),
|
||||||
|
'QA': ('Qatar', (50.7439107603, 24.5563308782, 51.6067004738, 26.1145820175)),
|
||||||
|
'RO': ('Romania', (20.2201924985, 43.6884447292, 29.62654341, 48.2208812526)),
|
||||||
|
'RU': ('Russia', (-180.0, 41.151416124, 180.0, 81.2504)),
|
||||||
|
'RW': ('Rwanda', (29.0249263852, -2.91785776125, 30.8161348813, -1.13465911215)),
|
||||||
|
'SA': ('Saudi Arabia', (34.6323360532, 16.3478913436, 55.6666593769, 32.161008816)),
|
||||||
|
'SD': ('Sudan', (21.93681, 8.61972971293, 38.4100899595, 22.0)),
|
||||||
|
'SS': ('S. Sudan', (23.8869795809, 3.50917, 35.2980071182, 12.2480077571)),
|
||||||
|
'SN': ('Senegal', (-17.6250426905, 12.332089952, -11.4678991358, 16.5982636581)),
|
||||||
|
'SB': ('Solomon Is.', (156.491357864, -10.8263672828, 162.398645868, -6.59933847415)),
|
||||||
|
'SL': ('Sierra Leone', (-13.2465502588, 6.78591685631, -10.2300935531, 10.0469839543)),
|
||||||
|
'SV': ('El Salvador', (-90.0955545723, 13.1490168319, -87.7235029772, 14.4241327987)),
|
||||||
|
'SO': ('Somalia', (40.98105, -1.68325, 51.13387, 12.02464)),
|
||||||
|
'RS': ('Serbia', (18.82982, 42.2452243971, 22.9860185076, 46.1717298447)),
|
||||||
|
'SR': ('Suriname', (-58.0446943834, 1.81766714112, -53.9580446031, 6.0252914494)),
|
||||||
|
'SK': ('Slovakia', (16.8799829444, 47.7584288601, 22.5581376482, 49.5715740017)),
|
||||||
|
'SI': ('Slovenia', (13.6981099789, 45.4523163926, 16.5648083839, 46.8523859727)),
|
||||||
|
'SE': ('Sweden', (11.0273686052, 55.3617373725, 23.9033785336, 69.1062472602)),
|
||||||
|
'SZ': ('Swaziland', (30.6766085141, -27.2858794085, 32.0716654803, -25.660190525)),
|
||||||
|
'SY': ('Syria', (35.7007979673, 32.312937527, 42.3495910988, 37.2298725449)),
|
||||||
|
'TD': ('Chad', (13.5403935076, 7.42192454674, 23.88689, 23.40972)),
|
||||||
|
'TG': ('Togo', (-0.0497847151599, 5.92883738853, 1.86524051271, 11.0186817489)),
|
||||||
|
'TH': ('Thailand', (97.3758964376, 5.69138418215, 105.589038527, 20.4178496363)),
|
||||||
|
'TJ': ('Tajikistan', (67.4422196796, 36.7381712916, 74.9800024759, 40.9602133245)),
|
||||||
|
'TM': ('Turkmenistan', (52.5024597512, 35.2706639674, 66.5461503437, 42.7515510117)),
|
||||||
|
'TL': ('East Timor', (124.968682489, -9.39317310958, 127.335928176, -8.27334482181)),
|
||||||
|
'TT': ('Trinidad and Tobago', (-61.95, 10.0, -60.895, 10.89)),
|
||||||
|
'TN': ('Tunisia', (7.52448164229, 30.3075560572, 11.4887874691, 37.3499944118)),
|
||||||
|
'TR': ('Turkey', (26.0433512713, 35.8215347357, 44.7939896991, 42.1414848903)),
|
||||||
|
'TW': ('Taiwan', (120.106188593, 21.9705713974, 121.951243931, 25.2954588893)),
|
||||||
|
'TZ': ('Tanzania', (29.3399975929, -11.7209380022, 40.31659, -0.95)),
|
||||||
|
'UG': ('Uganda', (29.5794661801, -1.44332244223, 35.03599, 4.24988494736)),
|
||||||
|
'UA': ('Ukraine', (22.0856083513, 44.3614785833, 40.0807890155, 52.3350745713)),
|
||||||
|
'UY': ('Uruguay', (-58.4270741441, -34.9526465797, -53.209588996, -30.1096863746)),
|
||||||
|
'US': ('United States', (-171.791110603, 18.91619, -66.96466, 71.3577635769)),
|
||||||
|
'UZ': ('Uzbekistan', (55.9289172707, 37.1449940049, 73.055417108, 45.5868043076)),
|
||||||
|
'VE': ('Venezuela', (-73.3049515449, 0.724452215982, -59.7582848782, 12.1623070337)),
|
||||||
|
'VN': ('Vietnam', (102.170435826, 8.59975962975, 109.33526981, 23.3520633001)),
|
||||||
|
'VU': ('Vanuatu', (166.629136998, -16.5978496233, 167.844876744, -14.6264970842)),
|
||||||
|
'PS': ('West Bank', (34.9274084816, 31.3534353704, 35.5456653175, 32.5325106878)),
|
||||||
|
'YE': ('Yemen', (42.6048726743, 12.5859504257, 53.1085726255, 19.0000033635)),
|
||||||
|
'ZA': ('South Africa', (16.3449768409, -34.8191663551, 32.830120477, -22.0913127581)),
|
||||||
|
'ZM': ('Zambia', (21.887842645, -17.9612289364, 33.4856876971, -8.23825652429)),
|
||||||
|
'ZW': ('Zimbabwe', (25.2642257016, -22.2716118303, 32.8498608742, -15.5077869605)),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_country_code(country_id):
|
||||||
|
if country_id in country.keys():
|
||||||
|
return country.get(country_id)
|
||||||
|
else:
|
||||||
|
return {}
|
||||||
89
ks_dashboard_ninja/models/ks_dashboard_filters.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNinjaTemplate(models.Model):
|
||||||
|
_name = 'ks_dashboard_ninja.board_defined_filters'
|
||||||
|
_description = 'Dashboard Ninja Defined Filters'
|
||||||
|
|
||||||
|
name = fields.Char('Filter Label')
|
||||||
|
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard")
|
||||||
|
ks_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_domain = fields.Char(string="Domain", help="Define conditions for filter. ")
|
||||||
|
ks_domain_temp = fields.Char(string="Domain Substitute")
|
||||||
|
ks_model_name = fields.Char(related='ks_model_id.model', string="Model Name")
|
||||||
|
display_type = fields.Selection([
|
||||||
|
('line_section', "Section")], default=False, help="Technical field for UX purpose.")
|
||||||
|
sequence = fields.Integer(default=10,
|
||||||
|
help="Gives the sequence order when displaying a list of payment terms lines.")
|
||||||
|
ks_is_active = fields.Boolean(string="Active")
|
||||||
|
|
||||||
|
@api.onchange('ks_domain')
|
||||||
|
def ks_domain_onchange(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.ks_model_id:
|
||||||
|
try:
|
||||||
|
ks_domain = rec.ks_domain
|
||||||
|
if ks_domain and "%UID" in ks_domain:
|
||||||
|
ks_domain = ks_domain.replace('"%UID"', str(self.env.user.id))
|
||||||
|
if ks_domain and "%MYCOMPANY" in ks_domain:
|
||||||
|
ks_domain = ks_domain.replace('"%MYCOMPANY"', str(self.env.company.id))
|
||||||
|
self.env[rec.ks_model_id.model].search_count(safe_eval(ks_domain))
|
||||||
|
except Exception as e:
|
||||||
|
raise ValidationError(_("Something went wrong . Possibly it is due to wrong input type for domain"))
|
||||||
|
|
||||||
|
@api.constrains('ks_domain', 'ks_model_id')
|
||||||
|
def ks_domain_check(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.ks_model_id and not rec.ks_domain:
|
||||||
|
raise ValidationError(_("Domain can not be empty"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNinjaTemplate(models.Model):
|
||||||
|
_name = 'ks_dashboard_ninja.board_custom_filters'
|
||||||
|
_description = 'Dashboard Ninja Custom Filters'
|
||||||
|
|
||||||
|
name = fields.Char("Filter Label")
|
||||||
|
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard")
|
||||||
|
ks_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_domain_field_id = fields.Many2one('ir.model.fields',
|
||||||
|
domain="[('model_id','=',ks_model_id),"
|
||||||
|
"('name','!=','id'),('store','=',True),"
|
||||||
|
"('ttype', 'in', ['boolean', 'char', "
|
||||||
|
"'date', 'datetime', 'float', 'integer', 'html', 'many2many', "
|
||||||
|
"'many2one', 'monetary', 'one2many', 'text', 'selection'])]",
|
||||||
|
string="Domain Field")
|
||||||
|
|
||||||
|
@api.onchange('ks_model_id')
|
||||||
|
def on_change_ks_model_id(self):
|
||||||
|
self.ks_domain_field_id = False
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNinjaTemplateFilters(models.Model):
|
||||||
|
_name = 'ks_dashboard_ninja.favourite_filters'
|
||||||
|
_description = 'Dashboard Ninja Favourite Filters'
|
||||||
|
|
||||||
|
name = fields.Char("Filter Label")
|
||||||
|
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard")
|
||||||
|
ks_filter = fields.Char("Filter")
|
||||||
|
ks_access_id = fields.Integer("Access Id")
|
||||||
|
ks_filter_type = fields.Char(default='favourite')
|
||||||
|
|
||||||
|
_sql_constraints = [
|
||||||
|
('name_uniq', 'UNIQUE (name)', 'The name of the filter must be unique!'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
1515
ks_dashboard_ninja/models/ks_dashboard_ninja.py
Normal file
4598
ks_dashboard_ninja/models/ks_dashboard_ninja_items.py
Normal file
41
ks_dashboard_ninja/models/ks_dashboard_templates.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNinjaTemplate(models.Model):
|
||||||
|
_name = 'ks_dashboard_ninja.board_template'
|
||||||
|
_description = 'Dashboard Ninja Template'
|
||||||
|
|
||||||
|
name = fields.Char()
|
||||||
|
ks_gridstack_config = fields.Char()
|
||||||
|
ks_item_count = fields.Integer()
|
||||||
|
ks_template_type = fields.Selection([('ks_default', 'Predefined'), ('ks_custom', 'Custom')],
|
||||||
|
string="Template Format")
|
||||||
|
ks_dashboard_item_ids = fields.One2many('ks_dashboard_ninja.item', 'ks_dashboard_board_template_id',
|
||||||
|
string="Template Type")
|
||||||
|
ks_dashboard_board_id = fields.Many2one('ks_dashboard_ninja.board', string="Dashboard", help="""
|
||||||
|
Items Configuration and their position in the dashboard will be copied from the selected dashboard
|
||||||
|
and will be saved as template.
|
||||||
|
""")
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
for val in vals_list:
|
||||||
|
if val.get('ks_template_type', False) and val.get('ks_dashboard_board_id', False):
|
||||||
|
dashboard_id = self.env['ks_dashboard_ninja.board'].browse(val.get('ks_dashboard_board_id'))
|
||||||
|
val['ks_gridstack_config'] = dashboard_id.ks_gridstack_config
|
||||||
|
val['ks_item_count'] = len(dashboard_id.ks_dashboard_items_ids)
|
||||||
|
val['ks_dashboard_item_ids'] = [(4, x.copy({'ks_dashboard_ninja_board_id': False}).id) for x in
|
||||||
|
dashboard_id.ks_dashboard_items_ids]
|
||||||
|
recs = super(KsDashboardNinjaTemplate, self).create(vals_list)
|
||||||
|
return recs
|
||||||
|
|
||||||
|
def write(self, val):
|
||||||
|
if val.get('ks_dashboard_board_id', False):
|
||||||
|
dashboard_id = self.env['ks_dashboard_ninja.board'].browse(val.get('ks_dashboard_board_id'))
|
||||||
|
val['ks_gridstack_config'] = dashboard_id.ks_gridstack_config
|
||||||
|
val['ks_item_count'] = len(dashboard_id.ks_dashboard_items_ids)
|
||||||
|
val['ks_dashboard_item_ids'] = [(6, 0,
|
||||||
|
[x.copy({'ks_dashboard_ninja_board_id': False}).id for x in
|
||||||
|
dashboard_id.ks_dashboard_items_ids])]
|
||||||
|
recs = super(KsDashboardNinjaTemplate, self).write(val)
|
||||||
|
return recs
|
||||||
141
ks_dashboard_ninja/models/ks_dn_to_do_item.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import json
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
import copy
|
||||||
|
import re
|
||||||
|
from odoo.exceptions import ValidationError, UserError
|
||||||
|
|
||||||
|
class KsDashboardNinjaItems(models.Model):
|
||||||
|
_inherit = 'ks_dashboard_ninja.item'
|
||||||
|
|
||||||
|
ks_to_do_preview = fields.Char("To Do Preview", default="To Do Preview")
|
||||||
|
ks_dn_header_lines = fields.One2many('ks_to.do.headers', 'ks_dn_item_id')
|
||||||
|
ks_to_do_data = fields.Char(string="To Do Data in JSon", compute='ks_get_to_do_view_data', compute_sudo=False)
|
||||||
|
ks_header_bg_color = fields.Char(string="Header Background Color", default="#8e24aa,0.99",
|
||||||
|
help=' Select the background color with transparency. ')
|
||||||
|
|
||||||
|
@api.depends('ks_dn_header_lines', 'ks_dashboard_item_type')
|
||||||
|
def ks_get_to_do_view_data(self):
|
||||||
|
for rec in self:
|
||||||
|
ks_to_do_data = rec._ksGetToDOData()
|
||||||
|
rec.ks_to_do_data = ks_to_do_data
|
||||||
|
|
||||||
|
def _ksGetToDOData(self):
|
||||||
|
ks_to_do_data = {
|
||||||
|
'label': [],
|
||||||
|
'ks_link': [],
|
||||||
|
'ks_href_id': [],
|
||||||
|
'ks_section_id': [],
|
||||||
|
'ks_content': {},
|
||||||
|
'ks_content_record_id': {},
|
||||||
|
'ks_content_active': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.ks_dn_header_lines:
|
||||||
|
for ks_dn_header_line in self.ks_dn_header_lines:
|
||||||
|
ks_to_do_header_label = ks_dn_header_line.ks_to_do_header[:]
|
||||||
|
ks_to_do_data['label'].append(ks_to_do_header_label)
|
||||||
|
ks_dn_header_line_id = str(ks_dn_header_line.id)
|
||||||
|
if type(ks_dn_header_line.id).__name__ != 'int' and ks_dn_header_line.id.ref != None:
|
||||||
|
ks_dn_header_line_id = ks_dn_header_line.id.ref
|
||||||
|
if ' ' in ks_dn_header_line.ks_to_do_header:
|
||||||
|
ks_temp = ks_dn_header_line.ks_to_do_header.replace(" ", "")
|
||||||
|
ks_to_do_data['ks_link'].append('#' + ks_temp + ks_dn_header_line_id)
|
||||||
|
ks_to_do_data['ks_href_id'].append(ks_temp + str(ks_dn_header_line.id))
|
||||||
|
|
||||||
|
elif ks_dn_header_line.ks_to_do_header[0].isdigit():
|
||||||
|
ks_temp = ks_dn_header_line.ks_to_do_header.replace(
|
||||||
|
ks_dn_header_line.ks_to_do_header[0], 'z')
|
||||||
|
ks_to_do_data['ks_link'].append('#' + ks_temp + ks_dn_header_line_id)
|
||||||
|
ks_to_do_data['ks_href_id'].append(ks_temp + str(ks_dn_header_line.id))
|
||||||
|
else:
|
||||||
|
ks_to_do_data['ks_link'].append('#' + ks_dn_header_line.ks_to_do_header + ks_dn_header_line_id)
|
||||||
|
ks_to_do_data['ks_href_id'].append(ks_dn_header_line.ks_to_do_header + str(ks_dn_header_line.id))
|
||||||
|
ks_to_do_data['ks_section_id'].append(str(ks_dn_header_line.id))
|
||||||
|
if len(ks_dn_header_line.ks_to_do_description_lines):
|
||||||
|
for ks_to_do_description_line in ks_dn_header_line.ks_to_do_description_lines:
|
||||||
|
if ' ' in ks_dn_header_line.ks_to_do_header or ks_dn_header_line.ks_to_do_header[0].isdigit():
|
||||||
|
if ks_to_do_data['ks_content'].get(ks_temp +
|
||||||
|
str(ks_dn_header_line.id), False):
|
||||||
|
|
||||||
|
ks_to_do_data['ks_content'][ks_temp +
|
||||||
|
str(ks_dn_header_line.id)].append(
|
||||||
|
ks_to_do_description_line.ks_description)
|
||||||
|
ks_to_do_data['ks_content_record_id'][ks_temp +
|
||||||
|
str(ks_dn_header_line.id)].append(
|
||||||
|
str(ks_to_do_description_line.id))
|
||||||
|
ks_to_do_data['ks_content_active'][ks_temp +
|
||||||
|
str(ks_dn_header_line.id)].append(
|
||||||
|
str(ks_to_do_description_line.ks_active))
|
||||||
|
else:
|
||||||
|
ks_to_do_data['ks_content'][ks_temp +
|
||||||
|
str(ks_dn_header_line.id)] = [
|
||||||
|
ks_to_do_description_line.ks_description]
|
||||||
|
ks_to_do_data['ks_content_record_id'][ks_temp +
|
||||||
|
str(ks_dn_header_line.id)] = [
|
||||||
|
str(ks_to_do_description_line.id)]
|
||||||
|
ks_to_do_data['ks_content_active'][ks_temp +
|
||||||
|
str(ks_dn_header_line.id)] = [
|
||||||
|
str(ks_to_do_description_line.ks_active)]
|
||||||
|
else:
|
||||||
|
if ks_to_do_data['ks_content'].get(ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id), False):
|
||||||
|
|
||||||
|
ks_to_do_data['ks_content'][ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id)].append(
|
||||||
|
ks_to_do_description_line.ks_description)
|
||||||
|
ks_to_do_data['ks_content_record_id'][ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id)].append(
|
||||||
|
str(ks_to_do_description_line.id))
|
||||||
|
ks_to_do_data['ks_content_active'][ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id)].append(
|
||||||
|
str(ks_to_do_description_line.ks_active))
|
||||||
|
else:
|
||||||
|
ks_to_do_data['ks_content'][ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id)] = [
|
||||||
|
ks_to_do_description_line.ks_description]
|
||||||
|
ks_to_do_data['ks_content_record_id'][ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id)] = [
|
||||||
|
str(ks_to_do_description_line.id)]
|
||||||
|
ks_to_do_data['ks_content_active'][ks_dn_header_line.ks_to_do_header +
|
||||||
|
str(ks_dn_header_line.id)] = [
|
||||||
|
str(ks_to_do_description_line.ks_active)]
|
||||||
|
|
||||||
|
ks_to_do_data = json.dumps(ks_to_do_data)
|
||||||
|
else:
|
||||||
|
ks_to_do_data = False
|
||||||
|
return ks_to_do_data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class KsToDoheaders(models.Model):
|
||||||
|
_name = 'ks_to.do.headers'
|
||||||
|
_description = "to do headers"
|
||||||
|
|
||||||
|
ks_dn_item_id = fields.Many2one('ks_dashboard_ninja.item')
|
||||||
|
ks_to_do_header = fields.Char('Header')
|
||||||
|
ks_to_do_description_lines = fields.One2many('ks_to.do.description', 'ks_to_do_header_id')
|
||||||
|
|
||||||
|
@api.constrains('ks_to_do_header')
|
||||||
|
def ks_to_do_header_check(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.ks_to_do_header:
|
||||||
|
ks_check = bool(re.match('^[A-Z, a-z,0-9,_]+$', rec.ks_to_do_header))
|
||||||
|
if not ks_check:
|
||||||
|
raise ValidationError(_("Special characters are not allowed only string and digits allow for section header"))
|
||||||
|
|
||||||
|
@api.onchange('ks_to_do_header')
|
||||||
|
def ks_to_do_header_onchange(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.ks_to_do_header:
|
||||||
|
ks_check = bool(re.match('^[A-Z, a-z,0-9,_]+$', rec.ks_to_do_header))
|
||||||
|
if not ks_check:
|
||||||
|
raise ValidationError(_("Special characters are not allowed only string and digits allow for section header"))
|
||||||
|
|
||||||
|
class KsToDODescription(models.Model):
|
||||||
|
_name = 'ks_to.do.description'
|
||||||
|
_description = 'to do description'
|
||||||
|
|
||||||
|
ks_to_do_header_id = fields.Many2one('ks_to.do.headers')
|
||||||
|
ks_description = fields.Text('Description')
|
||||||
|
ks_active = fields.Boolean('Active Description', default=True)
|
||||||
30
ks_dashboard_ninja/models/ks_import_dashboard.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import base64
|
||||||
|
import logging
|
||||||
|
from odoo import api, fields, models, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNInjaImport(models.TransientModel):
|
||||||
|
_name = 'ks_dashboard_ninja.import'
|
||||||
|
_description = 'Import Dashboard'
|
||||||
|
|
||||||
|
ks_import_dashboard = fields.Binary(string="Upload Dashboard", attachment=True)
|
||||||
|
ks_top_menu_id = fields.Many2one('ir.ui.menu', string="Show Under Menu", domain="[('parent_id','=',False)]",
|
||||||
|
required=True,
|
||||||
|
default=lambda self: self.env['ir.ui.menu'].search(
|
||||||
|
[('name', '=', 'My Dashboards')]))
|
||||||
|
|
||||||
|
def ks_do_action(self):
|
||||||
|
for rec in self:
|
||||||
|
try:
|
||||||
|
ks_result = base64.b64decode(rec.ks_import_dashboard)
|
||||||
|
self.env['ks_dashboard_ninja.board'].ks_import_dashboard(ks_result, self.ks_top_menu_id)
|
||||||
|
except Exception as e:
|
||||||
|
_logger.warning("Error importing dashboard for record %s: %s", rec.id, str(e))
|
||||||
|
raise ValidationError(_("%s") % str(e))
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'reload',
|
||||||
|
}
|
||||||
29
ks_dashboard_ninja/models/ks_item_action.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import UserError, ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class KsDashboardNinjaBoardItemAction(models.TransientModel):
|
||||||
|
_name = 'ks_ninja_dashboard.item_action'
|
||||||
|
_description = 'Dashboard Ninja Item Actions'
|
||||||
|
|
||||||
|
name = fields.Char()
|
||||||
|
ks_dashboard_item_ids = fields.Many2many("ks_dashboard_ninja.item", string="Dashboard Items")
|
||||||
|
ks_action = fields.Selection([('move', 'Move'),
|
||||||
|
('duplicate', 'Duplicate'),
|
||||||
|
], string="Action")
|
||||||
|
ks_dashboard_ninja_id = fields.Many2one("ks_dashboard_ninja.board", string="Select Dashboard")
|
||||||
|
ks_dashboard_ninja_ids = fields.Many2many("ks_dashboard_ninja.board", string="Select Dashboards")
|
||||||
|
|
||||||
|
# Move or Copy item to another dashboard action
|
||||||
|
|
||||||
|
def action_item_move_copy_action(self):
|
||||||
|
if self.ks_action == 'move':
|
||||||
|
for item in self.ks_dashboard_item_ids:
|
||||||
|
item.ks_dashboard_ninja_board_id = self.ks_dashboard_ninja_id
|
||||||
|
elif self.ks_action == 'duplicate':
|
||||||
|
# Using sudo here to allow creating same item without any security error
|
||||||
|
for dashboard_id in self.ks_dashboard_ninja_ids:
|
||||||
|
for item in self.ks_dashboard_item_ids:
|
||||||
|
item.sudo().copy({'ks_dashboard_ninja_board_id': dashboard_id.id})
|
||||||
31
ks_dashboard_ninja/models/ks_key_fetch.py
Normal 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)
|
||||||
52
ks_dashboard_ninja/models/res_settings.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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')
|
||||||
|
enable_chart_zoom = fields.Boolean(string="Enable Zooming for charts", store=True,
|
||||||
|
config_parameter='ks_dashboard_ninja.enable_chart_zoom')
|
||||||
|
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")
|
||||||
|
ks_analysis_word_length = fields.Selection([("50","50 words"),("100","100 words"),("150","150 words"),("200","200 words"),],default ="100", string="AI Analysis length", store=True,config_parameter="ks_dashboard_ninja.ks_analysis_word_length")
|
||||||
|
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"))
|
||||||
|
|
||||||
5
ks_dashboard_ninja/requirements.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
xlrd==2.0.1
|
||||||
|
openpyxl == 3.1.2
|
||||||
|
gTTS == 2.5.1
|
||||||
|
pandas==2.1.2
|
||||||
|
SQLAlchemy==2.0.32
|
||||||
36
ks_dashboard_ninja/security/ir.model.access.csv
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_ks_dashboard_ninja_board,ks_dashboard_ninja.board,model_ks_dashboard_ninja_board,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_kpi_mail,ks_dashboard_ninja.kpi_mail,model_ks_dashboard_ninja_kpi_mail,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_item,ks_dashboard_ninja.item,model_ks_dashboard_ninja_item,base.group_user,1,1,1,1
|
||||||
|
access_ks_to_do_headers,ks_to.do.headers,model_ks_to_do_headers,base.group_user,1,1,1,1
|
||||||
|
access_ks_to_do_description,ks_to.do.description,model_ks_to_do_description,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_child_board,ks_dashboard_ninja.child_board,model_ks_dashboard_ninja_child_board,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_board_defined_filters,ks_dashboard_ninja.board_defined_filters,model_ks_dashboard_ninja_board_defined_filters,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_board_custom_filters,ks_dashboard_ninja.board_custom_filters,model_ks_dashboard_ninja_board_custom_filters,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_ks_dashboard_ninja_board_template,ks_dashboard_ninja.board_template,model_ks_dashboard_ninja_board_template,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_item_goal,ks_dashboard_ninja_item_goal,model_ks_dashboard_ninja_item_goal,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_item_action,ks_dashboard_ninja_item_action,model_ks_dashboard_ninja_item_action,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_item_multiplier,ks_dashboard_item.multiplier,model_ks_dashboard_item_multiplier,base.group_user,1,1,1,1
|
||||||
|
access_ks_ninja_dashboard_item_action,ks_ninja_dashboard.item_action,model_ks_ninja_dashboard_item_action,base.group_user,1,1,1,0
|
||||||
|
access_ks_dashboard_group_by,ks.dashboard.group.by,model_ks_dashboard_group_by,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_csv_group_by,ks.dashboard.csv.group.by,model_ks_dashboard_csv_group_by,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_new,ks.dashboard.new,model_ks_dashboard_new,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_csv_new,ks.dashboard.csv.new,model_ks_dashboard_csv_new,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_import,ks_dashboard_ninja.import,model_ks_dashboard_ninja_import,base.group_system,1,1,1,0
|
||||||
|
access_ir_actions_act_window_view,ir.actions.act_window.view,base.model_ir_actions_act_window_view,base.group_user,1,0,0,0
|
||||||
|
access_ir_actions_act_window,ir.actions.act_window,base.model_ir_actions_act_window,base.group_user,1,0,0,0
|
||||||
|
access_ir_actions_client,ir.actions.client,base.model_ir_actions_client,base.group_user,1,0,0,0
|
||||||
|
access_ir_ui_menu,ir.ui.menu,base.model_ir_ui_menu,base.group_user,1,1,0,0
|
||||||
|
|
||||||
|
access_ir_model_group_user,ir.model,base.model_ir_model,base.group_user,1,0,0,0
|
||||||
|
access_ir_model_fields_group_user,ir.model.fields,base.model_ir_model_fields,base.group_user,1,0,0,0
|
||||||
|
|
||||||
|
access_ir_model_ks_dashboard_wizard,ks_dashboard_wizard,model_ks_dashboard_wizard,base.group_user,1,1,1,1
|
||||||
|
access_ir_model_ks_duplicate_dashboard_wizard,ks_duplicate_dashboard__wizard,model_ks_dashboard_duplicate_wizard,base.group_user,1,1,1,1
|
||||||
|
access_ir_model_ks_delete_dashboard_wizard,ks_delete_dashboard__wizard,model_ks_dashboard_delete_wizard,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_arti_int,ks_dashboard_ninja.arti_int,model_ks_dashboard_ninja_arti_int,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_ai_dashboard,ks_dashboard_ninja.ai_dashboard,model_ks_dashboard_ninja_ai_dashboard,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_fetch_key,ks_dashboard_ninja.fetch_key,model_ks_dashboard_ninja_fetch_key,base.group_user,1,1,1,1
|
||||||
|
access_ks_dashboard_ninja_favourite_filters,ks_dashboard_ninja.favourite_filters,model_ks_dashboard_ninja_favourite_filters,,1,1,1,1
|
||||||
|
59
ks_dashboard_ninja/security/ks_security_groups.xml
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
|
||||||
|
<record id="ir_rule_ks_dashboard_item_company_restrictions" model="ir.rule">
|
||||||
|
<field name="name">Dashboard Item Company Restriction: User Can only view their company and sub companies
|
||||||
|
items.
|
||||||
|
</field>
|
||||||
|
<field name="model_id" ref="model_ks_dashboard_ninja_item"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
['|',('ks_company_id','in', company_ids),('ks_company_id','=',False)]</field>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ir_rule_ks_accessible_dashboards" model="ir.rule">
|
||||||
|
<field name="name">Dashboard Record Level Groups Access: Show dashboards matching user's assigned groups.</field>
|
||||||
|
<field name="model_id" ref="model_ks_dashboard_ninja_board"/>
|
||||||
|
<field name="domain_force">['|', ('ks_dashboard_group_access', '=' , False), ('ks_dashboard_group_access','in', user.groups_id.ids)]</field>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ir_rule_ks_accessible_child_dashboards" model="ir.rule">
|
||||||
|
<field name="name">Child Dashboard Record Level Groups Access: Show dashboards matching user's assigned groups.</field>
|
||||||
|
<field name="model_id" ref="model_ks_dashboard_ninja_child_board"/>
|
||||||
|
<field name="domain_force">['|', ('ks_computed_group_access', '=', False), ('ks_computed_group_access', 'in', user.groups_id.ids)]</field>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]" />
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ir_rule_ks_admin_accessible_dashboards" model="ir.rule">
|
||||||
|
<field name="name">Dashboard Record Level Groups Access: Show all dashboards to admin regardless of assigned groups.</field>
|
||||||
|
<field name="model_id" ref="model_ks_dashboard_ninja_board"/>
|
||||||
|
<field name="domain_force">[(1, '=', 1)]</field>
|
||||||
|
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="ir_rule_ks_admin_accessible_child_dashboards" model="ir.rule">
|
||||||
|
<field name="name">Child Dashboard Record Level Groups Access: Show all dashboards to admin regardless of assigned groups.</field>
|
||||||
|
<field name="model_id" ref="model_ks_dashboard_ninja_child_board"/>
|
||||||
|
<field name="domain_force">[(1, '=', 1)]</field>
|
||||||
|
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.module.category" id="ks_dashboard_ninja_security_groups">
|
||||||
|
<field name="name">Dashboard Ninja Rights</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="res.groups" id="ks_dashboard_ninja_group_manager">
|
||||||
|
<field name="name">Show Full Dashboard Features</field>
|
||||||
|
<field name="category_id" ref="ks_dashboard_ninja.ks_dashboard_ninja_security_groups"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="base.group_system" model="res.groups">
|
||||||
|
<field name="implied_ids" eval="[(4, ref('ks_dashboard_ninja.ks_dashboard_ninja_group_manager'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
BIN
ks_dashboard_ninja/static/description/iconi.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
5
ks_dashboard_ninja/static/images/3dcube.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M29.6084 5.1793L44.5271 13.223C46.2688 14.1626 46.2688 16.8439 44.5271 17.7835L29.6084 25.8272C28.2792 26.5376 26.7209 26.5376 25.3917 25.8272L10.4729 17.7835C8.73127 16.8439 8.73127 14.1626 10.4729 13.223L25.3917 5.1793C26.7209 4.46888 28.2792 4.46888 29.6084 5.1793Z" stroke="#241C1D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M8.2729 23.2143L22.1375 30.158C23.8562 31.0288 24.9562 32.7934 24.9562 34.7184V47.8268C24.9562 49.7289 22.9625 50.9434 21.2666 50.0955L7.40206 43.1518C5.68331 42.2809 4.58331 40.5163 4.58331 38.5913V25.483C4.58331 23.5809 6.57706 22.3663 8.2729 23.2143Z" stroke="#241C1D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M46.7271 23.2143L32.8625 30.158C31.1438 31.0288 30.0438 32.7934 30.0438 34.7184V47.8268C30.0438 49.7289 32.0375 50.9434 33.7333 50.0955L47.5979 43.1518C49.3167 42.2809 50.4167 40.5163 50.4167 38.5913V25.483C50.4167 23.5809 48.4229 22.3663 46.7271 23.2143Z" stroke="#241C1D" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
4
ks_dashboard_ninja/static/images/Area.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.33398 19.9997C3.33398 12.1429 3.33398 8.21456 5.77476 5.77378C8.21554 3.33301 12.1439 3.33301 20.0007 3.33301C27.8574 3.33301 31.7858 3.33301 34.2265 5.77378C36.6673 8.21456 36.6673 12.1429 36.6673 19.9997C36.6673 27.8564 36.6673 31.7848 34.2265 34.2256C31.7858 36.6663 27.8574 36.6663 20.0007 36.6663C12.1439 36.6663 8.21554 36.6663 5.77476 34.2256C3.33398 31.7848 3.33398 27.8564 3.33398 19.9997Z" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
<path d="M11.666 23.3337L14.6608 19.7399C15.8476 18.3158 16.4409 17.6037 17.2216 17.6037C18.0022 17.6037 18.5956 18.3158 19.7823 19.7399L20.2164 20.2608C21.4031 21.6849 21.9965 22.3969 22.7771 22.3969C23.5578 22.3969 24.1511 21.6849 25.3379 20.2608L28.3327 16.667" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 875 B |
6
ks_dashboard_ninja/static/images/Bar.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.33398 19.9997C3.33398 12.1429 3.33398 8.21456 5.77476 5.77378C8.21554 3.33301 12.1439 3.33301 20.0007 3.33301C27.8574 3.33301 31.7858 3.33301 34.2265 5.77378C36.6673 8.21456 36.6673 12.1429 36.6673 19.9997C36.6673 27.8564 36.6673 31.7848 34.2265 34.2256C31.7858 36.6663 27.8574 36.6663 20.0007 36.6663C12.1439 36.6663 8.21554 36.6663 5.77476 34.2256C3.33398 31.7848 3.33398 27.8564 3.33398 19.9997Z" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
<path d="M11.666 30V15" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M20 30V10" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M28.334 30.0003V21.667" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 805 B |
6
ks_dashboard_ninja/static/images/Bullet.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M13.334 21.667C14.2545 21.667 15.0007 20.9208 15.0007 20.0003C15.0007 19.0799 14.2545 18.3337 13.334 18.3337C12.4135 18.3337 11.6673 19.0799 11.6673 20.0003C11.6673 20.9208 12.4135 21.667 13.334 21.667Z" fill="#1C1C1C"/>
|
||||||
|
<path d="M21.6673 20.0003C21.6673 20.9208 20.9211 21.667 20.0007 21.667C19.0802 21.667 18.334 20.9208 18.334 20.0003C18.334 19.0799 19.0802 18.3337 20.0007 18.3337C20.9211 18.3337 21.6673 19.0799 21.6673 20.0003Z" fill="#1C1C1C"/>
|
||||||
|
<path d="M26.6673 21.667C27.5878 21.667 28.334 20.9208 28.334 20.0003C28.334 19.0799 27.5878 18.3337 26.6673 18.3337C25.7468 18.3337 25.0007 19.0799 25.0007 20.0003C25.0007 20.9208 25.7468 21.667 26.6673 21.667Z" fill="#1C1C1C"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.5733 5.41699C13.5104 5.41697 11.0843 5.41695 9.18561 5.67222C7.23158 5.93493 5.65 6.48846 4.40272 7.73573C3.15545 8.983 2.60192 10.5646 2.33921 12.5186C2.08394 14.4173 2.08396 16.8434 2.08398 19.9063V20.0944C2.08396 23.1573 2.08394 25.5833 2.33921 27.482C2.60192 29.4361 3.15545 31.0177 4.40272 32.2649C5.65 33.5122 7.23158 34.0657 9.18561 34.3284C11.0843 34.5837 13.5103 34.5837 16.5732 34.5837H23.428C26.4909 34.5837 28.917 34.5837 30.8157 34.3284C32.7697 34.0657 34.3513 33.5122 35.5986 32.2649C36.8459 31.0177 37.3994 29.4361 37.6621 27.482C37.9174 25.5834 37.9173 23.1573 37.9173 20.0944V19.9063C37.9173 16.8434 37.9174 14.4173 37.6621 12.5186C37.3994 10.5646 36.8459 8.983 35.5986 7.73573C34.3513 6.48846 32.7697 5.93493 30.8157 5.67222C28.917 5.41695 26.491 5.41697 23.428 5.41699H16.5733ZM6.17049 9.5035C6.87584 8.79815 7.84192 8.37537 9.51873 8.14993C11.2315 7.91965 13.4893 7.91699 16.6673 7.91699H23.334C26.512 7.91699 28.7698 7.91965 30.4826 8.14993C32.1594 8.37537 33.1255 8.79815 33.8308 9.5035C34.5362 10.2088 34.9589 11.1749 35.1844 12.8517C35.4147 14.5645 35.4173 16.8223 35.4173 20.0003C35.4173 23.1784 35.4147 25.4361 35.1844 27.1489C34.9589 28.8257 34.5362 29.7918 33.8308 30.4972C33.1255 31.2025 32.1594 31.6253 30.4826 31.8507C28.7698 32.081 26.512 32.0837 23.334 32.0837H16.6673C13.4893 32.0837 11.2315 32.081 9.51873 31.8507C7.84192 31.6253 6.87584 31.2025 6.17049 30.4972C5.46514 29.7918 5.04236 28.8257 4.81692 27.1489C4.58664 25.4361 4.58399 23.1784 4.58399 20.0003C4.58399 16.8223 4.58664 14.5645 4.81692 12.8517C5.04236 11.1749 5.46514 10.2088 6.17049 9.5035Z" fill="#1C1C1C"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.4 KiB |
5
ks_dashboard_ninja/static/images/Chatbot.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8.01721 5.0351C8.24008 4.4328 9.09196 4.4328 9.31483 5.0351L10.7978 9.04284C10.8679 9.2322 11.0172 9.3815 11.2066 9.45157L15.2143 10.9346C15.8166 11.1574 15.8166 12.0093 15.2143 12.2322L11.2066 13.7152C11.0172 13.7853 10.8679 13.9346 10.7978 14.1239L9.31483 18.1316C9.09196 18.7339 8.24008 18.7339 8.01721 18.1316L6.53421 14.1239C6.46414 13.9346 6.31484 13.7853 6.12548 13.7152L2.11774 12.2322C1.51544 12.0093 1.51544 11.1574 2.11774 10.9346L6.12548 9.45157C6.31484 9.3815 6.46414 9.2322 6.53421 9.04284L8.01721 5.0351Z" fill="#ABC8E7" stroke="#6789C6" stroke-width="1.25"/>
|
||||||
|
<path d="M17.623 5L13.623 5" stroke="#6789C6" stroke-width="1.25" stroke-linecap="round"/>
|
||||||
|
<path d="M15.623 7L15.623 3" stroke="#6789C6" stroke-width="1.25" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 870 B |
BIN
ks_dashboard_ninja/static/images/Comp.gif
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
3
ks_dashboard_ninja/static/images/Doughnut.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0007 2.08301C10.1055 2.08301 2.08398 10.1046 2.08398 19.9997C2.08398 29.8948 10.1055 37.9163 20.0007 37.9163C29.8958 37.9163 37.9173 29.8948 37.9173 19.9997C37.9173 10.1046 29.8958 2.08301 20.0007 2.08301ZM4.58398 19.9997C4.58398 16.1925 5.96405 12.7076 8.25121 10.018L13.5887 15.3554C12.6421 16.66 12.084 18.2647 12.084 19.9997C12.084 21.7347 12.6421 23.3394 13.5886 24.6439L8.2512 29.9813C5.96405 27.2918 4.58398 23.8069 4.58398 19.9997ZM15.3564 13.5877L10.019 8.25023C12.7086 5.96307 16.1934 4.58301 20.0007 4.58301C23.8079 4.58301 27.2927 5.96307 29.9823 8.25023L24.6449 13.5877C23.3403 12.6411 21.7357 12.083 20.0007 12.083C18.2656 12.083 16.661 12.6411 15.3564 13.5877ZM10.019 31.7491C12.7086 34.0363 16.1934 35.4163 20.0007 35.4163C23.8079 35.4163 27.2927 34.0363 29.9823 31.7491L24.6449 26.4117C23.3403 27.3582 21.7357 27.9163 20.0007 27.9163C18.2656 27.9163 16.661 27.3582 15.3564 26.4117L10.019 31.7491ZM26.4127 24.6439L31.7501 29.9813C34.0373 27.2918 35.4173 23.8069 35.4173 19.9997C35.4173 16.1925 34.0373 12.7076 31.7501 10.018L26.4126 15.3554C27.3592 16.66 27.9173 18.2647 27.9173 19.9997C27.9173 21.7347 27.3592 23.3394 26.4127 24.6439ZM14.584 19.9997C14.584 17.0081 17.0091 14.583 20.0007 14.583C22.9922 14.583 25.4173 17.0081 25.4173 19.9997C25.4173 22.9912 22.9922 25.4163 20.0007 25.4163C17.0091 25.4163 14.584 22.9912 14.584 19.9997Z" fill="#1C1C1C"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
6
ks_dashboard_ninja/static/images/Flower.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.76044 33.0423L6.761 33.0428C6.82645 33.1093 6.89234 33.1752 6.95866 33.2405L6.95913 33.241C10.8038 37.0329 17.4193 34.2692 17.4193 28.7803V22.582H11.2211C5.73227 22.582 2.96851 29.1976 6.76044 33.0423ZM17.4193 20.582H11.2211C4.00159 20.582 0.266883 29.3066 5.33649 34.4467C5.40873 34.52 5.48147 34.5927 5.55472 34.6649C10.6948 39.7345 19.4193 35.9998 19.4193 28.7803V22.582V20.582H17.4193Z" fill="#1C1C1C"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.4221 6.41028C30.3447 3.37612 25.0176 5.58641 25.0176 10.0103V14.9824H29.9898C34.415 14.9824 36.6243 9.65289 33.5898 6.57783M25.0176 16.9824H29.9898C36.1381 16.9824 39.3319 9.54851 35.0129 5.17258C34.9512 5.11006 34.889 5.04795 34.8265 4.98625C30.4488 0.669851 23.0176 3.86251 23.0176 10.0103V14.9824V16.9824H25.0176ZM33.4222 6.41039C33.4783 6.46572 33.5341 6.52143 33.5895 6.5775L33.4222 6.41039Z" fill="#1C1C1C"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M23.0176 22.4424V20.4424H25.0176H28.2789C32.9246 20.4424 35.3475 26.0624 32.0827 29.3675C32.0357 29.415 31.9885 29.4623 31.9409 29.5092C28.634 32.7704 23.0176 30.3481 23.0176 25.7036V22.4424ZM30.6598 27.962C30.6188 28.0035 30.5775 28.0448 30.536 28.0858L30.6598 27.962ZM30.536 28.0858C28.5346 30.0585 25.0176 28.6316 25.0176 25.7036V22.4424H28.2789C31.2089 22.4424 32.6341 25.9626 30.6603 27.9615" fill="#1C1C1C"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.1211 15.6758L21.1211 17.6758L19.1211 17.6758L14.9191 17.6758C9.44285 17.6758 6.58673 11.051 10.4352 7.15495C10.4906 7.09892 10.5463 7.04325 10.6023 6.98795C14.5006 3.14365 21.1211 5.99903 21.1211 11.474L21.1211 15.6758ZM11.8576 8.56092C9.30016 11.1508 11.1585 15.6758 14.9191 15.6758L19.1211 15.6758L19.1211 11.474C19.1211 7.7152 14.5992 5.85532 12.0067 8.41198C11.9569 8.46113 11.9074 8.51062 11.8581 8.56045" fill="#1C1C1C"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
3
ks_dashboard_ninja/static/images/Funnel.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M20.1515 36.6663C20.7543 36.6663 21.3324 36.4269 21.7586 36.0007C22.1848 35.5745 22.4242 34.9964 22.4242 34.3936V25.583L34.1894 11.7876C34.5283 11.4854 34.8018 11.1172 34.9933 10.7055C35.1848 10.2939 35.2902 9.84745 35.303 9.39361C35.303 5.45422 27.5 3.33301 20.1515 3.33301C12.803 3.33301 5 5.45422 5 9.39361C5.01451 9.84897 5.12137 10.2966 5.31411 10.7095C5.50684 11.1223 5.78143 11.4916 6.12121 11.7951L17.8788 25.583V34.3936C17.8788 34.9964 18.1182 35.5745 18.5445 36.0007C18.9707 36.4269 19.5487 36.6663 20.1515 36.6663ZM20.303 4.99967C28.3409 4.99967 33.3333 7.2421 33.3333 9.39361C33.3096 9.77448 33.1604 10.1368 32.9091 10.4239L32.697 10.6739C31.0152 12.4239 26.5985 13.333 20.1515 13.333C13.7045 13.333 9.18182 12.4239 7.5 10.6815L7.25758 10.4012C7.01389 10.1196 6.87007 9.76538 6.84848 9.39361C6.84848 7.2421 12.2652 4.99967 20.303 4.99967ZM9.93939 13.9391C13.2406 14.9867 16.6884 15.4982 20.1515 15.4542C23.6147 15.4982 27.0624 14.9867 30.3636 13.9391L21.0909 24.8103C20.9736 24.9475 20.9091 25.1221 20.9091 25.3027V34.3936C20.9091 34.5945 20.8293 34.7872 20.6872 34.9293C20.5451 35.0714 20.3524 35.1512 20.1515 35.1512C19.9506 35.1512 19.7579 35.0714 19.6158 34.9293C19.4738 34.7872 19.3939 34.5945 19.3939 34.3936V25.3027C19.394 25.1221 19.3295 24.9475 19.2121 24.8103L9.93939 13.9391Z" fill="#1C1C1C"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
6
ks_dashboard_ninja/static/images/Horizontal Bar.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.33398 19.9997C3.33398 12.1429 3.33398 8.21456 5.77476 5.77378C8.21554 3.33301 12.1439 3.33301 20.0007 3.33301C27.8574 3.33301 31.7858 3.33301 34.2265 5.77378C36.6673 8.21456 36.6673 12.1429 36.6673 19.9997C36.6673 27.8564 36.6673 31.7848 34.2265 34.2256C31.7858 36.6663 27.8574 36.6663 20.0007 36.6663C12.1439 36.6663 8.21554 36.6663 5.77476 34.2256C3.33398 31.7848 3.33398 27.8564 3.33398 19.9997Z" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
<path d="M12.5 11.667L17.5 11.667" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M12.5 20H22.5" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M12.5 28.334H27.5" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 815 B |
6
ks_dashboard_ninja/static/images/KPI.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3 4H36.3333" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M14.666 18.1673L16.8208 16.0125C17.3764 15.4569 17.6542 15.1792 17.9993 15.1792C18.3445 15.1792 18.6223 15.4569 19.1779 16.0125L20.1542 16.9888C20.7097 17.5444 20.9875 17.8221 21.3327 17.8221C21.6779 17.8221 21.9556 17.5444 22.5112 16.9888L24.666 14.834" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M19.666 35.667L19.666 29.0003" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M33.0007 4V18.1667C33.0007 23.2735 33.0007 25.827 31.327 27.4135C29.6533 29 26.9596 29 21.5721 29H17.7626C12.3751 29 9.68134 29 8.00766 27.4135C6.33398 25.827 6.33398 23.2735 6.33398 18.1667V4" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 846 B |
4
ks_dashboard_ninja/static/images/Line.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M36.6673 36.6663H20.0007C12.1439 36.6663 8.21554 36.6663 5.77476 34.2256C3.33398 31.7848 3.33398 27.8564 3.33398 19.9997V3.33301" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M31.6669 11.667L26.4702 18.211C25.6742 19.2134 25.2762 19.7146 24.8193 19.9589C24.1167 20.3344 23.2772 20.3527 22.559 20.008C22.0919 19.7839 21.6725 19.3005 20.8336 18.3336C19.9947 17.3668 19.5753 16.8834 19.1082 16.6592C18.39 16.3146 17.5505 16.3328 16.8479 16.7084C16.391 16.9527 15.993 17.4538 15.197 18.4562L10 25.0003" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 693 B |
8
ks_dashboard_ninja/static/images/List.svg
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4.33398 19.9997C4.33398 16.043 4.33611 13.1762 4.63016 10.989C4.92035 8.8306 5.47825 7.48451 6.48187 6.48089C7.48549 5.47727 8.83157 4.91938 10.99 4.62919C13.1771 4.33513 16.044 4.33301 20.0007 4.33301C23.9573 4.33301 26.8242 4.33513 29.0113 4.62919C31.1697 4.91938 32.5158 5.47727 33.5194 6.48089C34.5231 7.48451 35.0809 8.8306 35.3711 10.989C35.6652 13.1762 35.6673 16.043 35.6673 19.9997C35.6673 23.9563 35.6652 26.8232 35.3711 29.0104C35.0809 31.1688 34.5231 32.5148 33.5194 33.5185C32.5158 34.5221 31.1697 35.08 29.0113 35.3702C26.8242 35.6642 23.9573 35.6663 20.0007 35.6663C16.044 35.6663 13.1771 35.6642 10.99 35.3702C8.83157 35.08 7.48549 34.5221 6.48187 33.5185C5.47825 32.5148 4.92035 31.1688 4.63016 29.0104C4.33611 26.8232 4.33398 23.9563 4.33398 19.9997Z" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
<path d="M5 16.667H35" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M5 26.667H35" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M11.666 16.667L11.666 35.0003" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M20 16.667L20 35.0003" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M28.334 16.667L28.334 35.0003" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
4
ks_dashboard_ninja/static/images/Map.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M20.0007 36.6663C12.1439 36.6663 8.21554 36.6663 5.77476 34.2256C3.33398 31.7848 3.33398 27.8564 3.33398 19.9997C3.33398 12.1429 3.33398 8.21456 5.77476 5.77379C8.21554 3.33301 12.1439 3.33301 20.0007 3.33301C27.8574 3.33301 31.7858 3.33301 34.2265 5.77378C36.6673 8.21456 36.6673 12.1429 36.6673 19.9997C36.6673 27.8564 36.6673 31.7848 34.2265 34.2256C31.7858 36.6663 27.8574 36.6663 20.0007 36.6663Z" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
<path d="M5.83398 34.1663L20.0007 19.9997M34.1673 5.83301L20.0007 19.9997M34.1673 34.1663L20.0007 19.9997" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 717 B |
4
ks_dashboard_ninja/static/images/Pie.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M33.334 25.921C31.3778 32.1492 25.5592 36.667 18.6854 36.667C10.207 36.667 3.33398 29.7939 3.33398 21.3156C3.33398 14.4418 7.85174 8.62316 14.08 6.66699" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M36.5225 16.5785C34.7532 10.2403 29.76 5.2471 23.4219 3.47784C20.6825 2.71318 18.334 5.08999 18.334 7.93404V19.0915C18.334 20.5136 19.4868 21.6663 20.9088 21.6663H32.0663C34.9103 21.6663 37.2871 19.3178 36.5225 16.5785Z" stroke="#1C1C1C" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 591 B |
3
ks_dashboard_ninja/static/images/Polar.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M33.0757 21.0763C32.8834 17.0117 30.9667 13.2617 27.9417 11.0324L29.7405 7.50666L29.2262 7.16991C26.9709 5.69294 24.3989 4.91236 21.7864 4.91236C19.3739 4.91236 16.9989 5.58652 14.8721 6.85202L13.0762 3.33301L12.5608 3.6711C6.8691 7.39688 3.33398 14.3245 3.33398 21.7498V22.4233H14.0739C14.2554 25.0519 15.4899 27.4684 17.4179 28.9649L15.6209 32.4866L16.1352 32.8234C17.856 33.9501 19.8108 34.5462 21.7864 34.5462C23.5637 34.5462 25.3233 34.0599 26.9126 33.1413L28.7114 36.6663L29.2268 36.3282C33.8167 33.3251 36.6673 27.7385 36.6673 21.7498V21.0763H33.0757ZM31.8876 21.0763H22.8173L27.3477 12.1969C30.0078 14.1844 31.6983 17.4906 31.8876 21.0763ZM15.4637 8.01178C17.4096 6.8628 19.5828 6.25935 21.7864 6.25935C23.9899 6.25935 26.1637 6.86347 28.109 8.01178L21.7864 20.4028L17.8739 12.735L15.4637 8.01178ZM12.6471 5.18445L20.7554 21.0763H14.0483H4.53517C4.73458 14.61 7.78994 8.62399 12.6471 5.18445ZM15.2661 22.4233H20.7554L18.7203 26.4117L18.0137 27.7964C16.4507 26.545 15.4423 24.5724 15.2661 22.4233ZM26.3185 31.9775C23.503 33.5797 20.0703 33.579 17.2542 31.9781L18.4346 29.6647L19.2251 28.1163L21.787 23.0967L25.4453 30.2654L26.3185 31.9775ZM29.1399 34.8129L22.8179 22.4233H33.0959H35.4643C35.2679 27.4516 32.8965 32.0987 29.1399 34.8129Z" fill="#1C1C1C" stroke="#1C1C1C" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |