|
|
@ -1,6 +1,9 @@
|
|||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
import datetime
|
||||
from collections import defaultdict
|
||||
from functools import reduce
|
||||
|
||||
|
||||
|
||||
class HrPayslipRun(models.Model):
|
||||
_inherit = 'hr.payslip.run'
|
||||
|
|
@ -287,6 +290,8 @@ class HrPayslipRun(models.Model):
|
|||
class HrPayslip(models.Model):
|
||||
_inherit = 'hr.payslip'
|
||||
|
||||
|
||||
|
||||
def get_payslip_lines_data(self, payslip_id):
|
||||
payslip = self.browse(payslip_id)
|
||||
return [{
|
||||
|
|
@ -297,3 +302,11 @@ class HrPayslip(models.Model):
|
|||
'quantity': line.quantity,
|
||||
'rate': line.rate
|
||||
} for line in payslip.line_ids]
|
||||
|
||||
def action_open_payslips(self):
|
||||
self.ensure_one()
|
||||
action = self.env["ir.actions.actions"]._for_xml_id("hr_payroll.action_view_hr_payslip_month_form")
|
||||
action['views'] = [[False, "form"]]
|
||||
action['res_id'] = self.id
|
||||
action['target'] = 'new'
|
||||
return action
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Component, onMounted, useRef, useState, onWillStart } from "@odoo/owl";
|
|||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { loadJS, loadCSS } from "@web/core/assets";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
|
||||
export class ConsolidatedPayslipGrid extends Component {
|
||||
static props = {
|
||||
|
|
@ -15,6 +16,7 @@ export class ConsolidatedPayslipGrid extends Component {
|
|||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.gridRef = useRef("gridContainer");
|
||||
this.action = useService("action");
|
||||
this.state = useState({
|
||||
rows: [],
|
||||
payslipRunId: this.props.record.resId || this.props.record.evalContext.id || false
|
||||
|
|
@ -36,16 +38,15 @@ export class ConsolidatedPayslipGrid extends Component {
|
|||
|
||||
async loadDependencies() {
|
||||
try {
|
||||
await Promise.all([
|
||||
loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"),
|
||||
loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"),
|
||||
loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css"),
|
||||
loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js"),
|
||||
loadJS("https://cdnjs.cloudflare.com/ajax/libs/jszip/2.6.1/jszip.min.js"),
|
||||
loadJS("https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"),
|
||||
loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css"),
|
||||
loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/themes/Office/pqgrid.min.css")
|
||||
]);
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js");
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css");
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js");
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jszip/2.6.1/jszip.min.js");
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/themes/Office/pqgrid.min.css");
|
||||
|
||||
|
||||
// Set global jQuery references
|
||||
window.$ = window.jQuery = window.$ || window.jQuery;
|
||||
|
|
@ -145,24 +146,18 @@ export class ConsolidatedPayslipGrid extends Component {
|
|||
editable: true,
|
||||
stripeRows:false,
|
||||
editModel: { saveKey: $.ui.keyCode.ENTER },
|
||||
filterModel: {
|
||||
on: true,
|
||||
mode: "AND",
|
||||
header: true,
|
||||
autoSearch: true,
|
||||
type: 'local',
|
||||
minLength: 1
|
||||
},
|
||||
dataModel: {
|
||||
data: this.state.rows,
|
||||
location: "local",
|
||||
sorting: "local",
|
||||
paging: "local"
|
||||
filterModel: {on: true, mode: "AND", header: true, autoSearch: true, type: 'local', minLength: 1},
|
||||
dataModel: {data: this.state.rows, location: "local", sorting: "local", paging: "local"},
|
||||
cellSave: function (evt, ui) {
|
||||
const payload = {
|
||||
id: ui.rowData.id,
|
||||
field: ui.dataIndx,
|
||||
value: ui.newVal
|
||||
};
|
||||
updateData(payload);
|
||||
},
|
||||
menuIcon: true,
|
||||
menuUI:{
|
||||
tabs: ['hideCols']
|
||||
},
|
||||
menuUI:{tabs: ['hideCols']},
|
||||
colModel: columns,
|
||||
postRenderInterval: -1,
|
||||
toolbar: {
|
||||
|
|
@ -212,6 +207,21 @@ export class ConsolidatedPayslipGrid extends Component {
|
|||
]
|
||||
},
|
||||
};
|
||||
function updateData(data){
|
||||
$.ajax({
|
||||
url: "/slip/update",
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(data),
|
||||
success: function (response) {
|
||||
console.log("Update successful:", response);
|
||||
},
|
||||
error: function (xhr) {
|
||||
console.error("Update failed:", xhr.responseText);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// Apply CSS and initialize grid
|
||||
$(this.gridRef.el)
|
||||
|
|
@ -428,7 +438,47 @@ export class ConsolidatedPayslipGrid extends Component {
|
|||
return `<span class="badge badge-${state === 'done' ? 'success' : 'warning'}">${state}</span>`;
|
||||
}
|
||||
},
|
||||
...subCols
|
||||
...subCols,
|
||||
{
|
||||
title: "View",
|
||||
width: 120,
|
||||
editable: false,
|
||||
summary:false,
|
||||
render: function (ui) {
|
||||
return "<button class='row-btn-view' type='button' >View</button>"
|
||||
},
|
||||
postRender: function (ui) {
|
||||
var grid = this,
|
||||
$cell = grid.getCell(ui);
|
||||
$cell.find(".row-btn-view")
|
||||
.button({ icons: { primary: 'ui-icon-extlink'} })
|
||||
.on("click", async function (evt) {
|
||||
const res = await odoo.__WOWL_DEBUG__.root.orm.call('hr.payslip','action_open_payslips',[ui.rowData.id])
|
||||
// res.views = [[false, "form"]],
|
||||
await odoo.__WOWL_DEBUG__.root.actionService.doAction(res)
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
title: "Edit",
|
||||
width: 120,
|
||||
editable: false,
|
||||
render: function (ui) {
|
||||
return "<button class='row-btn-edit' type='button'>Edit</button>"
|
||||
},
|
||||
postRender: function (ui) {
|
||||
var grid = this,
|
||||
$cell = grid.getCell(ui);
|
||||
$cell.find(".row-btn-edit")
|
||||
.button({ icons: { primary: 'ui-icon-pencil'} })
|
||||
.on("click", async function (evt) {
|
||||
const res = await odoo.__WOWL_DEBUG__.root.orm.call('hr.payslip','action_edit_payslip_lines',[ui.rowData.id])
|
||||
res.views = [[false, "form"]],
|
||||
await odoo.__WOWL_DEBUG__.root.actionService.doAction(res)
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
from . import models, controllers
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
'name': 'FTP Feed',
|
||||
'summary': 'Feed Module',
|
||||
'category': 'Reporting',
|
||||
'version': '1.0.0',
|
||||
'author': 'Pranay',
|
||||
'website': 'https://ftprotech.in',
|
||||
'license': 'LGPL-3',
|
||||
'sequence': -100,
|
||||
'depends': [
|
||||
'base', 'web', 'hr'
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/security.xml',
|
||||
'views/feed.xml',
|
||||
],
|
||||
'images': ['static/description/banner.png'],
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import controller
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
from odoo import http
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class FeedController(http.Controller):
|
||||
@http.route('/feed/attachment/<int:attachment_id>', auth='user')
|
||||
def get_feed_attachment(self, attachment_id, **kwargs):
|
||||
attachment = request.env['ir.attachment'].sudo().search([
|
||||
('id', '=', attachment_id),
|
||||
'|',
|
||||
('res_model', '=', 'ftp.feed'),
|
||||
('res_model', '=', 'ftp.feed.comments')
|
||||
])
|
||||
|
||||
if not attachment:
|
||||
return request.not_found()
|
||||
|
||||
return http.send_file(
|
||||
attachment._full_path(attachment.store_fname),
|
||||
filename=attachment.name,
|
||||
as_attachment=True
|
||||
)
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import feed
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
from odoo import fields, api, _, models
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class FtpFeed(models.Model):
|
||||
_name = 'ftp.feed'
|
||||
_description = 'Social Feed Posts'
|
||||
_order = 'create_date desc'
|
||||
|
||||
description = fields.Text(string='Post Content')
|
||||
images = fields.Many2many('ir.attachment', string='Post Images')
|
||||
user_id = fields.Many2one('res.users', default=lambda self: self.env.user, string='Author')
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee', compute='_compute_employee', store=True)
|
||||
feed_data = fields.One2many('ftp.feed.data', 'feed_id', string='Reactions')
|
||||
feed_comments = fields.One2many('ftp.feed.comments', 'feed_id', string='Comments')
|
||||
like_count = fields.Integer(compute='_compute_like_count', string='Likes')
|
||||
comment_count = fields.Integer(compute='_compute_comment_count', string='Comments')
|
||||
post_time = fields.Char(compute='_compute_post_time', string='Posted')
|
||||
|
||||
@api.depends('user_id')
|
||||
def _compute_employee(self):
|
||||
for record in self:
|
||||
employee = self.env['hr.employee'].search([('user_id', '=', record.user_id.id)], limit=1)
|
||||
record.employee_id = employee.id if employee else False
|
||||
|
||||
@api.depends('feed_data.feed_type')
|
||||
def _compute_like_count(self):
|
||||
for record in self:
|
||||
record.like_count = len(record.feed_data.filtered(lambda x: x.feed_type == 'like'))
|
||||
|
||||
@api.depends('feed_comments')
|
||||
def _compute_comment_count(self):
|
||||
for record in self:
|
||||
record.comment_count = len(record.feed_comments)
|
||||
|
||||
@api.depends('create_date')
|
||||
def _compute_post_time(self):
|
||||
for record in self:
|
||||
if record.create_date:
|
||||
delta = datetime.now() - record.create_date
|
||||
if delta.days > 0:
|
||||
record.post_time = f"{delta.days}d ago"
|
||||
elif delta.seconds > 3600:
|
||||
record.post_time = f"{delta.seconds // 3600}h ago"
|
||||
elif delta.seconds > 60:
|
||||
record.post_time = f"{delta.seconds // 60}m ago"
|
||||
else:
|
||||
record.post_time = "Just now"
|
||||
else:
|
||||
record.post_time = ""
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
vals['user_id'] = self.env.uid
|
||||
if not vals.get('images') and not vals.get('description'):
|
||||
raise ValidationError(_("Can't create an empty post"))
|
||||
# Handle images to ensure they are public
|
||||
if vals.get('images'):
|
||||
# images is a list of commands like [(6, 0, [id1, id2])]
|
||||
image_ids = []
|
||||
for command in vals['images']:
|
||||
if command[0] == 6: # REPLACE command
|
||||
image_ids = command[2]
|
||||
elif command[0] in (4, 1): # LINK or CREATE command
|
||||
image_ids.append(command[1] if command[0] == 4 else command[0])
|
||||
|
||||
# Update all attachments to be public
|
||||
if image_ids:
|
||||
self.env['ir.attachment'].browse(image_ids).write({'public': True})
|
||||
|
||||
return super().create(vals)
|
||||
|
||||
def write(self, vals):
|
||||
for record in self:
|
||||
if self.env.user != record.user_id:
|
||||
if 'description' in vals or 'images' in vals:
|
||||
raise UserError(_("Only the author can modify post content"))
|
||||
if vals.get('images'):
|
||||
# Get all new image IDs being added
|
||||
new_image_ids = []
|
||||
for command in vals['images']:
|
||||
if command[0] == 6: # REPLACE command
|
||||
new_image_ids = command[2]
|
||||
elif command[0] in (4, 1): # LINK or CREATE command
|
||||
new_image_ids.append(command[1] if command[0] == 4 else command[0])
|
||||
|
||||
# Update all new attachments to be public
|
||||
if new_image_ids:
|
||||
self.env['ir.attachment'].browse(new_image_ids).write({'public': True})
|
||||
return super().write(vals)
|
||||
|
||||
def unlink(self):
|
||||
for record in self:
|
||||
if self.env.user != record.user_id:
|
||||
raise UserError(_("Only the author can delete this post"))
|
||||
return super().unlink()
|
||||
|
||||
|
||||
class FtpFeedData(models.Model):
|
||||
_name = 'ftp.feed.data'
|
||||
_description = 'Feed Reactions'
|
||||
|
||||
feed_type = fields.Selection([
|
||||
('like', 'Like'),
|
||||
('dislike', 'Dislike')
|
||||
], default='like', required=True)
|
||||
user_id = fields.Many2one('res.users', default=lambda self: self.env.user, required=True)
|
||||
feed_id = fields.Many2one('ftp.feed', required=True, ondelete='cascade')
|
||||
|
||||
_sql_constraints = [
|
||||
('unique_user_feed', 'unique(user_id, feed_id)', 'You can only react once per post!'),
|
||||
]
|
||||
|
||||
|
||||
class FtpFeedComments(models.Model):
|
||||
_name = 'ftp.feed.comments'
|
||||
_description = 'Feed Comments'
|
||||
_order = 'create_date desc'
|
||||
|
||||
feed_comment = fields.Text(string='Comment', required=True)
|
||||
user_id = fields.Many2one('res.users', default=lambda self: self.env.user, string='Author')
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee', compute='_compute_employee', store=True)
|
||||
feed_id = fields.Many2one('ftp.feed', required=True, ondelete='cascade')
|
||||
comment_time = fields.Char(compute='_compute_comment_time', string='Commented')
|
||||
|
||||
@api.depends('user_id')
|
||||
def _compute_employee(self):
|
||||
for record in self:
|
||||
employee = self.env['hr.employee'].search([('user_id', '=', record.user_id.id)], limit=1)
|
||||
record.employee_id = employee.id if employee else False
|
||||
|
||||
@api.depends('create_date')
|
||||
def _compute_comment_time(self):
|
||||
for record in self:
|
||||
if record.create_date:
|
||||
delta = datetime.now() - record.create_date
|
||||
if delta.days > 0:
|
||||
record.comment_time = f"{delta.days}d ago"
|
||||
elif delta.seconds > 3600:
|
||||
record.comment_time = f"{delta.seconds // 3600}h ago"
|
||||
elif delta.seconds > 60:
|
||||
record.comment_time = f"{delta.seconds // 60}m ago"
|
||||
else:
|
||||
record.comment_time = "Just now"
|
||||
else:
|
||||
record.comment_time = ""
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_ftp_feed,access_ftp_feed,model_ftp_feed,,1,1,1,1
|
||||
access_ftp_feed_data,access_ftp_feed_data,model_ftp_feed_data,,1,1,1,1
|
||||
access_ftp_feed_comments,access_ftp_feed_comments,model_ftp_feed_comments,,1,1,1,1
|
||||
access_ftp_feed_attachment,ftp.feed.attachment.access,base.model_ir_attachment,base.group_user,1,0,0,0
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<!-- Allow everyone to read all -->
|
||||
<record id="ftp_feed_read_rule" model="ir.rule">
|
||||
<field name="name">Feed - Read</field>
|
||||
<field name="model_id" ref="model_ftp_feed"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="perm_read" eval="1"/>
|
||||
<field name="perm_write" eval="1"/>
|
||||
<field name="perm_create" eval="1"/>
|
||||
<field name="perm_unlink" eval="1"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
|
@ -0,0 +1,156 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="view_ftp_feed_form" model="ir.ui.view">
|
||||
<field name="name">ftp.feed.form</field>
|
||||
<field name="model">ftp.feed</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Feed Post">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1>
|
||||
<field name="user_id" class="oe_inline" readonly="1"/>
|
||||
</h1>
|
||||
<h2>
|
||||
<field name="post_time" readonly="1"/>
|
||||
</h2>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="description" placeholder="What's on your mind?"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="images" widget="many2many_binary" options="{'preview_images': true}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Reactions">
|
||||
<field name="like_count" widget="stat_info" string="Total Likes"/>
|
||||
<field name="feed_data">
|
||||
<list editable="bottom">
|
||||
<field name="user_id"/>
|
||||
<field name="feed_type"/>
|
||||
<field name="create_date" readonly="1"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Comments">
|
||||
<field name="comment_count" widget="stat_info" string="Total Comments"/>
|
||||
<field name="feed_comments">
|
||||
<list editable="bottom">
|
||||
<field name="user_id"/>
|
||||
<field name="feed_comment"/>
|
||||
<field name="comment_time" readonly="1"/>
|
||||
</list>
|
||||
<form>
|
||||
<group>
|
||||
<field name="user_id" readonly="1"/>
|
||||
<field name="feed_comment"/>
|
||||
<field name="comment_time" readonly="1"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Author Info">
|
||||
<field name="employee_id">
|
||||
<form>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="create_date" readonly="1"/>
|
||||
<field name="write_date" readonly="1"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_ftp_feed_list" model="ir.ui.view">
|
||||
<field name="name">ftp.feed.list</field>
|
||||
<field name="model">ftp.feed</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Feed Posts" decoration-info="like_count > 0" decoration-danger="like_count == 0">
|
||||
<field name="user_id"/>
|
||||
<field name="description" widget="text_emojis"/>
|
||||
<field name="post_time"/>
|
||||
<field name="like_count" widget="badge" invisible="1"/>
|
||||
<field name="comment_count" widget="badge" invisible="1"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_ftp_feed_kanban" model="ir.ui.view">
|
||||
<field name="name">ftp.feed.kanban</field>
|
||||
<field name="model">ftp.feed</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="user_id">
|
||||
<field name="description"/>
|
||||
<field name="images"/>
|
||||
<field name="user_id"/>
|
||||
<field name="post_time"/>
|
||||
<field name="like_count"/>
|
||||
<field name="comment_count"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_global_click o_kanban_record">
|
||||
<div class="o_kanban_record_header">
|
||||
<div class="o_kanban_record_title">
|
||||
<field name="user_id" widget="hr_employee"/>
|
||||
<small class="float-right">
|
||||
<field name="post_time"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_kanban_record_body">
|
||||
<div t-if="record.description.raw_value"
|
||||
widget="text_emojis" class="mb-2"/>
|
||||
|
||||
<div t-if="record.images.raw_value" class="d-flex flex-wrap">
|
||||
<t t-foreach="record.images.raw_value.slice(0, 3)" t-as="img">
|
||||
<img t-att-src="'/web/image/ir.attachment/' + img + '/datas/300x300'"
|
||||
class="img-fluid m-1" style="max-height: 100px;"/>
|
||||
</t>
|
||||
<t t-if="record.images.raw_value.length > 3">
|
||||
<div class="o_kanban_image_more ml-1">
|
||||
+<t t-esc="record.images.raw_value.length - 3"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<div>
|
||||
<i class="fa fa-thumbs-up mr-1"/>
|
||||
<field name="like_count" widget="badge"/>
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa fa-comments mr-1"/>
|
||||
<field name="comment_count" widget="badge"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Actions -->
|
||||
<record id="action_ftp_feed" model="ir.actions.act_window">
|
||||
<field name="name">Social Feed</field>
|
||||
<field name="res_model">ftp.feed</field>
|
||||
<field name="view_mode">kanban,list,form</field>
|
||||
<field name="context">{'default_user_id': uid}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Share updates with your team!
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Menu -->
|
||||
<menuitem id="menu_ftp_feed_root" name="Social Feed" sequence="10" web_icon="ftp_feed,static/description/banner.png"/>
|
||||
<menuitem id="menu_ftp_feed" name="Feed" parent="menu_ftp_feed_root" sequence="20" action="action_ftp_feed"/>
|
||||
</odoo>
|
||||
|
|
@ -66,6 +66,7 @@
|
|||
'web.assets_backend': [
|
||||
'hr_payroll/static/src/components/add_payslips/**',
|
||||
'hr_payroll/static/src/views/add_payslips_hook.js',
|
||||
'hr_payroll/static/src/js/payslip_line_one2many.js'
|
||||
# 'hr_payroll/static/src/**/*',
|
||||
# ('remove', 'hr_payroll/static/src/js/hr_payroll_report_graph_view.js'),
|
||||
# ('remove', 'hr_payroll/static/src/js/hr_payroll_report_pivot_*'),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
from datetime import timedelta, datetime, date
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.http import request
|
||||
from odoo import http
|
||||
import babel.dates
|
||||
|
||||
|
||||
|
||||
class HrPayslip(models.Model):
|
||||
_inherit = 'hr.payslip'
|
||||
|
||||
@api.model
|
||||
def get_wage_register_data(self, date):
|
||||
if not date:
|
||||
now = fields.Datetime.now()
|
||||
date = babel.dates.format_datetime(now, "MMMM yyyy", locale='en')
|
||||
sql = """
|
||||
SELECT
|
||||
e.name AS employee,
|
||||
job.name AS designation,
|
||||
e.doj AS date_of_joining,
|
||||
e.birthday AS date_of_birth,
|
||||
to_char(p.date_from, 'Month YYYY') AS month_of_wages,
|
||||
e.l10n_in_uan AS uan_no,
|
||||
e.l10n_in_esic_number AS esic_no,
|
||||
bank.acc_number AS bank_account_no,
|
||||
|
||||
SUM(CASE WHEN pl.code = 'BASIC' THEN pl.total ELSE 0 END) AS basic,
|
||||
SUM(CASE WHEN pl.code = 'HRA' THEN pl.total ELSE 0 END) AS hra,
|
||||
SUM(CASE WHEN pl.code = 'SPA' THEN pl.total ELSE 0 END) AS other_allowance,
|
||||
SUM(CASE WHEN pl.code = 'GROSS' THEN pl.total ELSE 0 END) AS gross_wages,
|
||||
|
||||
SUM(CASE WHEN pl.code = 'ESICS' THEN pl.total ELSE 0 END) AS esi,
|
||||
SUM(CASE WHEN pl.code = 'PF' THEN pl.total ELSE 0 END) AS pf,
|
||||
SUM(CASE WHEN pl.code = 'PT' THEN pl.total ELSE 0 END) AS pt,
|
||||
SUM(CASE WHEN pl.code = 'DED' THEN pl.total ELSE 0 END) AS total_deductions,
|
||||
|
||||
SUM(CASE WHEN pl.code = 'LTA' THEN pl.total ELSE 0 END) AS lta,
|
||||
p.net_wage AS net_amount_payable
|
||||
|
||||
FROM hr_payslip p
|
||||
JOIN hr_employee e ON p.employee_id = e.id
|
||||
LEFT JOIN hr_job job ON e.job_id = job.id
|
||||
LEFT JOIN hr_payslip_line pl ON pl.slip_id = p.id
|
||||
LEFT JOIN hr_salary_rule_category cat_earn ON cat_earn.code = 'GROSS'
|
||||
LEFT JOIN hr_salary_rule_category cat_deduct ON cat_deduct.code = 'DED'
|
||||
LEFT JOIN res_partner_bank bank ON bank.id = e.bank_account_id
|
||||
|
||||
GROUP BY
|
||||
e.name, job.name, e.doj, e.birthday,
|
||||
p.date_from, e.l10n_in_uan, e.l10n_in_esic_number, e.bank_account_id, p.net_wage, bank.acc_number
|
||||
ORDER BY e.name;
|
||||
"""
|
||||
self.env.cr.execute(sql)
|
||||
result = self.env.cr.dictfetchall()
|
||||
data = []
|
||||
for i in result:
|
||||
i['designation'] = i['designation']['en_US']
|
||||
data.append(i)
|
||||
return data
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/** @odoo-module **/
|
||||
import { standardWidgetProps } from "@web/views/widgets/standard_widget_props";
|
||||
import { Component, onMounted, useRef, useState, onWillStart } from "@odoo/owl";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { loadJS, loadCSS } from "@web/core/assets";
|
||||
|
||||
export class SaleTest extends Component {
|
||||
static props = {
|
||||
...standardWidgetProps,
|
||||
};
|
||||
static template = "SaleTest";
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.gridRef = useRef("wageGrid");
|
||||
this.state = useState({ rows: [] });
|
||||
|
||||
onWillStart(async () => {
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js");
|
||||
window.$ = window.jQuery = window.$ || window.jQuery;
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css");
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/themes/steelblue/pqgrid.min.css");
|
||||
await this.loadData();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (this.gridRef.el) {
|
||||
this.renderGrid();
|
||||
setTimeout(() => this.initializeDatePicker(), 200);
|
||||
} else {
|
||||
console.error("Grid element not found");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
renderGrid() {
|
||||
const data = this.state.rows.length ? this.state.rows : [
|
||||
{
|
||||
employee: "John Doe", designation: "Software Engineer", date_of_joining: "2020-01-10",
|
||||
date_of_birth: "1990-04-15", month_of_wages: "January 2024", days_worked: 22,
|
||||
uan_no: "100100100", esic_no: "ESIC12345", bank_account_no: "1234567890",
|
||||
basic: 35000, hra: 15000, lta: 5000, other_allowance: 5000,
|
||||
gross_wages: 60000, esi: 500, pf: 1800, pt: 200, total_deductions: 2500, net_amount_payable: 57500
|
||||
}
|
||||
];
|
||||
|
||||
$(this.gridRef.el).pqGrid({
|
||||
width: "100%",
|
||||
height: 600,
|
||||
editable: false,
|
||||
showSummary: true,
|
||||
filterModel: {
|
||||
on: true,
|
||||
mode: "AND",
|
||||
header: true
|
||||
},
|
||||
toolbar: {
|
||||
items: [
|
||||
{
|
||||
type: "button",
|
||||
label: "GET",
|
||||
icon: "fa fa-check",
|
||||
listener: () => this.onFilterClick()
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
label: "Export to Excel",
|
||||
icon: "ui-icon-document",
|
||||
listener: () => this.exportExcel()
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
label: "Export to PDF",
|
||||
icon: "ui-icon-print",
|
||||
listener: () => this.exportPDF()
|
||||
}
|
||||
]
|
||||
},
|
||||
colModel: [
|
||||
{ title: "Name of the Employee", dataIndx: "employee", width: 220, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} },
|
||||
{ title: "Designation / Category", dataIndx: "designation", width: 150, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} },
|
||||
{ title: "Date of Joining", dataIndx: "date_of_joining", width: 90 },
|
||||
{ title: "Date of Birth", dataIndx: "date_of_birth", width: 90 },
|
||||
{ title: "Month of Wages", dataIndx: "month_of_wages", width: 150 },
|
||||
{ title: "No. of Days Worked", dataIndx: "days_worked", width: 90 },
|
||||
{ title: "UAN No.", dataIndx: "uan_no", width: 150 },
|
||||
{ title: "ESIC No.", dataIndx: "esic_no", width: 150 },
|
||||
{ title: "Bank Account No.", dataIndx: "bank_account_no", width: 150, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} },
|
||||
{ title: "Basic", dataIndx: "basic", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "HRA", dataIndx: "hra", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "LTA", dataIndx: "lta", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Other Allowance", dataIndx: "other_allowance", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Gross Wages", dataIndx: "gross_wages", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "ESI", dataIndx: "esi", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "PF", dataIndx: "pf", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "PT", dataIndx: "pt", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Total Deductions", dataIndx: "total_deductions", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Net Amount Payable", dataIndx: "net_amount_payable", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }
|
||||
],
|
||||
dataModel: {
|
||||
data: data,
|
||||
location: "local"
|
||||
},
|
||||
groupModel: {
|
||||
on: true,
|
||||
dataIndx: ["month_of_wages"],
|
||||
showSummary: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initializeDatePicker() {
|
||||
$("#fromDate").datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
showButtonPanel: true,
|
||||
dateFormat: 'MM yy',
|
||||
onClose: function (dateText, inst) {
|
||||
const month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
|
||||
const year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
|
||||
$(this).datepicker('setDate', new Date(year, month, 1));
|
||||
},
|
||||
beforeShow: function (input, inst) {
|
||||
$(input).datepicker("widget").addClass("monthOnly");
|
||||
}
|
||||
});
|
||||
|
||||
$("<style>")
|
||||
.prop("type", "text/css")
|
||||
.html(".monthOnly .ui-datepicker-calendar { display: none; }")
|
||||
.appendTo("head");
|
||||
}
|
||||
|
||||
async loadData(fromDate = null) {
|
||||
try {
|
||||
const records = await this.orm.call("hr.payslip", "get_wage_register_data", [fromDate]);
|
||||
this.state.rows = records;
|
||||
this.renderGrid();
|
||||
} catch (error) {
|
||||
console.error("Error loading wage data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async onFilterClick() {
|
||||
const fromDate = $("#fromDate").val();
|
||||
await this.loadData(fromDate);
|
||||
}
|
||||
|
||||
exportExcel() {
|
||||
const grid = $(this.gridRef.el).pqGrid("instance");
|
||||
const data = grid.option("dataModel").data;
|
||||
const columns = grid.option("colModel").map(col => ({
|
||||
title: col.title,
|
||||
dataIndx: col.dataIndx
|
||||
}));
|
||||
|
||||
fetch("/hr_payroll/export_excel", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ data, columns }),
|
||||
headers: { "Content-Type": "application/json" }
|
||||
})
|
||||
.then(response => response.blob())
|
||||
.then(blob => {
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = "payroll_export.xlsx";
|
||||
link.click();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Export failed", err);
|
||||
alert("Failed to export Excel.");
|
||||
});
|
||||
}
|
||||
|
||||
exportPDF() {
|
||||
const grid = $(this.gridRef.el).pqGrid("instance");
|
||||
const data = grid.option("dataModel").data;
|
||||
const columns = grid.option("colModel").map(col => ({
|
||||
title: col.title,
|
||||
dataIndx: col.dataIndx
|
||||
}));
|
||||
|
||||
fetch("/hr_payroll/export_pdf", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ data, columns }),
|
||||
headers: { "Content-Type": "application/json" }
|
||||
})
|
||||
.then(response => response.blob())
|
||||
.then(blob => {
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = "payroll_export.pdf";
|
||||
link.click();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Export failed", err);
|
||||
alert("Export to PDF failed.");
|
||||
});
|
||||
}
|
||||
clicked() {
|
||||
alert("Button clicked!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const saleTest = {
|
||||
component: SaleTest,
|
||||
};
|
||||
registry.category("view_widgets").add("SaleTest", saleTest);
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { Component, onMounted, useRef, useState, onWillStart } from "@odoo/owl";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { loadJS, loadCSS } from "@web/core/assets";
|
||||
|
||||
export class WageRegisterGrid extends Component {
|
||||
static template = "WageRegisterGridTemplate";
|
||||
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.gridRef = useRef("wageGrid");
|
||||
this.state = useState({ rows: [] });
|
||||
|
||||
onWillStart(async () => {
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js");
|
||||
window.$ = window.jQuery = window.$ || window.jQuery;
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/themes/base/jquery-ui.min.css");
|
||||
await loadJS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.js");
|
||||
await loadCSS("https://cdnjs.cloudflare.com/ajax/libs/pqGrid/3.5.1/pqgrid.min.css");
|
||||
await this.loadData();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (this.gridRef.el) {
|
||||
this.renderGrid();
|
||||
setTimeout(() => this.initializeDatePicker(), 200);
|
||||
} else {
|
||||
console.error("Grid element not found");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
renderGrid() {
|
||||
const data = this.state.rows.length ? this.state.rows : [
|
||||
{
|
||||
employee: "John Doe", designation: "Software Engineer", date_of_joining: "2020-01-10",
|
||||
date_of_birth: "1990-04-15", month_of_wages: "January 2024", days_worked: 22,
|
||||
uan_no: "100100100", esic_no: "ESIC12345", bank_account_no: "1234567890",
|
||||
basic: 35000, hra: 15000, lta: 5000, other_allowance: 5000,
|
||||
gross_wages: 60000, esi: 500, pf: 1800, pt: 200, total_deductions: 2500, net_amount_payable: 57500
|
||||
}
|
||||
];
|
||||
|
||||
$(this.gridRef.el).pqGrid({
|
||||
width: "100%",
|
||||
height: 600,
|
||||
editable: false,
|
||||
showSummary: true,
|
||||
filterModel: {
|
||||
on: true,
|
||||
mode: "AND",
|
||||
header: true
|
||||
},
|
||||
toolbar: {
|
||||
items: [
|
||||
{
|
||||
type: "textbox",
|
||||
label: "From Date: ",
|
||||
attr: "id=fromDate"
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
label: "GET",
|
||||
icon: "fa fa-check",
|
||||
listener: () => this.onFilterClick()
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
label: "Export to Excel",
|
||||
icon: "ui-icon-document",
|
||||
listener: () => this.exportExcel()
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
label: "Export to PDF",
|
||||
icon: "ui-icon-print",
|
||||
listener: () => this.exportPDF()
|
||||
}
|
||||
]
|
||||
},
|
||||
colModel: [
|
||||
{ title: "Name of the Employee", dataIndx: "employee", width: 220, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} },
|
||||
{ title: "Designation / Category", dataIndx: "designation", width: 150, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} },
|
||||
{ title: "Date of Joining", dataIndx: "date_of_joining", width: 90 },
|
||||
{ title: "Date of Birth", dataIndx: "date_of_birth", width: 90 },
|
||||
{ title: "Month of Wages", dataIndx: "month_of_wages", width: 150 },
|
||||
{ title: "No. of Days Worked", dataIndx: "days_worked", width: 90 },
|
||||
{ title: "UAN No.", dataIndx: "uan_no", width: 150 },
|
||||
{ title: "ESIC No.", dataIndx: "esic_no", width: 150 },
|
||||
{ title: "Bank Account No.", dataIndx: "bank_account_no", width: 150, filter: {type: 'textbox', condition: 'begin', listeners: ['keyup']} },
|
||||
{ title: "Basic", dataIndx: "basic", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "HRA", dataIndx: "hra", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "LTA", dataIndx: "lta", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Other Allowance", dataIndx: "other_allowance", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Gross Wages", dataIndx: "gross_wages", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "ESI", dataIndx: "esi", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "PF", dataIndx: "pf", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "PT", dataIndx: "pt", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Total Deductions", dataIndx: "total_deductions", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" },
|
||||
{ title: "Net Amount Payable", dataIndx: "net_amount_payable", width: 90, dataType: "float", summary: {type: "sum"}, format: "##,##0.00" }
|
||||
],
|
||||
dataModel: {
|
||||
data: data,
|
||||
location: "local"
|
||||
},
|
||||
groupModel: {
|
||||
on: true,
|
||||
dataIndx: ["month_of_wages"],
|
||||
showSummary: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initializeDatePicker() {
|
||||
$("#fromDate").datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
showButtonPanel: true,
|
||||
dateFormat: 'MM yy',
|
||||
onClose: function (dateText, inst) {
|
||||
const month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
|
||||
const year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
|
||||
$(this).datepicker('setDate', new Date(year, month, 1));
|
||||
},
|
||||
beforeShow: function (input, inst) {
|
||||
$(input).datepicker("widget").addClass("monthOnly");
|
||||
}
|
||||
});
|
||||
|
||||
$("<style>")
|
||||
.prop("type", "text/css")
|
||||
.html(".monthOnly .ui-datepicker-calendar { display: none; }")
|
||||
.appendTo("head");
|
||||
}
|
||||
|
||||
async loadData(fromDate = null) {
|
||||
try {
|
||||
const records = await this.orm.call("hr.payslip", "get_wage_register_data", [fromDate]);
|
||||
this.state.rows = records;
|
||||
this.renderGrid();
|
||||
} catch (error) {
|
||||
console.error("Error loading wage data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async onFilterClick() {
|
||||
const fromDate = $("#fromDate").val();
|
||||
await this.loadData(fromDate);
|
||||
}
|
||||
|
||||
exportExcel() {
|
||||
const grid = $(this.gridRef.el).pqGrid("instance");
|
||||
const data = grid.option("dataModel").data;
|
||||
const columns = grid.option("colModel").map(col => ({
|
||||
title: col.title,
|
||||
dataIndx: col.dataIndx
|
||||
}));
|
||||
|
||||
fetch("/hr_payroll/export_excel", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ data, columns }),
|
||||
headers: { "Content-Type": "application/json" }
|
||||
})
|
||||
.then(response => response.blob())
|
||||
.then(blob => {
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = "payroll_export.xlsx";
|
||||
link.click();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Export failed", err);
|
||||
alert("Failed to export Excel.");
|
||||
});
|
||||
}
|
||||
|
||||
exportPDF() {
|
||||
const grid = $(this.gridRef.el).pqGrid("instance");
|
||||
const data = grid.option("dataModel").data;
|
||||
const columns = grid.option("colModel").map(col => ({
|
||||
title: col.title,
|
||||
dataIndx: col.dataIndx
|
||||
}));
|
||||
|
||||
fetch("/hr_payroll/export_pdf", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ data, columns }),
|
||||
headers: { "Content-Type": "application/json" }
|
||||
})
|
||||
.then(response => response.blob())
|
||||
.then(blob => {
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = "payroll_export.pdf";
|
||||
link.click();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Export failed", err);
|
||||
alert("Export to PDF failed.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("actions").add("WageRegisterGrid", WageRegisterGrid);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="SaleTest" owl="1">
|
||||
<button class="btn btn-primary" t-on-click="clicked">Fetch View</button>
|
||||
<div t-ref="wageGrid"
|
||||
style="width: 100%; ">
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="WageRegisterGridTemplate">
|
||||
<div class="o_form_view o_form_edit_mode" style="padding: 20px; background-color: #f9f9f9; border-radius: 10px;">
|
||||
<div style="margin-bottom: 20px; border-bottom: 2px solid #dcdcdc; padding-bottom: 10px;">
|
||||
<h2 style="margin: 0; font-size: 24px; font-weight: 600; color: #34495e;">
|
||||
📊 Register of Wages
|
||||
</h2>
|
||||
<p style="margin: 5px 0 0; color: #7f8c8d; font-size: 14px;">
|
||||
Detailed wage data of employees by pay period
|
||||
</p>
|
||||
<div t-ref="wageGrid"
|
||||
style="width: 100%; ">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -73,24 +73,24 @@
|
|||
<tr>
|
||||
<td style="border: 1px solid #ccc; padding: 6px;">
|
||||
<t t-set="income" t-value="0"/>
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.code in ['BASIC','HRA','LTA','SPA'])" t-as="l">
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.category_id.code in ['BASIC','SPA','ALW']and l.amount > 0)" t-as="l">
|
||||
<t t-esc="l.name"/><br/>
|
||||
</div>
|
||||
</td>
|
||||
<td style="border: 1px solid #ccc; padding: 6px; text-align: right;">
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.code in ['BASIC','HRA','LTA','SPA'])" t-as="l">
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.category_id.code in ['BASIC','SPA','ALW'] and l.amount > 0)" t-as="l">
|
||||
<t t-esc="l.amount"/><br/>
|
||||
<t t-set="income" t-value="income + l.amount"/>
|
||||
</div>
|
||||
</td>
|
||||
<td style="border: 1px solid #ccc; padding: 6px;">
|
||||
<t t-set="contribution" t-value="0"/>
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.code in ['PFE','ESICF'])" t-as="l">
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.category_id.code in ['COMP','MA'] and l.amount > 0)" t-as="l">
|
||||
<t t-esc="l.name"/><br/>
|
||||
</div>
|
||||
</td>
|
||||
<td style="border: 1px solid #ccc; padding: 6px; text-align: right;">
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.code in ['PFE','ESICF'])" t-as="l">
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.category_id.code in ['COMP','MA'] and l.amount > 0)" t-as="l">
|
||||
<t t-esc="l.amount"/><br/>
|
||||
<t t-set="contribution" t-value="contribution + l.amount"/>
|
||||
</div>
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
</div>
|
||||
</td>
|
||||
<td style="border: 1px solid #ccc; padding: 6px; text-align: right;">
|
||||
<strong><t t-esc="contribution + income"/></strong><br/><br/>
|
||||
<strong><t t-esc="contribution + income"/></strong><br/><br/><br/>
|
||||
<div t-foreach="o.line_ids.filtered(lambda l: l.appears_on_payslip and l.category_id.code == 'DED')" t-as="l">
|
||||
<t t-esc="l.amount"/><br/>
|
||||
<t t-set="ded" t-value="ded + l.amount"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<odoo>
|
||||
<record id="action_wage_register_grid" model="ir.actions.client">
|
||||
<field name="name">Wage Register Grid</field>
|
||||
<field name="tag">WageRegisterGrid</field>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem id="menu_report_payroll" name="Wage Grid" action="action_wage_register_grid" parent="menu_hr_payroll_report"/>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
# -*- 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 v16.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': 'PRANAY',
|
||||
|
||||
'website': 'https://ftprotech.in/',
|
||||
|
||||
'maintainer': 'FTPROTECH',
|
||||
|
||||
'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',
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import ks_date_filter_selections
|
||||
|
|
@ -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)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
from . import ks_chart_export
|
||||
from . import ks_list_export
|
||||
from . import ks_dashboard_export
|
||||
from . import ks_domain_fix
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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()
|
||||
|
|
@ -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://ftprotech.in/</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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">Template1</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">Template2</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">Template3</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>
|
||||
|
|
@ -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:")
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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, char=35)
|
||||
ks_menu_name = fields.Char(string="Menu Name", required=True, char=35)
|
||||
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"))
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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!'),
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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',
|
||||
}
|
||||
|
|
@ -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})
|
||||
|
|
@ -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)
|
||||
|
|
@ -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"))
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
xlrd==2.0.1
|
||||
openpyxl == 3.1.2
|
||||
gTTS == 2.5.1
|
||||
pandas==2.1.2
|
||||
SQLAlchemy==2.0.32
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
After Width: | Height: | Size: 103 KiB |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
After Width: | Height: | Size: 2.6 MiB |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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 |
|
After Width: | Height: | Size: 6.4 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.0007 3.33301C29.2054 3.33301 36.6673 10.7949 36.6673 19.9997C36.6673 29.2044 29.2054 36.6663 20.0007 36.6663C10.7959 36.6663 3.33398 29.2044 3.33398 19.9997C3.33398 15.3374 5.24838 11.1222 8.33398 8.09729" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M8.33398 19.9997C8.33398 26.443 13.5573 31.6663 20.0007 31.6663C26.444 31.6663 31.6673 26.443 31.6673 19.9997C31.6673 13.5564 26.444 8.33301 20.0007 8.33301" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M20 26.6663C23.6819 26.6663 26.6667 23.6816 26.6667 19.9997C26.6667 16.3178 23.6819 13.333 20 13.333" stroke="#1C1C1C" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 777 B |
|
|
@ -0,0 +1,10 @@
|
|||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M33.5324 30.3975C32.0109 30.3975 30.7361 31.0556 30.4583 32.4997H7.50065V9.54343C8.94469 9.26439 9.60381 7.99321 9.60381 6.46803C9.60381 4.73894 8.19674 3.33301 6.4689 3.33301C4.74106 3.33301 3.33398 4.73894 3.33398 6.46803C3.33398 7.99202 4.42864 9.2632 5.87268 9.54343V33.5313C5.87268 33.8604 6.14098 34.1276 6.4689 34.1276H30.4583C30.7361 35.5716 32.0109 36.6663 33.5324 36.6663C35.2591 36.6663 36.6673 35.2592 36.6673 33.5313C36.6673 31.8034 35.2591 30.3975 33.5324 30.3975ZM4.52642 6.46922C4.52642 5.39838 5.3969 4.52668 6.4689 4.52668C7.5409 4.52668 8.41137 5.39719 8.41137 6.46922C8.41137 7.53888 7.5409 8.41177 6.4689 8.41177C5.3969 8.41177 4.52642 7.54007 4.52642 6.46922ZM33.5324 35.4774C32.4628 35.4774 31.5899 34.6057 31.5899 33.5349C31.5899 32.464 32.4592 31.5912 33.5324 31.5912C34.6056 31.5912 35.4749 32.4629 35.4749 33.5349C35.4749 34.6045 34.602 35.4774 33.5324 35.4774Z" fill="#1C1C1C"/>
|
||||
<path d="M4.52642 6.46922C4.52642 5.39838 5.3969 4.52668 6.4689 4.52668C7.5409 4.52668 8.41137 5.39719 8.41137 6.46922C8.41137 7.53888 7.5409 8.41177 6.4689 8.41177C5.3969 8.41177 4.52642 7.54007 4.52642 6.46922Z" fill="#1C1C1C"/>
|
||||
<path d="M33.5324 35.4774C32.4628 35.4774 31.5899 34.6057 31.5899 33.5349C31.5899 32.464 32.4592 31.5912 33.5324 31.5912C34.6056 31.5912 35.4749 32.4629 35.4749 33.5349C35.4749 34.6045 34.602 35.4774 33.5324 35.4774Z" fill="#1C1C1C"/>
|
||||
<path d="M14.4986 17.3233C15.6171 17.3233 16.5234 16.4146 16.5234 15.2985C16.5234 14.1799 15.6147 13.2725 14.4986 13.2725C13.3825 13.2725 12.4727 14.1811 12.4727 15.2985C12.4727 16.4146 13.3837 17.3233 14.4986 17.3233ZM14.4986 14.4626C14.9601 14.4626 15.3309 14.8358 15.3309 15.2961C15.3309 15.7564 14.9577 16.1284 14.4986 16.1284C14.0395 16.1284 13.6651 15.7552 13.6651 15.2961C13.6651 14.8358 14.0383 14.4626 14.4986 14.4626Z" fill="#1C1C1C"/>
|
||||
<path d="M23.624 16.5745C24.7413 16.5745 25.65 15.6646 25.65 14.5473C25.65 13.4299 24.739 12.5225 23.624 12.5225C22.5055 12.5225 21.5957 13.4311 21.5957 14.5473C21.5957 15.6646 22.5079 16.5745 23.624 16.5745ZM23.624 13.7149C24.0843 13.7149 24.4575 14.0882 24.4575 14.5473C24.4575 15.0088 24.0843 15.3808 23.624 15.3808C23.1626 15.3808 22.7881 15.0076 22.7881 14.5461C22.7881 14.087 23.1649 13.7149 23.624 13.7149Z" fill="#1C1C1C"/>
|
||||
<path d="M19.7427 23.6526C20.8589 23.6526 21.7675 22.7428 21.7675 21.6266C21.7675 20.5081 20.8565 19.6006 19.7427 19.6006C18.6242 19.6006 17.7168 20.5093 17.7168 21.6266C17.7168 22.7428 18.6242 23.6526 19.7427 23.6526ZM19.7427 20.7919C20.2018 20.7919 20.5751 21.1651 20.5751 21.6254C20.5751 22.0857 20.2018 22.459 19.7427 22.459C19.2801 22.459 18.9092 22.0857 18.9092 21.6254C18.9092 21.1651 19.2801 20.7919 19.7427 20.7919Z" fill="#1C1C1C"/>
|
||||
<path d="M30.8424 21.6106C31.9609 21.6106 32.8671 20.7008 32.8671 19.5846C32.8671 18.4661 31.9585 17.5586 30.8424 17.5586C29.7262 17.5586 28.8164 18.4673 28.8164 19.5846C28.8164 20.7008 29.725 21.6106 30.8424 21.6106ZM30.8424 18.7499C31.3038 18.7499 31.6747 19.1231 31.6747 19.5834C31.6747 20.0437 31.3014 20.417 30.8424 20.417C30.3833 20.417 30.0088 20.0437 30.0088 19.5834C30.0088 19.1231 30.3821 18.7499 30.8424 18.7499Z" fill="#1C1C1C"/>
|
||||
<path d="M32.6826 13.3763C33.7999 13.3763 34.7074 12.4676 34.7074 11.3502C34.7074 10.2329 33.7964 9.32422 32.6826 9.32422C31.5641 9.32422 30.6543 10.2341 30.6543 11.3502C30.6543 12.4688 31.5653 13.3763 32.6826 13.3763ZM32.6826 10.5155C33.1417 10.5155 33.515 10.8888 33.515 11.349C33.515 11.8093 33.1417 12.1826 32.6826 12.1826C32.22 12.1826 31.8467 11.8093 31.8467 11.349C31.8467 10.8888 32.22 10.5155 32.6826 10.5155Z" fill="#1C1C1C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -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="M19.905 2.08301H20.0963C23.9436 2.08299 26.9587 2.08297 29.3111 2.39925C31.719 2.72299 33.6191 3.39855 35.1104 4.8899C36.6018 6.38125 37.2773 8.28129 37.6011 10.6892C37.9174 13.0417 37.9173 16.0567 37.9173 19.9041V24.9997C37.9173 32.1334 32.1343 37.9163 25.0007 37.9163H19.905C16.0577 37.9164 13.0426 37.9164 10.6902 37.6001C8.28227 37.2764 6.38223 36.6008 4.89088 35.1094C3.39953 33.6181 2.72396 31.7181 2.40023 29.3102C2.08395 26.9577 2.08396 23.9426 2.08398 20.0953V19.904C2.08396 16.0567 2.08395 13.0417 2.40023 10.6892C2.72396 8.28129 3.39953 6.38125 4.89088 4.8899C6.38223 3.39855 8.28227 2.72299 10.6902 2.39925C13.0426 2.08297 16.0577 2.08299 19.905 2.08301ZM11.0233 4.87696C8.89261 5.16342 7.60807 5.70824 6.65865 6.65767C5.70922 7.6071 5.1644 8.89163 4.87794 11.0223C4.58664 13.1889 4.58399 16.036 4.58399 19.9997C4.58399 23.9634 4.58664 26.8104 4.87794 28.977C5.1644 31.1077 5.70922 32.3923 6.65865 33.3417C7.60807 34.2911 8.89261 34.8359 11.0233 35.1224C13.1899 35.4137 16.0369 35.4163 20.0007 35.4163H23.7513C23.7569 33.1392 23.8065 31.6434 24.2197 30.3716C25.1677 27.4541 27.455 25.1667 30.3726 24.2187C31.6444 23.8055 33.1402 23.7559 35.4173 23.7503V19.9997C35.4173 16.036 35.4147 13.1889 35.1234 11.0223C34.8369 8.89163 34.2921 7.6071 33.3427 6.65767C32.3932 5.70824 31.1087 5.16342 28.978 4.87696C26.8114 4.58566 23.9644 4.58301 20.0007 4.58301C16.0369 4.58301 13.1899 4.58566 11.0233 4.87696ZM35.3428 26.2518C33.081 26.2615 32.0108 26.3151 31.1451 26.5964C28.9887 27.297 27.298 28.9877 26.5973 31.1441C26.3161 32.0098 26.2625 33.08 26.2527 35.3419C31.0048 34.7726 34.7735 31.0039 35.3428 26.2518Z" fill="#1C1C1C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -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="M19.905 2.08301H20.0963C23.9436 2.08299 26.9587 2.08297 29.3111 2.39925C31.719 2.72299 33.6191 3.39855 35.1104 4.8899C36.6018 6.38125 37.2773 8.28129 37.6011 10.6892C37.9174 13.0417 37.9173 16.0567 37.9173 19.9041V20.0953C37.9173 23.9426 37.9174 26.9577 37.6011 29.3102C37.2773 31.7181 36.6018 33.6181 35.1104 35.1094C33.6191 36.6008 31.719 37.2764 29.3111 37.6001C26.9587 37.9164 23.9436 37.9164 20.0963 37.9163H19.905C16.0577 37.9164 13.0426 37.9164 10.6902 37.6001C8.28227 37.2764 6.38223 36.6008 4.89088 35.1094C3.39953 33.6181 2.72396 31.7181 2.40023 29.3102C2.08395 26.9577 2.08396 23.9426 2.08398 20.0953V19.904C2.08396 16.0567 2.08395 13.0417 2.40023 10.6892C2.72396 8.28129 3.39953 6.38125 4.89088 4.8899C6.38223 3.39855 8.28227 2.72299 10.6902 2.39925C13.0426 2.08297 16.0577 2.08299 19.905 2.08301ZM11.0233 4.87696C8.89261 5.16342 7.60807 5.70824 6.65865 6.65767C5.70922 7.6071 5.1644 8.89163 4.87794 11.0223C4.58664 13.1889 4.58399 16.036 4.58399 19.9997C4.58399 23.9634 4.58664 26.8104 4.87794 28.977C5.1644 31.1077 5.70922 32.3923 6.65865 33.3417C7.60807 34.2911 8.89261 34.8359 11.0233 35.1224C13.1899 35.4137 16.0369 35.4163 20.0007 35.4163C23.9644 35.4163 26.8114 35.4137 28.978 35.1224C31.1087 34.8359 32.3932 34.2911 33.3427 33.3417C34.2921 32.3923 34.8369 31.1077 35.1234 28.977C35.4147 26.8104 35.4173 23.9634 35.4173 19.9997C35.4173 16.036 35.4147 13.1889 35.1234 11.0223C34.8369 8.89163 34.2921 7.6071 33.3427 6.65767C32.3932 5.70824 31.1087 5.16342 28.978 4.87696C26.8114 4.58566 23.9644 4.58301 20.0007 4.58301C16.0369 4.58301 13.1899 4.58566 11.0233 4.87696ZM17.5294 10.7612C18.0293 11.2373 18.0486 12.0285 17.5725 12.5284L12.8106 17.5284C12.5747 17.7761 12.2475 17.9163 11.9054 17.9163C11.5633 17.9163 11.2362 17.7761 11.0002 17.5284L9.09548 15.5284C8.61937 15.0285 8.63867 14.2373 9.13858 13.7612C9.6385 13.2851 10.4297 13.3044 10.9058 13.8043L11.9054 14.8538L15.7621 10.8043C16.2383 10.3044 17.0295 10.2851 17.5294 10.7612ZM20.4173 14.9997C20.4173 14.3093 20.977 13.7497 21.6673 13.7497H30.0007C30.691 13.7497 31.2507 14.3093 31.2507 14.9997C31.2507 15.69 30.691 16.2497 30.0007 16.2497H21.6673C20.977 16.2497 20.4173 15.69 20.4173 14.9997ZM17.5294 22.4278C18.0293 22.9039 18.0486 23.6952 17.5725 24.1951L12.8106 29.1951C12.5747 29.4428 12.2475 29.583 11.9054 29.583C11.5633 29.583 11.2362 29.4428 11.0002 29.1951L9.09548 27.1951C8.61937 26.6952 8.63867 25.9039 9.13858 25.4278C9.6385 24.9517 10.4297 24.971 10.9058 25.4709L11.9054 26.5205L15.7621 22.4709C16.2383 21.971 17.0295 21.9517 17.5294 22.4278ZM20.4173 26.6663C20.4173 25.976 20.977 25.4163 21.6673 25.4163H30.0007C30.691 25.4163 31.2507 25.976 31.2507 26.6663C31.2507 27.3567 30.691 27.9163 30.0007 27.9163H21.6673C20.977 27.9163 20.4173 27.3567 20.4173 26.6663Z" fill="#1C1C1C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 17C8 12.7574 8 10.636 9.31802 9.31802C10.636 8 12.7574 8 17 8C21.2426 8 23.364 8 24.682 9.31802C26 10.636 26 12.7574 26 17C26 21.2426 26 23.364 24.682 24.682C23.364 26 21.2426 26 17 26C12.7574 26 10.636 26 9.31802 24.682C8 23.364 8 21.2426 8 17Z" stroke="#1C1C1C" stroke-width="1.5"/>
|
||||
<path d="M12.5 18.7997L14.1172 16.8591C14.758 16.0901 15.0785 15.7056 15.5 15.7056C15.9215 15.7056 16.242 16.0901 16.8828 16.8591L17.1172 17.1403C17.758 17.9094 18.0785 18.2939 18.5 18.2939C18.9215 18.2939 19.242 17.9094 19.8828 17.1403L21.5 15.1997" stroke="#1C1C1C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 712 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 17C8 12.7574 8 10.636 9.31802 9.31802C10.636 8 12.7574 8 17 8C21.2426 8 23.364 8 24.682 9.31802C26 10.636 26 12.7574 26 17C26 21.2426 26 23.364 24.682 24.682C23.364 26 21.2426 26 17 26C12.7574 26 10.636 26 9.31802 24.682C8 23.364 8 21.2426 8 17Z" stroke="#1C1C1C" stroke-width="1.5"/>
|
||||
<path d="M12.5001 22.3998V14.2998" stroke="#1C1C1C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M17 22.4001V11.6001" stroke="#1C1C1C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M21.5 22.3999V17.8999" stroke="#1C1C1C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 680 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="56" height="55" viewBox="0 0 56 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M21.7923 24.9105C21.5631 24.8875 21.2881 24.8875 21.036 24.9105C15.5819 24.7271 11.2506 20.2584 11.2506 14.7584C11.2506 9.14379 15.7881 4.58337 21.4256 4.58337C27.0402 4.58337 31.6006 9.14379 31.6006 14.7584C31.5777 20.2584 27.2464 24.7271 21.7923 24.9105Z" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M38.4056 9.16663C42.8514 9.16663 46.4264 12.7645 46.4264 17.1875C46.4264 21.5187 42.9889 25.0479 38.7035 25.2083C38.5202 25.1854 38.3139 25.1854 38.1077 25.2083" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.3336 33.3666C4.78774 37.0791 4.78774 43.1291 10.3336 46.8187C16.6357 51.0354 26.9711 51.0354 33.2732 46.8187C38.819 43.1062 38.819 37.0562 33.2732 33.3666C26.994 29.1729 16.6586 29.1729 10.3336 33.3666Z" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M42.8296 45.8334C44.4796 45.4896 46.0379 44.825 47.3213 43.8396C50.8963 41.1584 50.8963 36.7355 47.3213 34.0542C46.0608 33.0917 44.5254 32.45 42.8983 32.0834" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="56" height="55" viewBox="0 0 56 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.8255 50.4167H34.5755C46.0338 50.4167 50.6172 45.8334 50.6172 34.375V20.625C50.6172 9.16671 46.0338 4.58337 34.5755 4.58337H20.8255C9.36715 4.58337 4.78381 9.16671 4.78381 20.625V34.375C4.78381 45.8334 9.36715 50.4167 20.8255 50.4167Z" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M35.7208 42.3958C38.2416 42.3958 40.3041 40.3333 40.3041 37.8125V17.1875C40.3041 14.6666 38.2416 12.6041 35.7208 12.6041C33.2 12.6041 31.1375 14.6666 31.1375 17.1875V37.8125C31.1375 40.3333 33.177 42.3958 35.7208 42.3958Z" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M19.6796 42.3959C22.2005 42.3959 24.263 40.3334 24.263 37.8125V29.7917C24.263 27.2709 22.2005 25.2084 19.6796 25.2084C17.1588 25.2084 15.0963 27.2709 15.0963 29.7917V37.8125C15.0963 40.3334 17.1359 42.3959 19.6796 42.3959Z" stroke="#241C1D" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="55" height="55" viewBox="0 0 55 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.4587 22.9167H16.0421C20.6254 22.9167 22.9171 20.625 22.9171 16.0417V11.4584C22.9171 6.87504 20.6254 4.58337 16.0421 4.58337H11.4587C6.87541 4.58337 4.58374 6.87504 4.58374 11.4584V16.0417C4.58374 20.625 6.87541 22.9167 11.4587 22.9167Z" stroke="#241C1D" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M38.9587 22.9167H43.5421C48.1254 22.9167 50.4171 20.625 50.4171 16.0417V11.4584C50.4171 6.87504 48.1254 4.58337 43.5421 4.58337H38.9587C34.3754 4.58337 32.0837 6.87504 32.0837 11.4584V16.0417C32.0837 20.625 34.3754 22.9167 38.9587 22.9167Z" stroke="#241C1D" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M38.9587 50.4167H43.5421C48.1254 50.4167 50.4171 48.125 50.4171 43.5417V38.9584C50.4171 34.375 48.1254 32.0834 43.5421 32.0834H38.9587C34.3754 32.0834 32.0837 34.375 32.0837 38.9584V43.5417C32.0837 48.125 34.3754 50.4167 38.9587 50.4167Z" stroke="#241C1D" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.4587 50.4167H16.0421C20.6254 50.4167 22.9171 48.125 22.9171 43.5417V38.9584C22.9171 34.375 20.6254 32.0834 16.0421 32.0834H11.4587C6.87541 32.0834 4.58374 34.375 4.58374 38.9584V43.5417C4.58374 48.125 6.87541 50.4167 11.4587 50.4167Z" stroke="#241C1D" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,7 @@
|
|||
<svg width="56" height="55" viewBox="0 0 56 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.1334 4.58337V11.4584" stroke="#292D32" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M37.4667 4.58337V11.4584" stroke="#292D32" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M16.8417 29.7916H35.175" stroke="#292D32" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M16.8417 38.9584H28.3" stroke="#292D32" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M37.4667 8.02087C45.098 8.43337 48.9251 11.3438 48.9251 22.1146V36.2771C48.9251 45.7188 46.6334 50.4396 35.175 50.4396H21.425C9.96672 50.4396 7.67505 45.7188 7.67505 36.2771V22.1146C7.67505 11.3438 11.5021 8.45629 19.1334 8.02087H37.4667Z" stroke="#292D32" stroke-width="2.35714" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.45488 5.60777L14 4L12.6198 9.6061L10.898 7.9532L8.12069 10.8463C8.02641 10.9445 7.89615 11 7.76 11C7.62385 11 7.49359 10.9445 7.39931 10.8463L5.36 8.72199L2.36069 11.8463C2.16946 12.0455 1.85294 12.0519 1.65373 11.8607C1.45453 11.6695 1.44807 11.3529 1.63931 11.1537L4.99931 7.65373C5.09359 7.55552 5.22385 7.5 5.36 7.5C5.49615 7.5 5.62641 7.55552 5.72069 7.65373L7.76 9.77801L10.1766 7.26067L8.45488 5.60777Z" fill="#1C1C1C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 583 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="56" height="60" viewBox="0 0 56 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M33.8293 26.3588H22.371" stroke="#241C1D" stroke-width="2.54571" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M39.1466 4.94995H17.0549C12.1737 4.94995 8.20911 9.25645 8.20911 14.5035V49.3762C8.20911 53.8312 11.1654 55.7122 14.7862 53.559L25.9695 46.8517C27.1612 46.134 29.0862 46.134 30.2549 46.8517L41.4383 53.559C45.0591 55.737 48.0154 53.856 48.0154 49.3762V14.5035C47.9924 9.25645 44.0279 4.94995 39.1466 4.94995Z" stroke="#241C1D" stroke-width="2.54571" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 656 B |
|
|
@ -0,0 +1,9 @@
|
|||
<svg width="25" height="23" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_9094_3795" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="21">
|
||||
<rect y="0.5" width="20" height="20" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_9094_3795)">
|
||||
<path d="M8.54411 5.40375L8.77611 8.85371L8.89128 10.5877C8.89253 10.766 8.92045 10.9432 8.97436 11.1135C9.11345 11.444 9.44811 11.654 9.81219 11.6393L15.3599 11.2764C15.6001 11.2725 15.8321 11.3623 16.0048 11.5262C16.1487 11.6628 16.2416 11.8415 16.2709 12.0336L16.2808 12.1503C16.0512 15.3292 13.7164 17.9807 10.5441 18.6651C7.37174 19.3495 4.11866 17.9037 2.55104 15.1125C2.0991 14.3016 1.81682 13.4104 1.72076 12.491C1.68064 12.2188 1.66297 11.9439 1.66793 11.6689C1.66297 8.26074 4.09 5.31426 7.48739 4.60394C7.89629 4.54026 8.29714 4.75673 8.46111 5.12974C8.50353 5.21612 8.53153 5.30864 8.54411 5.40375Z" fill="#04A9CC"/>
|
||||
<path opacity="0.4" d="M18.3333 8.67687L18.3275 8.70403L18.3107 8.74352L18.313 8.85196C18.3043 8.99554 18.2488 9.13371 18.1533 9.24538C18.0537 9.36163 17.9177 9.44079 17.768 9.47154L17.6767 9.48404L11.276 9.89879C11.0631 9.91979 10.8511 9.85113 10.6928 9.70996C10.5608 9.59221 10.4765 9.43338 10.4527 9.26221L10.0231 2.87084C10.0156 2.84923 10.0156 2.82581 10.0231 2.80419C10.0289 2.62802 10.1065 2.46149 10.2384 2.34182C10.3702 2.22214 10.5456 2.15929 10.725 2.16731C14.5249 2.26398 17.7186 4.99645 18.3333 8.67687Z" fill="#04A9CC"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3C3.89543 3 3 3.89545 3 5V19C3 20.1046 3.89543 21 5 21H19C20.1046 21 21 20.1046 21 19V5C21 3.89545 20.1046 3 19 3H5ZM8 13C8 12.4477 7.55228 12 7 12C6.44772 12 6 12.4477 6 13V17C6 17.5523 6.44772 18 7 18C7.55228 18 8 17.5523 8 17V13ZM12 9C12.5523 9 13 9.44769 13 10V17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17V10C11 9.44769 11.4477 9 12 9ZM18 7C18 6.44769 17.5523 6 17 6C16.4477 6 16 6.44769 16 7V17C16 17.5523 16.4477 18 17 18C17.5523 18 18 17.5523 18 17V7Z" fill="#04A9CC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 646 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="56" height="55" viewBox="0 0 56 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.64807 17.8292V40.1271C5.64807 44.4813 8.74182 46.2688 12.5002 44.1146L17.8856 41.0438C19.0543 40.3792 21.0022 40.3104 22.2168 40.9292L34.2481 46.9563C35.4627 47.5521 37.4106 47.5063 38.5793 46.8417L48.5022 41.1584C49.7627 40.425 50.8168 38.6375 50.8168 37.1709V14.8729C50.8168 10.5188 47.7231 8.73128 43.9647 10.8854L38.5793 13.9563C37.4106 14.6209 35.4627 14.6896 34.2481 14.0709L22.2168 8.06669C21.0022 7.47086 19.0543 7.51669 17.8856 8.18128L7.96265 13.8646C6.67932 14.5979 5.64807 16.3854 5.64807 17.8292Z" stroke="#292D32" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M20.0153 9.16663V38.9583" stroke="#292D32" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M36.449 15.1708V45.8333" stroke="#292D32" stroke-width="2.35714" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 962 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 4C0 1.79086 1.79086 0 4 0H10V4C10 6.20914 11.7909 8 14 8H16V16C16 18.2091 14.2091 20 12 20H4C1.79086 20 0 18.2091 0 16V4ZM4 9C3.44772 9 3 9.44772 3 10C3 10.5523 3.44772 11 4 11H6C6.55228 11 7 10.5523 7 10C7 9.44772 6.55228 9 6 9H4ZM4 13C3.44772 13 3 13.4477 3 14C3 14.5523 3.44772 15 4 15H8C8.55228 15 9 14.5523 9 14C9 13.4477 8.55228 13 8 13H4ZM12.6818 2.19879L12.5509 4.16288C12.5106 4.76656 13.0115 5.26743 13.6152 5.22718L15.5792 5.09624C16.4365 5.03909 16.8274 3.99887 16.2198 3.39135L14.3867 1.5582C13.7792 0.950684 12.7389 1.34153 12.6818 2.19879Z" fill="#04A9CC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 728 B |
|
After Width: | Height: | Size: 5.4 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.99984 12.8334C10.2082 12.8334 12.8332 10.2084 12.8332 7.00008C12.8332 3.79175 10.2082 1.16675 6.99984 1.16675C3.7915 1.16675 1.1665 3.79175 1.1665 7.00008C1.1665 10.2084 3.7915 12.8334 6.99984 12.8334Z" stroke="#241C1D" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.6665 7H9.33317" stroke="#241C1D" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7 9.33341V4.66675" stroke="#241C1D" stroke-width="0.875" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 636 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.33301 8H10.6663" stroke="#4B5563" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 10.6667V5.33337" stroke="#4B5563" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.99967 14.6667H9.99967C13.333 14.6667 14.6663 13.3334 14.6663 10V6.00004C14.6663 2.66671 13.333 1.33337 9.99967 1.33337H5.99967C2.66634 1.33337 1.33301 2.66671 1.33301 6.00004V10C1.33301 13.3334 2.66634 14.6667 5.99967 14.6667Z" stroke="#4B5563" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 599 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 8.5H4C3.72667 8.5 3.5 8.27333 3.5 8C3.5 7.72667 3.72667 7.5 4 7.5H12C12.2733 7.5 12.5 7.72667 12.5 8C12.5 8.27333 12.2733 8.5 12 8.5Z" fill="white"/>
|
||||
<path d="M8 12.5C7.72667 12.5 7.5 12.2733 7.5 12V4C7.5 3.72667 7.72667 3.5 8 3.5C8.27333 3.5 8.5 3.72667 8.5 4V12C8.5 12.2733 8.27333 12.5 8 12.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 429 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.94 13.28L10.2867 8.9333C10.8 8.41997 10.8 7.57997 10.2867 7.06664L5.94 2.71997" stroke="#E7495E" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 303 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.70825 7.54163C9.19159 8.08329 10.8083 8.08329 12.2916 7.54163" stroke="#292D32" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.0168 1.66663H5.98351C4.20851 1.66663 2.76685 3.11663 2.76685 4.88329V16.625C2.76685 18.125 3.84185 18.7583 5.15851 18.0333L9.22518 15.775C9.65851 15.5333 10.3585 15.5333 10.7835 15.775L14.8502 18.0333C16.1668 18.7666 17.2418 18.1333 17.2418 16.625V4.88329C17.2335 3.11663 15.7918 1.66663 14.0168 1.66663Z" stroke="#292D32" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.0168 1.66663H5.98351C4.20851 1.66663 2.76685 3.11663 2.76685 4.88329V16.625C2.76685 18.125 3.84185 18.7583 5.15851 18.0333L9.22518 15.775C9.65851 15.5333 10.3585 15.5333 10.7835 15.775L14.8502 18.0333C16.1668 18.7666 17.2418 18.1333 17.2418 16.625V4.88329C17.2335 3.11663 15.7918 1.66663 14.0168 1.66663Z" stroke="#292D32" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 443 B |
|
|
@ -0,0 +1,7 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.3996 4.62671C13.3996 4.98671 13.2063 5.31337 12.8996 5.48004L11.7396 6.10671L10.7529 6.63337L8.70628 7.74004C8.48628 7.86004 8.24628 7.92004 7.99961 7.92004C7.75294 7.92004 7.51294 7.86004 7.29294 7.74004L3.09961 5.48004C2.79294 5.31337 2.59961 4.98671 2.59961 4.62671C2.59961 4.26671 2.79294 3.94004 3.09961 3.77337L4.41294 3.06671L5.45961 2.50004L7.29294 1.51337C7.73294 1.27337 8.26628 1.27337 8.70628 1.51337L12.8996 3.77337C13.2063 3.94004 13.3996 4.26671 13.3996 4.62671Z" fill="#6789C6"/>
|
||||
<path d="M6.59917 8.52664L2.69917 6.57997C2.39917 6.42664 2.0525 6.44664 1.76583 6.61997C1.47917 6.79331 1.3125 7.09997 1.3125 7.4333V11.12C1.3125 11.76 1.66583 12.3333 2.23917 12.62L6.13917 14.5666C6.2725 14.6333 6.41917 14.6666 6.56583 14.6666C6.73917 14.6666 6.9125 14.62 7.06583 14.52C7.3525 14.3466 7.51917 14.04 7.51917 13.7066V10.02C7.52583 9.38664 7.1725 8.8133 6.59917 8.52664Z" fill="#6789C6"/>
|
||||
<path d="M14.686 7.43338V11.12C14.686 11.7534 14.3327 12.3267 13.7593 12.6134L9.85932 14.5667C9.72599 14.6334 9.57932 14.6667 9.43266 14.6667C9.25932 14.6667 9.08599 14.62 8.92599 14.52C8.64599 14.3467 8.47266 14.04 8.47266 13.7067V10.0267C8.47266 9.38671 8.82599 8.81338 9.39932 8.52671L10.8327 7.81338L11.8327 7.31338L13.2993 6.58004C13.5993 6.42671 13.946 6.44004 14.2327 6.62004C14.5127 6.79338 14.686 7.10004 14.686 7.43338Z" fill="#6789C6"/>
|
||||
<path d="M11.7407 6.10667L10.7541 6.63333L4.41406 3.06667L5.46073 2.5L11.5807 5.95333C11.6474 5.99333 11.7007 6.04667 11.7407 6.10667Z" fill="#6789C6"/>
|
||||
<path d="M11.834 7.31335V8.82669C11.834 9.10002 11.6073 9.32669 11.334 9.32669C11.0607 9.32669 10.834 9.10002 10.834 8.82669V7.81335L11.834 7.31335Z" fill="#6789C6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |