@ -0,0 +1,52 @@ |
|||
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
|||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
ChatGPT Odoo Connector |
|||
====================== |
|||
This module simplifies content creation and editing by integrating ChatGPT. |
|||
It also facilitates the generation of images for newly created products and |
|||
when modifying product names. Additionally, it includes a Speech-to-Text feature |
|||
that allows users to convert spoken language into written text, making hands-free |
|||
interaction possible and further streamlining the content creation process. |
|||
|
|||
Configuration |
|||
============= |
|||
The user should install 'openai' for Python by running: |
|||
'sudo pip install openai' for authorization code flow. |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
License |
|||
------- |
|||
Affero General Public License, Version 3 (AGPL v3). |
|||
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
|||
|
|||
Credits |
|||
------- |
|||
Developer: (V16) Ashwin A, Contact: odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if |
|||
your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
|
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import controllers |
|||
from . import models |
@ -0,0 +1,63 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
{ |
|||
"name": "ChatGPT Odoo Connector", |
|||
"version": "16.0.1.0.0", |
|||
"category": "Productivity, Extra Tools ", |
|||
"summary": "User can create content, Generate product image and Convert spoken language into written text using AI.", |
|||
"description": """ This module simplifies content creation and editing by integrating ChatGPT. |
|||
It also facilitates the generation of images for newly created products and |
|||
when modifying product names. Additionally, it includes a Speech-to-Text feature |
|||
that allows users to convert spoken language into written text, making hands-free |
|||
interaction possible and further streamlining the content creation process.""", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': "https://www.cybrosys.com", |
|||
'depends': ['mail', 'product', 'web_editor'], |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'views/res_config_settings_views.xml', |
|||
'views/product_template.xml', |
|||
'views/product_product.xml', |
|||
], |
|||
'assets': { |
|||
'web_editor.assets_wysiwyg': [ |
|||
'chatgpt_odoo_connector/static/src/xml/web_editor_toolbar.xml', |
|||
'chatgpt_odoo_connector/static/src/xml/alternative_chatgpt.xml', |
|||
], |
|||
'web.assets_backend': [ |
|||
'chatgpt_odoo_connector/static/src/css/chatgpt_odoo.css', |
|||
'chatgpt_odoo_connector/static/src/js/wysiwyg.js', |
|||
'chatgpt_odoo_connector/static/src/js/open_chatgpt.js', |
|||
'chatgpt_odoo_connector/static/src/js/recordAudio.js', |
|||
'chatgpt_odoo_connector/static/src/js/custom_toolbar.js', |
|||
'chatgpt_odoo_connector/static/src/js/alternative_chatgpt.js', |
|||
], |
|||
}, |
|||
'external_dependencies': {'python': ['openai']}, |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import chatgpt_odoo_connector |
@ -0,0 +1,43 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import http |
|||
from pathlib import Path |
|||
from odoo.http import request |
|||
import os |
|||
from odoo.tools import json |
|||
|
|||
|
|||
class SpeechToText(http.Controller): |
|||
@http.route('/upload_audio', type='http', auth='public', methods=['POST'], csrf=False) |
|||
def upload_audio(self, **kwargs): |
|||
""" |
|||
Function for uploading audio file into a file and |
|||
returns the path of the file as json format |
|||
""" |
|||
upload_dir = Path(__file__).parent |
|||
file = kwargs.get('file') |
|||
if file: |
|||
file_path = os.path.join(upload_dir, file.filename) |
|||
with open(file_path, 'wb') as f: |
|||
f.write(file.read()) |
|||
return request.make_response(json.dumps({'filePath': file_path}), headers={'Content-Type': 'application/json'}) |
|||
return request.make_response(json.dumps({'error': 'No file uploaded'}), headers={'Content-Type': 'application/json'}) |
@ -0,0 +1,8 @@ |
|||
## Module <chatgpt_odoo_connector> |
|||
|
|||
#### 27.05.2024 |
|||
#### Version 16.0.1.0.0 |
|||
#### ADD |
|||
|
|||
- Initial commit for ChatGPT Odoo Connector |
|||
|
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from . import open_chatgpt |
|||
from . import product_product |
|||
from . import product_template |
|||
from . import res_config_settings |
@ -0,0 +1,91 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from os import remove |
|||
from openai import OpenAI |
|||
from odoo import api, models |
|||
|
|||
|
|||
class ChatGPTOdoo(models.Model): |
|||
_name = 'open.chatgpt' |
|||
_description = 'Open ChatGPT' |
|||
|
|||
@api.model |
|||
def get_response(self, message): |
|||
"""Function for getting response based on the message.""" |
|||
api_key = self.env['ir.config_parameter'].sudo().get_param('chatgpt_odoo_connector.api_key') |
|||
client = OpenAI(api_key=api_key) |
|||
try: |
|||
chat_completion = client.chat.completions.create( |
|||
messages=[ |
|||
{ |
|||
"role": "user", |
|||
"content": message, |
|||
} |
|||
], |
|||
model="gpt-3.5-turbo", |
|||
) |
|||
except Exception as e: |
|||
message = str(e).split("'message':")[1] |
|||
error_message = message.split(", 'type':")[0] |
|||
return error_message |
|||
return chat_completion.choices[0].message.content |
|||
|
|||
@api.model |
|||
def edit_content(self, message, message_type): |
|||
"""Function for editing(shortening, lengthening, and rephrasing) the description """ |
|||
api_key = self.env['ir.config_parameter'].sudo().get_param( |
|||
'chatgpt_odoo_connector.api_key') |
|||
client = OpenAI(api_key=api_key) |
|||
try: |
|||
chat_completion = client.chat.completions.create( |
|||
messages=[ |
|||
{ |
|||
"role": "user", |
|||
"content": f"{message_type}: {message}", |
|||
} |
|||
], |
|||
model="gpt-3.5-turbo", |
|||
) |
|||
except Exception as e: |
|||
message = str(e).split("'message':")[1] |
|||
error_message = message.split(", 'type':")[0] |
|||
return error_message |
|||
return chat_completion.choices[0].message.content |
|||
|
|||
@api.model |
|||
def convert_to_text(self, audio_path): |
|||
""" Function for converting the audio from the file into text using AI. |
|||
It returns the text. |
|||
""" |
|||
api_key = self.env['ir.config_parameter'].sudo().get_param( |
|||
'chatgpt_odoo_connector.api_key') |
|||
client = OpenAI(api_key=api_key) |
|||
try: |
|||
audio_file = open(audio_path, "rb") |
|||
transcription = client.audio.transcriptions.create( |
|||
model="whisper-1", |
|||
file=audio_file |
|||
) |
|||
remove(audio_path) |
|||
except Exception as e: |
|||
return f'Error: {str(e)}' |
|||
return transcription.text |
@ -0,0 +1,91 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
import base64 |
|||
import requests |
|||
from openai import OpenAI |
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class ProductProduct(models.Model): |
|||
_inherit = 'product.product' |
|||
|
|||
is_create_image = fields.Boolean(related='product_tmpl_id.is_create_image', |
|||
string='Generate Image', |
|||
readonly=False, |
|||
help='Check this box if you want to automatically generate an image for this product') |
|||
|
|||
is_update_image = fields.Boolean(related='product_tmpl_id.is_update_image', |
|||
string='Update Image', |
|||
readonly=False, |
|||
help='Check this box if you want to automatically update an image for this product while changing the name.') |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
""" Method for generating images for product """ |
|||
res = super(ProductProduct, self).create(vals) |
|||
if not res.image_1920 and res.is_create_image: |
|||
image_base64 = self.generate_image(res.name) |
|||
if image_base64: |
|||
res.write({ |
|||
'image_1920': image_base64, |
|||
}) |
|||
else: |
|||
res.message_post( |
|||
body="Failed to generate image for product: '%s' due to 'Incorrect API key provided or Other issues. You can find your API key at https://platform.openai.com/account/api-keys." % res.name, |
|||
message_type='notification') |
|||
return res |
|||
|
|||
def write(self, vals): |
|||
""" Method for updating image if name of the product updates""" |
|||
if 'name' in vals and 'image_1920' not in vals: |
|||
is_update_image = vals.get('is_update_image', self.is_update_image) |
|||
if is_update_image: |
|||
image_base64 = self.generate_image(vals['name']) |
|||
if image_base64: |
|||
vals['image_1920'] = image_base64 |
|||
else: |
|||
self.message_post( |
|||
body="Failed to update image for product: '%s' due to 'Incorrect API key provided or Other issues. You can find your API key at https://platform.openai.com/account/api-keys." % |
|||
vals['name'], |
|||
message_type='notification') |
|||
return super(ProductProduct, self).write(vals) |
|||
|
|||
def generate_image(self, name): |
|||
""" Function for generating images with the help of AI based on the name |
|||
of the product""" |
|||
api_key = self.env['ir.config_parameter'].sudo().get_param( |
|||
'chatgpt_odoo_connector.api_key') |
|||
client = OpenAI(api_key=api_key) |
|||
try: |
|||
response = client.images.generate( |
|||
model="dall-e-3", |
|||
prompt=name, |
|||
size="1024x1024", |
|||
quality="standard", |
|||
n=1, |
|||
) |
|||
image_url = response.data[0].url |
|||
response = requests.get(image_url) |
|||
image_base64 = base64.b64encode(response.content) |
|||
except: |
|||
return None |
|||
return image_base64 |
@ -0,0 +1,88 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
import base64 |
|||
import requests |
|||
from openai import OpenAI |
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class ProductTemplate(models.Model): |
|||
_inherit = 'product.template' |
|||
|
|||
is_create_image = fields.Boolean(string='Generate Image', |
|||
default=True, |
|||
help='Check this box if you want to automatically generate an image for this product') |
|||
|
|||
is_update_image = fields.Boolean(string='Update Image', |
|||
help='Check this box if you want to automatically update an image for this product while changing the name.') |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
""" Method for generating images for product """ |
|||
res = super(ProductTemplate, self).create(vals) |
|||
if not res.image_1920 and res.is_create_image: |
|||
image_base64 = self.generate_image(res.name) |
|||
if image_base64: |
|||
res.write({ |
|||
'image_1920': image_base64, |
|||
}) |
|||
else: |
|||
res.message_post( |
|||
body="Failed to generate image for product: '%s' due to 'Incorrect API key provided or Other issues. You can find your API key at https://platform.openai.com/account/api-keys." % res.name, |
|||
message_type='notification') |
|||
return res |
|||
|
|||
def write(self, vals): |
|||
""" Method for updating image if name of the product updates""" |
|||
if 'name' in vals and 'image_1920' not in vals: |
|||
is_update_image = vals.get('is_update_image', self.is_update_image) |
|||
if is_update_image: |
|||
image_base64 = self.generate_image(vals['name']) |
|||
if image_base64: |
|||
vals['image_1920'] = image_base64 |
|||
else: |
|||
self.message_post( |
|||
body="Failed to update image for product: '%s' due to 'Incorrect API key provided or Other issues. You can find your API key at https://platform.openai.com/account/api-keys." % |
|||
vals['name'], |
|||
message_type='notification') |
|||
return super(ProductTemplate, self).write(vals) |
|||
|
|||
def generate_image(self, name): |
|||
""" Function for generating images with the help of AI based on the name |
|||
of the product""" |
|||
api_key = self.env['ir.config_parameter'].sudo().get_param( |
|||
'chatgpt_odoo_connector.api_key') |
|||
client = OpenAI(api_key=api_key) |
|||
try: |
|||
response = client.images.generate( |
|||
model="dall-e-3", |
|||
prompt=name, |
|||
size="1024x1024", |
|||
quality="standard", |
|||
n=1, |
|||
) |
|||
image_url = response.data[0].url |
|||
response = requests.get(image_url) |
|||
image_base64 = base64.b64encode(response.content) |
|||
except: |
|||
return None |
|||
return image_base64 |
@ -0,0 +1,30 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class ResConfigSettings(models.TransientModel): |
|||
"""Add field to configuration settings""" |
|||
_inherit = "res.config.settings" |
|||
|
|||
api_key = fields.Char(string="API Key", help="Provide the API Key here", |
|||
config_parameter="chatgpt_odoo_connector.api_key") |
|
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 967 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 127 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 135 KiB |
After Width: | Height: | Size: 134 KiB |
After Width: | Height: | Size: 150 KiB |
After Width: | Height: | Size: 133 KiB |
After Width: | Height: | Size: 119 KiB |
After Width: | Height: | Size: 119 KiB |
After Width: | Height: | Size: 141 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 143 KiB |
After Width: | Height: | Size: 157 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 169 KiB |
After Width: | Height: | Size: 242 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,752 @@ |
|||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;"> |
|||
<!-- TITLE BAR --> |
|||
<div class="d-flex align-items-center justify-content-between" |
|||
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> |
|||
<img src="assets/misc/cybrosys-logo.png" width="42" height="42" |
|||
style="width: 42px; height: 42px;"/> |
|||
<div> |
|||
<div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Community |
|||
</div> |
|||
<div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" |
|||
class="mr-2"> |
|||
<i class="fa fa-check mr-1"></i>Enterprise |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF TITLE BAR --> |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12"> |
|||
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> |
|||
ChatGPT Odoo Connector |
|||
</h1> |
|||
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> |
|||
User can create content, Generate product image and Convert |
|||
spoken language into written text using AI |
|||
</p> |
|||
<!-- END OF APP HERO --> |
|||
<img src="assets/screenshots/hero.gif" class="img-responsive" |
|||
style="width: 100%; margin-left: auto; margin-right: auto;" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- NAVIGATION SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/compass.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Explore This |
|||
Module</h2> |
|||
</div> |
|||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#overview"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn more about this module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#features"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View features of this module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-sm-12 col-md-6 my-3"> |
|||
<a href="#screenshots"> |
|||
<div class="d-flex justify-content-between align-items-center" |
|||
style="background-color: #f5f5f5; padding: 30px; width: 100%;"> |
|||
<div> |
|||
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> |
|||
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View screenshots for this module</span> |
|||
</div> |
|||
<img src="assets/misc/right-arrow.png" width="36" height="36"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<!-- END OF NAVIGATION SECTION --> |
|||
|
|||
<!-- OVERVIEW SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="overview"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/pie-chart.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Overview |
|||
</h2> |
|||
</div> |
|||
<div class="row" |
|||
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> |
|||
<div class="col-sm-12 py-4"> |
|||
This module simplifies content creation and editing by integrating ChatGPT. |
|||
It also facilitates the generation of images for newly created products and |
|||
when modifying product names. Additionally, it includes a Speech-to-Text feature |
|||
that allows users to convert spoken language into written text, making hands-free |
|||
interaction possible and further streamlining the content creation process. |
|||
</div> |
|||
</div> |
|||
<!-- END OF OVERVIEW SECTION --> |
|||
|
|||
<!-- FEATURES SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="features"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/features.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Features |
|||
</h2> |
|||
</div> |
|||
<div class="row" |
|||
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> |
|||
<div class="col-sm-12 col-md-6"> |
|||
|
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available in Odoo 16.0 Community & Enterprise</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Easy to Set Up API Key of the ChatGPT</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Accessing questions and answers directly from the Odoo interface is as easy as interacting with ChatGPT</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Image generation for products using AI</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Speech to Text feature for hands-free interaction</span> |
|||
</div> |
|||
<div class="d-flex align-items-center" |
|||
style="margin-top: 30px; margin-bottom: 30px"> |
|||
<img src="assets/misc/check-box.png" class="mr-2"/> |
|||
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Speech to Text feature supports 57 languages</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF FEATURES SECTION --> |
|||
|
|||
<!-- SCREENSHOTS SECTION --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" |
|||
id="screenshots"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/pictures.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Screenshots |
|||
</h2> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12"> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Setting API Key |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Simply set chatGPT API Key inside Settings. You can find your API key at |
|||
<a href="https://platform.openai.com/account/api-keys">https://platform.openai.com/account/api-keys</a> |
|||
</p> |
|||
<img src="assets/screenshots/1.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
We can access ChatGPT from Text field section by typing '/'. |
|||
</p> |
|||
<img src="assets/screenshots/2.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
When we're selecting the ChatGPT option, we can have an interface for entering the question and click Send Icon. |
|||
</p> |
|||
<img src="assets/screenshots/3.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
We can see the generated response and also an 'INSERT' button. |
|||
</p> |
|||
<img src="assets/screenshots/4.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
While clicking the 'INSERT' button the generated response from AI will be added to the Notes field. |
|||
</p> |
|||
<img src="assets/screenshots/5.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
We can use the ChatGPT option for generating mail content also. |
|||
</p> |
|||
<img src="assets/screenshots/6.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Additional Feature |
|||
</h3> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Edit Content |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
We can perform various process on the content |
|||
such as shortening , lengthening or rephrasing the content. |
|||
Access these features by selecting the content. |
|||
</p> |
|||
<img src="assets/screenshots/7.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Upon clicking the icon, a popup window emerges, presenting users |
|||
with various buttons for content processing options: shortening, |
|||
lengthening, or rephrasing. This interface allows users to select |
|||
their preferred method for modifying the content according to |
|||
their specific needs or objectives. |
|||
</p> |
|||
<img src="assets/screenshots/8.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
By clicking any of the button it will generate response and shows |
|||
in the specified field, and we can replace the content by clicking |
|||
the 'REPLACE' button. |
|||
</p> |
|||
<img src="assets/screenshots/9.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
If any errors while generating response it will return the response as error as shown in the image below. |
|||
</p> |
|||
<img src="assets/screenshots/10.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Generate Image |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Generate product image using AI while creating a new product or Updating name of a product. |
|||
To use the feature while creating a product, enable "Generate Image," enter a name for the product, and save. |
|||
</p> |
|||
<img src="assets/screenshots/11.png" class="img-thumbnail"> |
|||
<img src="assets/screenshots/12.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
For updating the product image while changing the product name, enable "Update Image". |
|||
By turning on it will automatically generate an image and update it. |
|||
</p> |
|||
<img src="assets/screenshots/13.png" class="img-thumbnail"> |
|||
<img src="assets/screenshots/14.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
If any errors encounter while generating or updating image using AI it will create a message in Log note. |
|||
</p> |
|||
<img src="assets/screenshots/15.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> |
|||
Speech-to-text |
|||
</h3> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
Speech-to-Text using AI allows users to convert spoken language |
|||
into written text seamlessly. This feature leverages advanced artificial |
|||
intelligence to accurately transcribe voice inputs, enabling hands-free |
|||
interaction and improving efficiency in tasks such as note-taking, and content creation. |
|||
</p> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
We can access Speech-to-text from Text field section by typing '/'. |
|||
</p> |
|||
<img src="assets/screenshots/16.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
When we're selecting the Speech-to-text option, we can have an interface for recoding audio. |
|||
Start the recording by clicking the button. |
|||
</p> |
|||
<img src="assets/screenshots/17.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
After recording audio stop the recording by clicking the button. |
|||
</p> |
|||
<img src="assets/screenshots/18.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
By stopping the recording, the system will process the audio and |
|||
provide the transcribed text in the response. |
|||
</p> |
|||
<img src="assets/screenshots/19.png" class="img-thumbnail"> |
|||
</div> |
|||
<div style="display: block; margin: 30px auto;"> |
|||
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> |
|||
While clicking the 'INSERT' button the generated Text form audio using AI will be added to the Notes field. |
|||
</p> |
|||
<img src="assets/screenshots/20.png" class="img-thumbnail"> |
|||
<img src="assets/screenshots/21.png" class="img-thumbnail"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF SCREENSHOTS SECTION --> |
|||
|
|||
<!-- RELATED PRODUCTS --> |
|||
<div class="d-flex align-items-center" |
|||
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> |
|||
<div class="d-flex justify-content-center align-items-center mr-2" |
|||
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> |
|||
<img src="assets/misc/categories.png"/> |
|||
</div> |
|||
<h2 class="mt-2" |
|||
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
|||
Related |
|||
Products |
|||
</h2> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-sm-12"> |
|||
<div id="demo1" class="row carousel slide" data-ride="carousel"> |
|||
<!-- The slideshow --> |
|||
<div class="carousel-inner" style="padding: 30px;"> |
|||
<div class="carousel-item" style="min-height: 198.656px;"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/hide_menu_user/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/1.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/odoo_dynamic_dashboard/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/2.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/whatsapp_mail_messaging/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/3.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item active" |
|||
style="min-height: 198.656px;"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/login_user_detail/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/4.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/all_in_one_dynamic_custom_fields/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/5.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" |
|||
style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/16.0/rest_api_odoo/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-radius: 0px;" |
|||
src="assets/modules/6.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Left and right controls --> |
|||
<a class="carousel-control-prev" href="#demo1" data-slide="prev" |
|||
style="width:35px; color:#000"> <span |
|||
class="carousel-control-prev-icon"><i |
|||
class="fa fa-chevron-left" |
|||
style="font-size:24px"></i></span> |
|||
</a> <a class="carousel-control-next" href="#demo1" |
|||
data-slide="next" style="width:35px; color:#000"> |
|||
<span class="carousel-control-next-icon"><i |
|||
class="fa fa-chevron-right" |
|||
style="font-size:24px"></i></span> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF RELATED PRODUCTS --> |
|||
|
|||
<!-- OUR SERVICES --> |
|||
<section class="container" style="margin-top: 6rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Our Services</h2> |
|||
<hr style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/cogs.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Customization</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/wrench.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/lifebuoy.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Support</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/user.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Hire |
|||
Odoo |
|||
Developer</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/puzzle.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Integration</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/update.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Migration</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/consultation.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Consultancy</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/training.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/license.png" class="img-responsive" |
|||
height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" |
|||
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo Licensing Consultancy</h6> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<!-- END OF OUR SERVICES --> |
|||
|
|||
<!-- OUR INDUSTRIES --> |
|||
<section class="container" style="margin-top: 6rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Our Industries</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/trading-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Trading |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easily procure and sell your products</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/pos-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
POS |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easy |
|||
configuration |
|||
and convivial experience</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/education-black.png" |
|||
class="img-responsive mb-3" height="48px" |
|||
width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Education |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
A platform for |
|||
educational management</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/manufacturing-black.png" |
|||
class="img-responsive mb-3" height="48px" |
|||
width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Manufacturing |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Plan, track and |
|||
schedule your operations</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/ecom-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
E-commerce & Website |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Mobile |
|||
friendly, |
|||
awe-inspiring product pages</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/service-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Service Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Keep track of |
|||
services and invoice</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/restaurant-black.png" |
|||
class="img-responsive mb-3" height="48px" |
|||
width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Restaurant |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Run your bar or |
|||
restaurant methodically</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/hotel-black.png" |
|||
class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 |
|||
style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Hotel Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
An |
|||
all-inclusive |
|||
hotel management application</p> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</section> |
|||
|
|||
<!-- END OF OUR INDUSTRIES --> |
|||
|
|||
<!-- FOOTER --> |
|||
<!-- Footer Section --> |
|||
<section class="container" style="margin: 5rem auto 2rem;"> |
|||
<div class="row" style="max-width:1540px;"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Need Help?</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Contact Cards --> |
|||
<div class="row d-flex justify-content-center align-items-center" |
|||
style="max-width:1540px; margin: 0 auto 2rem auto;"> |
|||
|
|||
<div class="col-lg-12" |
|||
style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; "> |
|||
|
|||
<div class="row mt-4"> |
|||
<div class="col-lg-6"> |
|||
<a href="mailto:odoo@cybrosys.com" target="_blank" |
|||
class="btn btn-block mb-2 deep_hover" |
|||
style="text-decoration: none; background-color: #4d4d4d; color: #FFF; border-radius: 4px;"><i |
|||
class="fa fa-envelope mr-2"></i>odoo@cybrosys.com</a> |
|||
</div> |
|||
<div class="col-lg-6"> |
|||
<a href="https://api.whatsapp.com/send?phone=918606827707" |
|||
target="_blank" |
|||
class="btn btn-block mb-2 deep_hover" |
|||
style="text-decoration: none; background-color: #25D366; color: #FFF; border-radius: 4px;"><i |
|||
class="fa fa-whatsapp mr-2"></i>+91 86068 27707</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<!-- End of Contact Cards --> |
|||
</section> |
|||
<!-- Footer --> |
|||
<section class="oe_container" style="padding: 2rem 3rem 1rem;"> |
|||
<div class="row" |
|||
style="max-width:1540px; margin: 0 auto; margin-right: 3rem; "> |
|||
<!-- Logo --> |
|||
<div class="col-lg-12 d-flex justify-content-center align-items-center" |
|||
style="margin-top: 3rem;"> |
|||
<img src="https://www.cybrosys.com/images/logo.png" width="200px" |
|||
height="auto"/> |
|||
</div> |
|||
<!-- End of Logo --> |
|||
<div class="col-lg-12"> |
|||
<hr |
|||
style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;"> |
|||
<!-- End of Footer Section --> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<!-- END OF FOOTER --> |
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,94 @@ |
|||
.popChatGPT{ |
|||
background-color: #2d2d2d; |
|||
width: 600px; |
|||
height: 360px; |
|||
position: fixed; |
|||
left: 28%; |
|||
top: 28%; |
|||
padding: 50px; |
|||
z-index: 9999; |
|||
border-radius: 25px; |
|||
} |
|||
|
|||
.popChatGPTAlter{ |
|||
background-color: #2d2d2d; |
|||
width: 600px; |
|||
height: 360px; |
|||
position: fixed; |
|||
left: 28%; |
|||
top: 28%; |
|||
padding: 50px; |
|||
z-index: 9999; |
|||
border-radius: 25px; |
|||
} |
|||
|
|||
.heading{ |
|||
color: white; |
|||
margin-left: 10px; |
|||
} |
|||
|
|||
.custom{ |
|||
width:48%; |
|||
border-radius:10px; |
|||
} |
|||
|
|||
.custom-input{ |
|||
padding: 0.375rem 0.75rem; |
|||
font-size: 1.08333333rem; |
|||
font-weight: 400; |
|||
line-height: 1.5; |
|||
color: #ffffff; |
|||
background-color: #353535; |
|||
background-clip: padding-box; |
|||
border: 1px solid #353535; |
|||
height:40px; |
|||
border-radius: 12px 0px 0px 12px; |
|||
} |
|||
|
|||
.custom-text{ |
|||
padding: 0.375rem 0.75rem; |
|||
font-size: 1.08333333rem; |
|||
font-weight: 400; |
|||
line-height: 1.5; |
|||
color: #ffffff; |
|||
background-color: #353535; |
|||
background-clip: padding-box; |
|||
border: 1px solid #353535; |
|||
resize:none; |
|||
border-radius: 12px; |
|||
} |
|||
|
|||
.alterButton{ |
|||
border-radius:10px; |
|||
width: 120px; |
|||
} |
|||
|
|||
#response::-webkit-scrollbar { |
|||
width: 5px; |
|||
} |
|||
|
|||
/* Track */ |
|||
#response::-webkit-scrollbar-track { |
|||
box-shadow: inset 0 0 5px grey; |
|||
border-radius: 10px; |
|||
} |
|||
|
|||
#response::-webkit-scrollbar-thumb { |
|||
background: white; |
|||
border-radius: 10px; |
|||
} |
|||
|
|||
#response::-webkit-scrollbar-thumb:hover { |
|||
background: #818281; |
|||
} |
|||
|
|||
.audio-record{ |
|||
display: flex; |
|||
justify-content: center |
|||
} |
|||
|
|||
.button-mic{ |
|||
border-radius: 13px; |
|||
height: 65px; |
|||
width: 55px; |
|||
} |
@ -0,0 +1,56 @@ |
|||
odoo.define('chatgpt_odoo_connector.alternative_chatgpt', function (require) { |
|||
'use strict'; |
|||
var Widget = require('web.Widget'); |
|||
var rpc = require('web.rpc'); |
|||
/* Extending the widget */ |
|||
var AlternativeChatGPT = Widget.extend({ |
|||
template: 'alternativeChatGPT', |
|||
events: { |
|||
'click .alterButton': '_onClick', |
|||
'click .Replace': '_onClickReplace', |
|||
'click .Cancel': '_onClickCancel', |
|||
}, |
|||
init: function(parent, options) { |
|||
this._super(parent); |
|||
$(document).on('click', this._onOutSideClick.bind(this)); |
|||
}, |
|||
start: function() { |
|||
var self = this; |
|||
this._super.apply(this, arguments); |
|||
}, |
|||
/* Function for clicking the buttons for shortening, lengthening and rephrasing the content */ |
|||
_onClick: function(event){ |
|||
var dataValue = event.target.getAttribute('data-value'); |
|||
var message = this.__parentedParent.__parentedParent.el.innerText |
|||
this.response = rpc.query({ |
|||
model: 'open.chatgpt', |
|||
method: 'edit_content', |
|||
args: [message,dataValue], |
|||
}).then((response) => { |
|||
document.getElementById('response').value = response; |
|||
}) |
|||
}, |
|||
/* Function for inserting the created response into the description field */ |
|||
_onClickReplace: function(){ |
|||
var new_content = document.getElementById('response').value; |
|||
if (new_content.trim()){ |
|||
this.__parentedParent.__parentedParent.el.innerText = new_content |
|||
this._onClickCancel(); |
|||
} |
|||
}, |
|||
/* Function for closing the widget while clicking outside */ |
|||
_onOutSideClick: function(ev){ |
|||
var element = document.querySelector('.popChatGPTAlter'); |
|||
var element_button = document.getElementsByClassName('chatgpt'); |
|||
var isClickInsideElementButton = Array.from(element_button).some(button => button.contains(ev.target)); |
|||
if (element && !element.contains(ev.target) && !isClickInsideElementButton){ |
|||
this._onClickCancel(); |
|||
} |
|||
}, |
|||
/* Function for closing */ |
|||
_onClickCancel: function(){ |
|||
this.destroy() |
|||
} |
|||
}); |
|||
return AlternativeChatGPT; |
|||
}); |
@ -0,0 +1,21 @@ |
|||
odoo.define('chatgpt_odoo_connector.custom_toolbar', function (require) { |
|||
'use strict'; |
|||
var web_editor = require('web_editor.toolbar'); |
|||
var Dialog = require('web.Dialog'); |
|||
var AlternativeChatGPT = require('chatgpt_odoo_connector.alternative_chatgpt'); |
|||
/* Adding a new button to the toolbar */ |
|||
var toolbar = web_editor.include({ |
|||
start: function () { |
|||
var res = this._super.apply(this, arguments); |
|||
this.$el.on('click', '#open-chatgpt', this._onButtonClick.bind(this)); |
|||
return res; |
|||
}, |
|||
/* Function for showing the widget while clicking the button. */ |
|||
_onButtonClick: function () { |
|||
if (!this.alternativeChatGPT || this.alternativeChatGPT.isDestroyed()) { |
|||
this.alternativeChatGPT = new AlternativeChatGPT(this); |
|||
} |
|||
this.alternativeChatGPT.appendTo(this.el.offsetParent); |
|||
}, |
|||
}); |
|||
}); |
@ -0,0 +1,93 @@ |
|||
/** @odoo-module **/ |
|||
const { Component, useState, useExternalListener, xml } = owl; |
|||
import { registry } from "@web/core/registry"; |
|||
/* Extending the component and creating class OpenChatGPT */ |
|||
export class OpenChatGPT extends Component { |
|||
constructor() { |
|||
super(...arguments); |
|||
this.state = useState({ |
|||
message: '', |
|||
response: '' |
|||
}); |
|||
this.Send = this.Send.bind(this); |
|||
this.Cancel = this.Cancel.bind(this); |
|||
this.onWindowEnter = this.onWindowEnter.bind(this); |
|||
useExternalListener(window, "click", this.onWindowClick); |
|||
useExternalListener(window, "keydown", this.onWindowEnter); |
|||
} |
|||
/* Getting the response based on the message provided */ |
|||
async Send(ev){ |
|||
if (ev.state.message.trim()){ |
|||
this.state.response = await this.props.rpc.query({ |
|||
model: 'open.chatgpt', |
|||
method: 'get_response', |
|||
args: [ev.state.message], |
|||
}) |
|||
} |
|||
} |
|||
|
|||
/* Function for inserting the response to the description field */ |
|||
insert(){ |
|||
var content = this.state.response |
|||
const lines = content.split('\n').filter(line => line.trim().length); |
|||
const fragment = document.createDocumentFragment(); |
|||
for (const line of lines) { |
|||
const block = document.createElement(line.startsWith('Title: ') ? 'h2' : 'p'); |
|||
block.innerText = line; |
|||
fragment.appendChild(block); |
|||
} |
|||
this.props.self.el.appendChild(fragment); |
|||
this.Cancel() |
|||
} |
|||
|
|||
/* Function for cancelling */ |
|||
Cancel(){ |
|||
var element = document.querySelector('.popChatGPT'); |
|||
element.remove(); |
|||
} |
|||
|
|||
/* Function for closing the widget while clicking outside */ |
|||
onWindowClick(ev) { |
|||
var element = document.querySelector('.popChatGPT'); |
|||
if (element && !element.contains(ev.target)){ |
|||
element.remove(); |
|||
} |
|||
} |
|||
/* Function for calling the function Send */ |
|||
onWindowEnter(ev){ |
|||
var element = document.querySelector('.popChatGPT'); |
|||
if (element && ev.key == 'Enter'){ |
|||
this.Send(this) |
|||
} |
|||
} |
|||
} |
|||
|
|||
OpenChatGPT.template = xml` |
|||
<div class="popChatGPT"> |
|||
<div style="display: flex; align-items: end;margin-top:-20px;"> |
|||
<img src="chatgpt_odoo_connector/static/src/Icons/icon.png" height="35px"/> |
|||
<div class="h2 heading">ChatGPT</div> |
|||
</div> |
|||
<hr/> |
|||
<div class="mb-3"> |
|||
<label for="message" class="form-label" style="color:white;">Message</label> |
|||
<div style="display: flex;"> |
|||
<input type="text" class="custom-input" id="message" placeholder="Enter message" |
|||
t-model="state.message"/> |
|||
<button class="btn btn-success" style="border-radius:0px 12px 12px 0px;" t-on-click="() => Send(this)"> |
|||
<i class="fa fa-paper-plane"></i> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
<label for="response" class="form-label" style="color:white;" t-if="state.response">Response</label> |
|||
<div t-if="state.response"> |
|||
<div class="mb-3"> |
|||
<textarea id="response" class="custom-text" rows="4" t-model="state.response"></textarea> |
|||
</div> |
|||
</div> |
|||
<div style="display: flex;justify-content: space-around;"> |
|||
<button class="btn btn-primary custom" t-if="state.response" t-on-click="insert">Insert</button> |
|||
<button class="btn btn-secondary custom" t-on-click="Cancel">Cancel</button> |
|||
</div> |
|||
</div>`; |
|||
registry.category("actions").add("chatGPT", OpenChatGPT); |
@ -0,0 +1,128 @@ |
|||
/** @odoo-module **/ |
|||
const { Component, useState, useRef, useExternalListener, xml } = owl; |
|||
import { registry } from "@web/core/registry"; |
|||
import { browser } from '@web/core/browser/browser'; |
|||
import {_t} from 'web.core'; |
|||
/* Extending the component and creating class recordAudio */ |
|||
export class recordAudio extends Component { |
|||
constructor() { |
|||
super(...arguments); |
|||
this.state = useState({ |
|||
startedRecording: '', |
|||
transcriptedText: '', |
|||
audioChunks: [], |
|||
}); |
|||
this.recordAudio = this.recordAudio.bind(this); |
|||
this.stopRecord = this.stopRecord.bind(this); |
|||
this.onWindowClick = this.onWindowClick.bind(this); |
|||
useExternalListener(window, "click", this.onWindowClick); |
|||
} |
|||
/* Function for recording audio and save the recording in a file. */ |
|||
async recordAudio(ev){ |
|||
this.state.startedRecording = true |
|||
this.state.audioChunks = []; |
|||
try { |
|||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); |
|||
this.mediaRecorder = new MediaRecorder(stream); |
|||
this.mediaRecorder.ondataavailable = (e) => { |
|||
if (e.data.size > 0) { |
|||
this.state.audioChunks.push(e.data); |
|||
} |
|||
}; |
|||
|
|||
this.mediaRecorder.onstop = async () => { |
|||
if (this.state.audioChunks.length > 0) { |
|||
const audioBlob = new Blob(this.state.audioChunks, { type: 'audio/wav' }); |
|||
const file = new File([audioBlob], 'recorded_audio.wav', { type: 'audio/wav' }); |
|||
const formData = new FormData(); |
|||
formData.append('file', file); |
|||
const response = await fetch('/upload_audio', { |
|||
method: 'POST', |
|||
body: formData, |
|||
}); |
|||
const { filePath } = await response.json(); |
|||
this.state.transcriptedText = await this.props.rpc.query({ |
|||
model: 'open.chatgpt', |
|||
method: 'convert_to_text', |
|||
args: [filePath], |
|||
}) |
|||
} |
|||
}; |
|||
|
|||
this.audioStream = stream; |
|||
this.mediaRecorder.start(); |
|||
} catch (error) { |
|||
this.props.self.displayNotification({ |
|||
title: _t('Warning'), |
|||
message: "Recording Error: Error accessing Microphone" |
|||
}); |
|||
} |
|||
} |
|||
/* Function for stop audio recording */ |
|||
async stopRecord() { |
|||
this.state.startedRecording = false; |
|||
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') { |
|||
this.mediaRecorder.stop(); |
|||
if (this.audioStream) { |
|||
this.audioStream.getTracks().forEach(track => track.stop()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* Function for inserting the converted text from the audio file. */ |
|||
Insert(){ |
|||
var content = this.state.transcriptedText |
|||
const lines = content.split('\n').filter(line => line.trim().length); |
|||
const fragment = document.createDocumentFragment(); |
|||
for (const line of lines) { |
|||
const block = document.createElement(line.startsWith('Title: ') ? 'h2' : 'p'); |
|||
block.innerText = line; |
|||
fragment.appendChild(block); |
|||
} |
|||
this.props.self.el.appendChild(fragment); |
|||
this.Cancel() |
|||
} |
|||
|
|||
/* Function for cancelling it will remove the element popChatGPT*/ |
|||
Cancel(){ |
|||
var element = document.querySelector('.popChatGPT'); |
|||
element.remove(); |
|||
} |
|||
/* Function for closing the widget while clicking outside */ |
|||
onWindowClick(ev) { |
|||
var element = document.querySelector('.popChatGPT'); |
|||
if (element && !element.contains(ev.target)){ |
|||
this.Cancel() |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
recordAudio.template = xml` |
|||
<div class="popChatGPT"> |
|||
<div style="display: flex; align-items: end;margin-top:-20px;"> |
|||
<img src="chatgpt_odoo_connector/static/src/Icons/icon.png" height="35px"/> |
|||
<div class="h2 heading">Speech-to-text</div> |
|||
</div> |
|||
<hr/> |
|||
<div class="mb-3 audio-record"> |
|||
<button class="btn btn-success button-mic" t-if="!state.startedRecording" t-on-click="() => recordAudio(this)"> |
|||
<i class="fa fa-microphone" style="font-size: 24px;color:black;"/> |
|||
</button> |
|||
<button class="btn btn-danger button-mic" t-if="state.startedRecording" style="border-radius:13px;" t-on-click="() => stopRecord(this)"> |
|||
<i class="fa fa-microphone-slash" style="font-size: 24px;color:black;"></i> |
|||
</button> |
|||
</div> |
|||
<label for="response" class="form-label" t-if="state.transcriptedText" |
|||
style="color:white;">Response</label> |
|||
<div t-if="state.transcriptedText"> |
|||
<div class="mb-3"> |
|||
<textarea id="response" class="custom-text" rows="4" t-model="state.transcriptedText"></textarea> |
|||
</div> |
|||
</div> |
|||
<div style="display: flex;justify-content: space-around;"> |
|||
<button class="btn btn-primary custom" t-if="state.transcriptedText" t-on-click="Insert">Insert</button> |
|||
<button class="btn btn-secondary custom" t-on-click="Cancel">Cancel</button> |
|||
</div> |
|||
</div>`; |
|||
registry.category("actions").add("recordAudio", recordAudio); |
@ -0,0 +1,62 @@ |
|||
/** @odoo-module **/ |
|||
import Wysiwyg from 'web_editor.wysiwyg'; |
|||
import { browser } from '@web/core/browser/browser'; |
|||
import { _t } from 'web.core'; |
|||
var Dialog = require('web.Dialog'); |
|||
var core = require('web.core'); |
|||
var QWeb = core.qweb; |
|||
var rpc = require('web.rpc'); |
|||
import { OpenChatGPT } from "./open_chatgpt"; |
|||
import { recordAudio } from "./recordAudio"; |
|||
const { mount } = owl; |
|||
/* Appending new Category AI Tools, Chatgpt tool, and Speech-to-text tool in the powerbox options */ |
|||
Wysiwyg.include({ |
|||
init: function (parent, options) { |
|||
this._super.apply(this, arguments); |
|||
}, |
|||
/* Function for adding new category and tool */ |
|||
_getPowerboxOptions: function (){ |
|||
const options = this._super(); |
|||
const { commands, categories } = options; |
|||
const Category = { |
|||
name: _t('AI Tools'), |
|||
priority: 40 |
|||
}; |
|||
const itemSectionCommand = { |
|||
category: _t('AI Tools'), |
|||
name: _t('ChatGPT'), |
|||
priority: 40, |
|||
description: _t('Generate content with AI'), |
|||
fontawesome: 'fa-magic', |
|||
callback: this._openChatGPT.bind(this) |
|||
}; |
|||
const itemSpeechToAudio = { |
|||
category: _t('AI Tools'), |
|||
name: _t('Speech-To-Text'), |
|||
priority: 40, |
|||
description: _t('Speech to text'), |
|||
fontawesome: 'fa-microphone', |
|||
callback: this._recordVoice.bind(this) |
|||
}; |
|||
categories.push(Category); |
|||
commands.push(itemSectionCommand); |
|||
commands.push(itemSpeechToAudio); |
|||
return options; |
|||
}, |
|||
/* Function for mounting the element of chatgpt in the view */ |
|||
_openChatGPT: function () { |
|||
var element = $('.o_web_client')[0]; |
|||
if (element) { |
|||
const props = {rpc: rpc, self: this}; |
|||
mount(OpenChatGPT, element, {props: props}); |
|||
} |
|||
}, |
|||
/* Function for mounting the element speech-to-text in the view */ |
|||
_recordVoice: function () { |
|||
var element = $('.o_web_client')[0]; |
|||
if (element) { |
|||
const props = {rpc: rpc, self: this}; |
|||
mount(recordAudio, element, {props: props}); |
|||
} |
|||
}, |
|||
}); |
@ -0,0 +1,33 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<templates id="template" xml:space="preserve"> |
|||
<!-- Template for alternative chatgpt --> |
|||
<t t-name="alternativeChatGPT" id="chatGPTdialog"> |
|||
<div class="popChatGPTAlter"> |
|||
<div style="display: flex; align-items: end;margin-top:-20px;"> |
|||
<img src="chatgpt_odoo_connector/static/src/Icons/icon.png" height="35px"/> |
|||
<div class="h2 heading">ChatGPT</div> |
|||
</div> |
|||
<hr/> |
|||
<div style="display:flex;justify-content: space-evenly;"> |
|||
<div> |
|||
<button class="alterButton btn btn-outline-light" data-value="shorten">Shorten</button> |
|||
</div> |
|||
<div> |
|||
<button class="alterButton btn btn-outline-light" data-value="lengthen">Lengthen</button> |
|||
</div> |
|||
<div> |
|||
<button class="alterButton btn btn-outline-light" data-value="rephrase">Rephrase</button> |
|||
</div> |
|||
</div> |
|||
<br/> |
|||
<div class="mb-3"> |
|||
<label for="response" style="color:white;" class="form-label">Response</label> |
|||
<textarea class="custom-text" id="response" rows="4"/> |
|||
</div> |
|||
<div style="display: flex;justify-content: space-around;"> |
|||
<button class="Replace custom btn btn-primary">Replace</button> |
|||
<button class="Cancel custom btn btn-secondary">Cancel</button> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<templates xml:space="preserve"> |
|||
<!-- Adding new icon in the web_editor toolbar--> |
|||
<t t-name="toolbarCustom" t-inherit="web_editor.toolbar" t-inherit-mode="extension" owl="1"> |
|||
<xpath expr="//div[@id='link']" position="after"> |
|||
<div id="chatgpt" class="btn-group"> |
|||
<div id="open-chatgpt" title="Generate or transform content with AI" class="btn editor-ignore chatgpt"> |
|||
<span class="fa fa-magic fa-fw"/> |
|||
</div> |
|||
</div> |
|||
</xpath> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<!-- Inheriting product_product view --> |
|||
<record id="product_normal_form_view" model="ir.ui.view"> |
|||
<field name="name">product.product.view.form</field> |
|||
<field name="model">product.product</field> |
|||
<field name="inherit_id" ref="product.product_normal_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='product_tag_ids']" position="after"> |
|||
<field name="is_create_image"/> |
|||
<field name="is_update_image"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<!-- Inheriting product template view --> |
|||
<record id="product_template_only_form_view" model="ir.ui.view"> |
|||
<field name="name">product.template.view.form</field> |
|||
<field name="model">product.template</field> |
|||
<field name="inherit_id" ref="product.product_template_only_form_view"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//group[@name='group_standard_price']" position="inside"> |
|||
<field name="is_create_image"/> |
|||
<field name="is_update_image"/> |
|||
</xpath> |
|||
|
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<!-- Inheriting res config settings view--> |
|||
<record id="res_config_settings_view_form" model="ir.ui.view"> |
|||
<field name="name"> |
|||
res.config.settings.view.form.inherit.odoo.ai |
|||
</field> |
|||
<field name="model">res.config.settings</field> |
|||
<field name="priority" eval="20"/> |
|||
<field name="inherit_id" ref="base.res_config_settings_view_form"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//div[@name='integration']" position="inside"> |
|||
<div class="col-12 col-lg-6 o_setting_box"> |
|||
<div class="o_setting_left_pane" id="chatgpt"> |
|||
</div> |
|||
<div class="o_setting_right_pane"> |
|||
<label string="ChatGPT" for="api_key"/> |
|||
<div class="text-muted"> |
|||
<field name="api_key"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |