@ -0,0 +1,46 @@ |
|||||
|
.. 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 |
||||
|
|
||||
|
Email Management in Odoo |
||||
|
======================== |
||||
|
This Module will help to manage mails in odoo |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
* Configure outgoing mail server |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
General Public License, Version 3 (AGPL v3). |
||||
|
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developers: (V16) Hafeesul ALi, Jumana Jabin MP 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,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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 models |
@ -0,0 +1,55 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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': 'Email Management in Odoo', |
||||
|
'version': '16.0.1.0.0', |
||||
|
'category': 'Productivity', |
||||
|
'summary': 'This Module will help to manage all type of mails in Odoo', |
||||
|
'description': """Email Management in Odoo is a comprehensive module that |
||||
|
enhances the email handling capabilities of Odoo.This module is designed |
||||
|
to streamline and improve the management of all types of emails, providing |
||||
|
a user-friendly interface and additional functionalities for increased |
||||
|
productivity.""", |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'website': 'https://www.cybrosys.com', |
||||
|
'depends': ['mail', 'calendar', 'note', 'base'], |
||||
|
'data': [ |
||||
|
'security/ir.model.access.csv', |
||||
|
'data/mail_icon_data.xml', |
||||
|
'views/res_config_views.xml', |
||||
|
'views/odoo_mail_views.xml', |
||||
|
'views/mail_attachment_views.xml' |
||||
|
], |
||||
|
'assets': { |
||||
|
'web.assets_backend': [ |
||||
|
"odoo_mail_management/static/src/css/main.css", |
||||
|
"odoo_mail_management/static/src/js/*", |
||||
|
"odoo_mail_management/static/src/xml/*", |
||||
|
]}, |
||||
|
'images': ['static/description/banner.jpg'], |
||||
|
'license': 'AGPL-3', |
||||
|
'installable': True, |
||||
|
'application': False, |
||||
|
'auto_install': False, |
||||
|
} |
@ -0,0 +1,10 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- This XML file is used to define a record in Odoo. It sets the default logo for the main company. --> |
||||
|
<data noupdate="1"> |
||||
|
<record id="main_company" model="mail.icon"> |
||||
|
<field name="mail_icon" model="mail.icon" |
||||
|
eval="obj()._get_default_logo(original=True)"/> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,7 @@ |
|||||
|
## Module <odoo_mail_management> |
||||
|
|
||||
|
#### 06.07.2024 |
||||
|
#### Version 16.0.1.0.0 |
||||
|
#### ADD |
||||
|
|
||||
|
- Initial commit for Odoo Mail Management |
@ -0,0 +1,26 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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 ir_attachment |
||||
|
from . import mail_attachment |
||||
|
from . import mail_icon |
||||
|
from . import mail_mail |
||||
|
from . import res_config_settings |
@ -0,0 +1,46 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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 api, models |
||||
|
|
||||
|
|
||||
|
class IrAttachment(models.Model): |
||||
|
""" |
||||
|
This model extends the functionality of 'ir.attachment' in Odoo. |
||||
|
""" |
||||
|
_inherit = 'ir.attachment' |
||||
|
|
||||
|
@api.model |
||||
|
def get_fields(self, value): |
||||
|
""" |
||||
|
Retrieve specified fields from attachments identified by the given list of IDs. |
||||
|
""" |
||||
|
data_list = [] |
||||
|
for values in value: |
||||
|
attach = self.env['ir.attachment'].browse(values) |
||||
|
data_dict = { |
||||
|
'attachment': attach.id, |
||||
|
'datas': attach.datas, |
||||
|
'mimetype': attach.mimetype, |
||||
|
'name': attach.name |
||||
|
} |
||||
|
data_list.append(data_dict) |
||||
|
return data_list |
@ -0,0 +1,34 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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 MailAttachment(models.TransientModel): |
||||
|
"""This model is used for handling mail attachments in Odoo.""" |
||||
|
_name = "mail.attachment" |
||||
|
_description = "Mail Attachment" |
||||
|
|
||||
|
mail_attachment = fields.Binary(string="Attachment", |
||||
|
help="Binary field to store the attachment" |
||||
|
" data.") |
||||
|
file_name = fields.Char(string="File Name", |
||||
|
help="Name of the attached file.") |
@ -0,0 +1,69 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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 |
||||
|
from odoo import api, fields, models, tools |
||||
|
from odoo.modules.module import get_resource_path |
||||
|
|
||||
|
|
||||
|
class MailIcon(models.Model): |
||||
|
"""This model is used to manage mail icons in Odoo.""" |
||||
|
_name = "mail.icon" |
||||
|
_description = "Mail Icon " |
||||
|
|
||||
|
def _get_default_logo(self, original=False): |
||||
|
"""Method to load default logo""" |
||||
|
img_path = get_resource_path('odoo_mail_management', |
||||
|
'static/src/img/logo.png') |
||||
|
with tools.file_open(img_path, 'rb') as f: |
||||
|
return base64.b64encode(f.read()) |
||||
|
|
||||
|
mail_icon = fields.Binary(string="Mail Icon", |
||||
|
help="Binary field to store the mail icon.", |
||||
|
default=_get_default_logo) |
||||
|
|
||||
|
@api.model_create_multi |
||||
|
def create(self, vals_list): |
||||
|
"""Method to super create function and call _handle_icon() function""" |
||||
|
for vals in vals_list: |
||||
|
self._handle_icon(vals) |
||||
|
mail_settings = super().create(vals_list) |
||||
|
return mail_settings |
||||
|
|
||||
|
def write(self, values): |
||||
|
"""Method to super write function and call _handle_icon() function""" |
||||
|
self._handle_icon(values) |
||||
|
mail_settings = super().create(values) |
||||
|
return mail_settings |
||||
|
|
||||
|
@api.model |
||||
|
def _handle_icon(self, vals): |
||||
|
"""Method to handle the icon""" |
||||
|
if vals.get('mail_icon'): |
||||
|
vals['mail_icon'] = base64.b64encode( |
||||
|
tools.image_process(base64.b64decode(vals['mail_icon']), |
||||
|
size=(150, 150), crop='center')) |
||||
|
|
||||
|
@api.model |
||||
|
def load_logo(self): |
||||
|
"""Method to load logo into mail view""" |
||||
|
return self.env['mail.icon'].search([], order="id desc", limit=1). \ |
||||
|
mail_icon |
@ -0,0 +1,190 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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 api, fields, models |
||||
|
import re |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
|
||||
|
class MailMail(models.Model): |
||||
|
"""This model extends the 'mail.mail' model in Odoo to add additional |
||||
|
features.""" |
||||
|
_inherit = "mail.mail" |
||||
|
|
||||
|
is_starred = fields.Boolean(string="Starred Mail", default=False, |
||||
|
help="Flag indicating whether the mail is" |
||||
|
" starred.") |
||||
|
active = fields.Boolean(default=True, |
||||
|
help="Flag indicating whether the mail is active.") |
||||
|
|
||||
|
@api.model |
||||
|
def get_mail_count(self): |
||||
|
"""Method to get count of all mails,sent mails |
||||
|
,mails in outbox,starred mails and archived mails.""" |
||||
|
all_count = self.sudo().search_count( |
||||
|
[('create_uid', '=', self.env.user.id)]) |
||||
|
sent_count = self.sudo().search_count( |
||||
|
[('create_uid', '=', self.env.user.id), ('state', '=', 'sent')]) |
||||
|
outbox_count = self.sudo().search_count( |
||||
|
[('state', '=', 'exception'), |
||||
|
('create_uid', '=', self.env.user.id)]) |
||||
|
stared_count = self.sudo().search_count( |
||||
|
[('is_starred', '=', True), ('create_uid', '=', self.env.user.id)]) |
||||
|
archived_count = self.sudo().search_count( |
||||
|
[('active', '=', False), ('create_uid', '=', self.env.user.id)]) |
||||
|
mail_dict = {'all_count': all_count, |
||||
|
'sent_count': sent_count, |
||||
|
'outbox_count': outbox_count, |
||||
|
'starred_count': stared_count, |
||||
|
"archived_count": archived_count, } |
||||
|
return mail_dict |
||||
|
|
||||
|
@api.model |
||||
|
def get_starred_mail(self): |
||||
|
"""Method to fetch all starred mails.""" |
||||
|
mails = self.sudo().search( |
||||
|
[('is_starred', '=', True), ('create_uid', '=', self.env.user.id)]) |
||||
|
return mails.read() |
||||
|
|
||||
|
@api.model |
||||
|
def delete_mail(self, ids): |
||||
|
"""Method to unlink mail.""" |
||||
|
mails = self.sudo().search( |
||||
|
[('id', 'in', ids), ('create_uid', '=', self.env.user.id), '|', |
||||
|
('active', '=', False), ('id', 'in', ids), |
||||
|
('create_uid', '=', self.env.user.id)]) |
||||
|
for mail in mails: |
||||
|
mail.sudo().unlink() |
||||
|
|
||||
|
@api.model |
||||
|
def open_mail(self, *args): |
||||
|
"""Method to open a mail and show its content.""" |
||||
|
detail = self.sudo().search( |
||||
|
[('id', '=', *args), ('create_uid', '=', self.env.user.id), '|', |
||||
|
('active', '=', False), ('id', '=', *args), |
||||
|
('create_uid', '=', self.env.user.id)]).body_html |
||||
|
return detail |
||||
|
|
||||
|
@api.model |
||||
|
def star_mail(self, *args): |
||||
|
"""Method to make a mail starred.""" |
||||
|
self.search([('id', '=', *args), |
||||
|
('create_uid', '=', self.env.user.id)]). \ |
||||
|
write({"is_starred": True}) |
||||
|
|
||||
|
@api.model |
||||
|
def unstar_mail(self, *args): |
||||
|
"""Method to make a mail not starred.""" |
||||
|
self.sudo().search([('id', '=', *args), |
||||
|
('create_uid', '=', self.env.user.id)]). \ |
||||
|
write({"is_starred": False}) |
||||
|
|
||||
|
@api.model |
||||
|
def archive_mail(self, *args): |
||||
|
"""Method to archive mail.""" |
||||
|
self.sudo().search([('id', '=', *args), |
||||
|
('create_uid', '=', self.env.user.id)]). \ |
||||
|
write({"active": False}) |
||||
|
|
||||
|
@api.model |
||||
|
def get_archived_mail(self): |
||||
|
"""Method to get archived mails""" |
||||
|
mail_dict = {} |
||||
|
mails = self.sudo().search([('active', '=', False), |
||||
|
('create_uid', '=', self.env.user.id)]) |
||||
|
for record in mails: |
||||
|
if record.email_to: |
||||
|
mail_dict[str(record.mail_message_id)] = ({ |
||||
|
"id": record.id, |
||||
|
"sender": record.email_to, |
||||
|
"subject": record.subject, |
||||
|
"date": fields.Date.to_date(record.create_date), }) |
||||
|
elif record.recipient_ids: |
||||
|
mail_dict[str(record.mail_message_id)] = ({ |
||||
|
"id": record.id, |
||||
|
"sender": record.recipient_ids.name, |
||||
|
"subject": record.subject, |
||||
|
"date": fields.Date.to_date(record.create_date), }) |
||||
|
return mails.read() |
||||
|
|
||||
|
@api.model |
||||
|
def unarchive_mail(self, *args): |
||||
|
"""Method to make mail unarchived.""" |
||||
|
self.sudo().search([('active', '=', False), ('id', '=', *args), |
||||
|
('create_uid', '=', self.env.user.id)]). \ |
||||
|
write({'active': True}) |
||||
|
|
||||
|
@api.model |
||||
|
def delete_checked_mail(self, *args): |
||||
|
"""Method to delete checked mails.""" |
||||
|
self.search( |
||||
|
[('id', '=', *args), '|', ('id', '=', *args), |
||||
|
('active', '=', False)]).sudo().unlink() |
||||
|
|
||||
|
@api.model |
||||
|
def archive_checked_mail(self, *args): |
||||
|
"""Method to archive checked mails.""" |
||||
|
self.sudo().search([('id', 'in', *args), |
||||
|
('create_uid', '=', self.env.user.id)]). \ |
||||
|
write({"active": False}) |
||||
|
|
||||
|
@api.model |
||||
|
def sent_mail(self, **kwargs): |
||||
|
"""Method to compose and send mail.""" |
||||
|
attachment_ids = [] |
||||
|
mail_from = self.env.user.email |
||||
|
subject = kwargs.get('subject') |
||||
|
recipient = kwargs.get('recipient') |
||||
|
if not re.match(r"[^@]+@gmail\.com", recipient): |
||||
|
raise ValidationError("Recipient email should be a Gmail address.") |
||||
|
content = kwargs.get('content') |
||||
|
content_html = content.replace('\n', '<br>') |
||||
|
image = kwargs.get('images') |
||||
|
if image: |
||||
|
for img_data in image: |
||||
|
image_data = img_data.get('image_uri') |
||||
|
if image_data: |
||||
|
attachment = self.env['ir.attachment'].create({ |
||||
|
'name': img_data.get('name'), |
||||
|
'datas': image_data, |
||||
|
'res_model': 'mail.mail', |
||||
|
}) |
||||
|
attachment_ids.append((4, attachment.id)) |
||||
|
|
||||
|
mail_id = self.sudo().with_user(user=self.env.user).create({ |
||||
|
"subject": subject, |
||||
|
"email_to": recipient, |
||||
|
"email_from": mail_from, |
||||
|
"body_html": content_html, |
||||
|
"attachment_ids": attachment_ids |
||||
|
}) |
||||
|
|
||||
|
mail_id.send() |
||||
|
return mail_id.read() |
||||
|
|
||||
|
@api.model |
||||
|
def retry_mail(self, *args): |
||||
|
"""Method to retry failed messages""" |
||||
|
mail = self.search([('id', '=', int(*args)), |
||||
|
('create_uid', '=', self.env.user.id)]) |
||||
|
mail.mark_outgoing() |
||||
|
mail.send() |
@ -0,0 +1,46 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Hafeesul Ali(<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): |
||||
|
"""This model extends the 'res.config.settings' model in Odoo to add |
||||
|
additional settings.""" |
||||
|
_inherit = "res.config.settings" |
||||
|
|
||||
|
def _default_mail_icon_id(self): |
||||
|
"""Method to return default mail_icon model """ |
||||
|
return self.env['mail.icon'].search([], order='id desc', limit=1) |
||||
|
|
||||
|
mail_icon_id = fields.Many2one("mail.icon", |
||||
|
default=_default_mail_icon_id, |
||||
|
ondelete='cascade', |
||||
|
string="Mail Icon Id", |
||||
|
help="Mail Icon Id") |
||||
|
icon = fields.Binary('mail_icon', |
||||
|
related='mail_icon_id.mail_icon', |
||||
|
readonly=False, |
||||
|
help="Icon") |
||||
|
custom_mail_logo = fields.Boolean(string="Custom Mail Logo", |
||||
|
help="Customize your mail logo", |
||||
|
config_parameter="odoo_mail_management." |
||||
|
"custom_mail_logo") |
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
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: 68 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 255 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,751 @@ |
|||||
|
<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: #875A7B; 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 --> |
||||
|
|
||||
|
<!-- APP HERO --> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-12 col-md-12 col-lg-12" |
||||
|
> |
||||
|
<h1 |
||||
|
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #FFFFFF !important; font-size: 3.5rem !important; text-align: center !important;"> |
||||
|
Email Management in Odoo</h1> |
||||
|
<p |
||||
|
style="font-family: 'Montserrat', sans-serif !important; font-weight: 300 !important; color: #FFFFFF !important; font-size: 1.4rem !important; text-align: center !important;"> |
||||
|
Odoo Mail Management |
||||
|
</p> |
||||
|
<img src="./assets/screenshots/hero.gif" class="img-responsive" width="100%" height="auto" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<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> |
||||
|
<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 !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
||||
|
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"> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;"> |
||||
|
This module helps to manage mails in Odoo.Here we can |
||||
|
compose,search,star,archive,delete mail.We can view the outgoing mail,sent |
||||
|
mail,archived mail ,starred mail in separate tabs. |
||||
|
</p> |
||||
|
|
||||
|
</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="configuration"> |
||||
|
<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 !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
||||
|
Configuration |
||||
|
</h2> |
||||
|
</div> |
||||
|
<div class="col-mg-12 pl-3"> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;"> |
||||
|
Configure Outgoing Mail Server</p> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<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"/> |
||||
|
<h4 |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Community & Enterprise Support</h4> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<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"/> |
||||
|
<h4 |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Manage mails in Odoo</h4> |
||||
|
|
||||
|
</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;"> <h4 class="my-2" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Manage mails in Odoo.</h4> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
||||
|
We can see all mails in Odoo. |
||||
|
</p> |
||||
|
<img src="assets/screenshots/1.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="my-2" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Search bar.</h4> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
||||
|
We can search a mail easily using this search bar. |
||||
|
</p> |
||||
|
<img src="assets/screenshots/2.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-2" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Checkbox.</h4> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
||||
|
Checkbox that can select all mail,multiple mail to delete and archive multiple |
||||
|
mail together. |
||||
|
</p> |
||||
|
<img src="assets/screenshots/3.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Make mails starred.</h4> |
||||
|
<img src="assets/screenshots/4.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Delete and archive mail.</h4> |
||||
|
<img src="assets/screenshots/5.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Calendar,Notes and Contacts button.</h4> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
||||
|
Calendar,Notes and Contacts button to redirect into respective modules. |
||||
|
</p> |
||||
|
<img src="assets/screenshots/6.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Compose a mail</h4> |
||||
|
<img src="assets/screenshots/7.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Compose mail window.</h4> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
||||
|
we can compose mail easily here and have an option to attach file,button to extend |
||||
|
compose mail window. |
||||
|
</p> |
||||
|
|
||||
|
<img src="assets/screenshots/8.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Large window to compose mail.</h4> |
||||
|
<img src="assets/screenshots/9.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Minimize Feature for the mail.</h4> |
||||
|
<img src="assets/screenshots/10.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Sent mails.</h4> |
||||
|
<img src="assets/screenshots/12.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Can See the Starred mails, Archived mails and outbox mails individually .</h4> |
||||
|
<img src="assets/screenshots/13.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
</div> |
||||
|
<div style="display: block; margin: 30px auto;"> |
||||
|
<h4 class="mt-3" |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
||||
|
Custom Mail Logo.</h4> |
||||
|
<p |
||||
|
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
||||
|
User can change the mail logo from settings |
||||
|
</p> |
||||
|
|
||||
|
<img src="assets/screenshots/14.png" class="img-responsive img-thumbnail border" width="100%" |
||||
|
height="auto" /> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<!-- END OF SCREENSHOTS SECTION --> |
||||
|
|
||||
|
<!-- SUGGESTED 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 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/direct_send_email_template/" |
||||
|
target="_blank"> |
||||
|
<div style="border-radius:10px"> |
||||
|
<img class="img img-responsive center-block" style="border-radius: 0px;" |
||||
|
src="./assets/modules/module01.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/sale_order_line_multi_warehouse/" |
||||
|
target="_blank"> |
||||
|
<div style="border-radius:10px"> |
||||
|
<img class="img img-responsive center-block" style="border-radius: 0px;" |
||||
|
src="./assets/modules/module02.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/pos_sync_orders/" target="_blank"> |
||||
|
<div style="border-radius:10px"> |
||||
|
<img class="img img-responsive center-block" style="border-radius: 0px;" |
||||
|
src="./assets/modules/module03.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/fleet_complete_report/" target="_blank"> |
||||
|
<div style="border-radius:10px"> |
||||
|
<img class="img img-responsive center-block" style="border-radius: 0px;" |
||||
|
src="./assets/modules/module04.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/gender_contact/" target="_blank"> |
||||
|
<div style="border-radius:10px"> |
||||
|
<img class="img img-responsive center-block" style="border-radius: 0px;" |
||||
|
src="./assets/modules/module05.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/service_charges_pos/" target="_blank"> |
||||
|
<div style="border-radius:10px"> |
||||
|
<img class="img img-responsive center-block" style="border-radius: 0px;" |
||||
|
src="./assets/modules/module06.png"> |
||||
|
</div> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<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 --> |
||||
|
|
||||
|
<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/star.png"/> |
||||
|
</div> |
||||
|
<h2 class="mt-2" |
||||
|
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
||||
|
Our Services |
||||
|
</h2> |
||||
|
</div> |
||||
|
|
||||
|
<div class="container my-5"> |
||||
|
<div class="row"> |
||||
|
<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> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<!-- END OF OUR SERVICES --> |
||||
|
|
||||
|
<!-- OUR INDUSTRIES --> |
||||
|
|
||||
|
<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/corporate.png"/> |
||||
|
</div> |
||||
|
<h2 class="mt-2" |
||||
|
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
||||
|
Our |
||||
|
Industries |
||||
|
</h2> |
||||
|
</div> |
||||
|
|
||||
|
<div class="container my-5"> |
||||
|
<div class="row"> |
||||
|
<div class="col-lg-3"> |
||||
|
<div class="my-4 d-flex flex-column justify-content-center" |
||||
|
style="background-color: #f6f8f9 !important; border-radius: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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> |
||||
|
</div> |
||||
|
|
||||
|
<!-- END OF OUR INDUSTRIES --> |
||||
|
|
||||
|
<!-- SUPPORT --> |
||||
|
<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/customer-support.png"/> |
||||
|
</div> |
||||
|
<h2 class="mt-2" |
||||
|
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> |
||||
|
Support |
||||
|
</h2> |
||||
|
</div> |
||||
|
<div class="container mt-5"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-12 col-md-6"> |
||||
|
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> |
||||
|
<div class="mr-4 d-flex justify-content-center align-items-center" |
||||
|
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> |
||||
|
<img src="assets/misc/support.png" height="48" width="48" |
||||
|
style="width: 42px; height: 42px;"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<h4>Need Help?</h4> |
||||
|
<p style="line-height: 100%;">Got questions or need help? |
||||
|
Get in touch.</p> |
||||
|
<a href="mailto:odoo@cybrosys.com"> |
||||
|
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> |
||||
|
odoo@cybrosys.com</p> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-sm-12 col-md-6"> |
||||
|
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> |
||||
|
<div class="mr-4 d-flex justify-content-center align-items-center" |
||||
|
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> |
||||
|
<img src="assets/misc/whatsapp.png" height="52" width="52" |
||||
|
style="width: 52px; height: 52px;"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<h4>WhatsApp</h4> |
||||
|
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p> |
||||
|
<a href="https://api.whatsapp.com/send?phone=918606827707"> |
||||
|
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> |
||||
|
+91 86068 |
||||
|
27707</p> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> |
||||
|
<img src="assets/misc/logo.png" width="144" height="31" |
||||
|
style="width:144px; height: 31px; margin-top: 40px;"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- END OF SUPPORT --> |
After Width: | Height: | Size: 389 B |
After Width: | Height: | Size: 562 B |
After Width: | Height: | Size: 890 B |
After Width: | Height: | Size: 268 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 234 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 659 B |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 204 B |
After Width: | Height: | Size: 249 B |
After Width: | Height: | Size: 334 B |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 359 B |
After Width: | Height: | Size: 393 B |
After Width: | Height: | Size: 282 B |
After Width: | Height: | Size: 351 B |
After Width: | Height: | Size: 349 B |
After Width: | Height: | Size: 582 B |
@ -0,0 +1,29 @@ |
|||||
|
/** @odoo-module **/ |
||||
|
import { Component, useRef} from "@odoo/owl"; |
||||
|
import { _t } from "@web/core/l10n/translation"; |
||||
|
import { Dialog } from "@web/core/dialog/dialog"; |
||||
|
|
||||
|
export class ImportDialog extends Component { |
||||
|
/** |
||||
|
*handle the json file and import the data |
||||
|
**/ |
||||
|
setup() { |
||||
|
this.file = false |
||||
|
} |
||||
|
onChangeFileInput(ev) { |
||||
|
const { files } = ev.target |
||||
|
if (!files[0]) return; |
||||
|
this.file = files[0] |
||||
|
} |
||||
|
async onFileUpload(ev) { if (this.file){ |
||||
|
this.props.addAttachment(this.file) |
||||
|
this.cancel() |
||||
|
} |
||||
|
} |
||||
|
cancel() { |
||||
|
this.props.close(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ImportDialog.template = "ImportDialog" |
||||
|
ImportDialog.components = { Dialog } |
@ -0,0 +1,136 @@ |
|||||
|
/* @odoo-module*/ |
||||
|
import {Component,useState,useRef} from '@odoo/owl' |
||||
|
import { useBus, useService } from "@web/core/utils/hooks"; |
||||
|
import {ImportDialog} from "./AttachmentMail"; |
||||
|
/** |
||||
|
* ComposeMail component for handling mail composition. |
||||
|
* @extends Component |
||||
|
*/ |
||||
|
export class ComposeMail extends Component { |
||||
|
setup() { |
||||
|
this.orm = useService('orm') |
||||
|
this.root = useRef('root'); |
||||
|
this.action = useService('action') |
||||
|
this.dialog = useService('dialog') |
||||
|
this.state = useState({ |
||||
|
subject: "", |
||||
|
recipient: "", |
||||
|
content: "", |
||||
|
images: [], |
||||
|
originalHeight: null, |
||||
|
minimized: false, |
||||
|
attachedFiles: [], |
||||
|
}) |
||||
|
this.contentState = useState({ |
||||
|
images: [], |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
async imageReader(file) { |
||||
|
const fileReader = new FileReader(); |
||||
|
fileReader.onload = (event) => { |
||||
|
const imageDataUrl = event.target.result; // Data URL of the image
|
||||
|
if (imageDataUrl) { |
||||
|
this.state.images.push({name: file.name, image_uri: imageDataUrl.split(",")[1]}) |
||||
|
} |
||||
|
}; |
||||
|
fileReader.readAsDataURL(file); |
||||
|
|
||||
|
} |
||||
|
contentHandler(file) { |
||||
|
switch (file.type) { |
||||
|
case "image/jpeg": |
||||
|
case "image/png": |
||||
|
case "image/gif": |
||||
|
case "image/svg+xml": |
||||
|
case "image/webp": |
||||
|
return this.imageReader(file); |
||||
|
case "application/pdf": |
||||
|
return this.imageReader(file); |
||||
|
case "text/csv": |
||||
|
return this.csvReader(file); |
||||
|
default: |
||||
|
console.warn(`Unsupported file type: ${file.type}`); |
||||
|
} |
||||
|
} |
||||
|
/** |
||||
|
* Method to send the composed mail. |
||||
|
*/ |
||||
|
async sentMail() { |
||||
|
const { |
||||
|
subject, |
||||
|
recipient, |
||||
|
content, |
||||
|
images, |
||||
|
} = this.state |
||||
|
let sendMail = [] |
||||
|
if (recipient) { |
||||
|
sendMail = await this.orm.call('mail.mail', 'sent_mail', [], { |
||||
|
subject, |
||||
|
recipient, |
||||
|
content, |
||||
|
images, |
||||
|
}) |
||||
|
this.props.loadMail(...sendMail) |
||||
|
this.props.close() |
||||
|
window.location.reload() |
||||
|
} |
||||
|
} |
||||
|
/** |
||||
|
* Method to maximize or restore the mail composition window. |
||||
|
*/ |
||||
|
maximizeMail() { |
||||
|
const mailBody = this.root.el; |
||||
|
const TextArea = this.root.el.querySelector("#content"); |
||||
|
|
||||
|
if (mailBody.classList.contains('maximized')) { |
||||
|
mailBody.style.height = '532px'; |
||||
|
mailBody.style.right = '5%'; |
||||
|
mailBody.style.width = '30%'; |
||||
|
mailBody.style.position = 'fixed'; |
||||
|
TextArea.style.height = '300px'; |
||||
|
} else { |
||||
|
mailBody.style.height = '900px'; |
||||
|
mailBody.style.right = '5%'; |
||||
|
mailBody.style.width = '100%'; |
||||
|
mailBody.style.position = 'absolute'; |
||||
|
|
||||
|
} |
||||
|
mailBody.classList.toggle('maximized'); |
||||
|
} |
||||
|
/** |
||||
|
* Method to close the mail composition window. |
||||
|
*/ |
||||
|
Close() { |
||||
|
this.props.close() |
||||
|
} |
||||
|
/** |
||||
|
* Method to minimize or restore the mail composition window. |
||||
|
*/ |
||||
|
minimizeMail() { |
||||
|
const mailBody = this.root.el; |
||||
|
if (!this.state.minimized) { |
||||
|
this.state.originalHeight = mailBody.style.height; |
||||
|
mailBody.style.height = '50px'; |
||||
|
} else { |
||||
|
mailBody.style.height = this.state.originalHeight; |
||||
|
} |
||||
|
this.state.minimized = !this.state.minimized; |
||||
|
} |
||||
|
/** |
||||
|
* Method to trigger the attachment action. |
||||
|
*/ |
||||
|
async attachmentAction() { |
||||
|
this.dialog.add(ImportDialog, { |
||||
|
addAttachment: this.addAttachment.bind(this) |
||||
|
}) |
||||
|
} |
||||
|
closeInput(index){ |
||||
|
this.state.attachedFiles.splice(index, 1) |
||||
|
} |
||||
|
addAttachment(attachment) { |
||||
|
this.state.attachedFiles.push(attachment) |
||||
|
this.contentHandler(attachment) |
||||
|
} |
||||
|
} |
||||
|
ComposeMail.template = 'ComposeMail' |
@ -0,0 +1,83 @@ |
|||||
|
/* @odoo-module*/ |
||||
|
import { Component, useRef, useState ,markup} from '@odoo/owl' |
||||
|
import { useService } from "@web/core/utils/hooks"; |
||||
|
|
||||
|
/** |
||||
|
* MailBody component for displaying mail details. |
||||
|
* @extends Component |
||||
|
*/ |
||||
|
export class MailBody extends Component { |
||||
|
setup() { |
||||
|
this.ref = useRef('root') |
||||
|
this.html_content = this.props.mail.body_html.replace(/<br>/g, '') |
||||
|
|
||||
|
this.orm = useService('orm') |
||||
|
this.state = useState({ |
||||
|
starred: false, |
||||
|
}) |
||||
|
this.env.bus.addEventListener("SELECT:ALL", (event) => { |
||||
|
const { checked } = event.detail |
||||
|
this.ref.el.querySelector(".mail_check_box").checked = checked |
||||
|
this.props.onSelectMail(this.props.mail.id, checked) |
||||
|
}) |
||||
|
} |
||||
|
/** |
||||
|
* Method triggered on click of the mail selection checkbox. |
||||
|
* @param {Object} ev - Event object. |
||||
|
*/ |
||||
|
onClickSelect(ev) { |
||||
|
const checked = ev.target.checked |
||||
|
this.props.onSelectMail(this.props.mail.id, checked) |
||||
|
} |
||||
|
/** |
||||
|
* Method to archive the mail. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async archiveMail(event){ |
||||
|
var mail = this.props.mail.id |
||||
|
await this.orm.call('mail.mail','archive_mail',[mail]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to unarchive the mail. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async unArchive(event){ |
||||
|
var mail = this.props.mail.id |
||||
|
await this.orm.call('mail.mail','unarchive_mail',[mail]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to resend the mail. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async resendMail(){ |
||||
|
var mail = this.props.mail.id |
||||
|
await this.orm.call('mail.mail','retry_mail',[mail]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to delete the mail. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async deleteMail(event){ |
||||
|
var mail = this.props.mail.id |
||||
|
await this.orm.call('mail.mail','delete_checked_mail',[mail]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to star or unstar the mail. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async starMail(event){ |
||||
|
this.state.starred = !this.state.starred |
||||
|
var mail = this.props.mail.id |
||||
|
this.props.starMail(mail, this.state.starred) |
||||
|
await this.orm.call('mail.mail','star_mail',[mail]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to open the mail. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async openMail(event){ |
||||
|
var mail = this.props.mail |
||||
|
this.props.openMail(mail) |
||||
|
} |
||||
|
} |
||||
|
MailBody.template = 'MailBody' |
@ -0,0 +1,276 @@ |
|||||
|
/* @odoo-module*/ |
||||
|
import { registry } from '@web/core/registry'; |
||||
|
import { Component , useRef , useState, onWillStart ,onMounted} from '@odoo/owl' |
||||
|
import { useService } from "@web/core/utils/hooks"; |
||||
|
import { MailBody } from './MailBody' |
||||
|
import { SentMail } from './SentMail' |
||||
|
import { MessageView } from './MessageView' |
||||
|
import { ComposeMail } from './ComposeMail' |
||||
|
import { ImportDialog } from './AttachmentMail' |
||||
|
import { session } from "@web/session"; |
||||
|
/** |
||||
|
* odooMail component for handling mail-related functionalities. |
||||
|
* @extends Component |
||||
|
*/ |
||||
|
class odooMail extends Component { |
||||
|
setup() { |
||||
|
this.mailState = useState({ |
||||
|
loadLogo: "", |
||||
|
loadMail: [], |
||||
|
getCount: "", |
||||
|
outBox: "", |
||||
|
mode: "tree", |
||||
|
formData: {}, |
||||
|
mailType: "all" |
||||
|
}) |
||||
|
this.dialogService = useService("dialog") |
||||
|
this.root = useRef('root'); |
||||
|
this.action = useService('action') |
||||
|
this.orm = useService('orm') |
||||
|
this.selectedMails = [] |
||||
|
onMounted(() => { |
||||
|
this.allMailView() |
||||
|
}) |
||||
|
onWillStart(async ()=> { |
||||
|
this.mailState.loadLogo = await this.orm.call('mail.icon','load_logo',[]) |
||||
|
// this.allMailView()
|
||||
|
this.getCount() |
||||
|
}) |
||||
|
} |
||||
|
/** |
||||
|
* Method to get the count of different mail categories. |
||||
|
*/ |
||||
|
async getCount(){ |
||||
|
this.mailState.getCount = await this.orm.call('mail.mail','get_mail_count',[]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to compose a new mail. |
||||
|
*/ |
||||
|
async composeMail(){ |
||||
|
this.dialogService.add(ComposeMail, { |
||||
|
loadMail: (mail) => { |
||||
|
this.mailState.loadMail.unshift(mail) |
||||
|
this.getCount() |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
/** |
||||
|
* Method triggered on click of the "Select All" checkbox. |
||||
|
* @param {Object} ev - Event object. |
||||
|
*/ |
||||
|
onClickSelectAll(ev) { |
||||
|
const checked = ev.target.checked |
||||
|
this.env.bus.trigger("SELECT:ALL", { checked }) |
||||
|
} |
||||
|
/** |
||||
|
* Getter method to get props for MailBody component. |
||||
|
* @returns {Object} - Props for MailBody component. |
||||
|
*/ |
||||
|
get mailProps() { |
||||
|
return { |
||||
|
onSelectMail: this.onSelectMail.bind(this), |
||||
|
starMail: this.starMail.bind(this), |
||||
|
openMail: this.openMail.bind(this), |
||||
|
mailType: this.mailType, |
||||
|
} |
||||
|
} |
||||
|
/** |
||||
|
* Method to reset the mail view. |
||||
|
*/ |
||||
|
resetView(){ |
||||
|
this.mailState.formData = {} |
||||
|
this.mailState.mode = "tree" |
||||
|
} |
||||
|
/** |
||||
|
* Method to open a specific mail. |
||||
|
* @param {Object} mail - Mail object. |
||||
|
*/ |
||||
|
openMail(mail) { |
||||
|
this.mailState.formData = mail |
||||
|
this.mailState.mode = "form" |
||||
|
} |
||||
|
/** |
||||
|
* Method to star or unstar a mail. |
||||
|
* @param {Number} mail - Mail ID. |
||||
|
* @param {Boolean} type - Type of action (star or unstar). |
||||
|
*/ |
||||
|
starMail(mail, type){ |
||||
|
if (type) { |
||||
|
this.mailState.getCount.starred_count ++ |
||||
|
} |
||||
|
else this.mailState.getCount.starred_count -- |
||||
|
} |
||||
|
/** |
||||
|
* Method triggered on selecting or deselecting a mail. |
||||
|
* @param {Number} mailId - Mail ID. |
||||
|
* @param {Boolean} check - Checked or not. |
||||
|
*/ |
||||
|
onSelectMail(mailId, check) { |
||||
|
if (check) { |
||||
|
this.selectedMails.push(mailId) |
||||
|
} |
||||
|
else { |
||||
|
this.selectedMails.filter(item => item !== mailId) |
||||
|
} |
||||
|
} |
||||
|
/** |
||||
|
* Getter method to get the mail type. |
||||
|
* @returns {String} - Current mail type. |
||||
|
*/ |
||||
|
get mailType() { |
||||
|
return this.mailState.mailType |
||||
|
} |
||||
|
/** |
||||
|
* Method to archive selected mails. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async archiveMail(event){ |
||||
|
if (this.selectedMails.length){ |
||||
|
this.mailState.loadMail = this.mailState.loadMail.filter(item => !this.selectedMails.includes(item.id)) |
||||
|
await this.orm.call('mail.mail','archive_mail',[this.selectedMails]) |
||||
|
this.getCount() |
||||
|
this.selectedMails = [] |
||||
|
} |
||||
|
} |
||||
|
/** |
||||
|
* Method to refresh the page. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
refreshPage(event){ |
||||
|
window.location.reload() |
||||
|
} |
||||
|
/** |
||||
|
* Method to delete selected mails. |
||||
|
* @param {Object} event - Event object. |
||||
|
*/ |
||||
|
async deleteMail(event){ |
||||
|
if (this.selectedMails.length){ |
||||
|
this.mailState.loadMail = this.mailState.loadMail.filter(item => !this.selectedMails.includes(item.id)) |
||||
|
await this.orm.call('mail.mail','delete_mail',[this.selectedMails]) |
||||
|
this.getCount() |
||||
|
this.selectedMails = [] |
||||
|
} |
||||
|
} |
||||
|
/** |
||||
|
* Method to view all mails. |
||||
|
*/ |
||||
|
async allMailView(){ |
||||
|
await $(this.root.el.querySelector('.all_mail')).addClass('active'); |
||||
|
$(this.root.el.querySelector('.archieved-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.outbox')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent')).removeClass('active'); |
||||
|
this.mailState.mailType = 'all' |
||||
|
this.resetView() |
||||
|
this.mailState.loadMail = await this.orm.searchRead('mail.mail',[['create_uid', '=', session.uid]],[], { order: "create_date desc"}) |
||||
|
} |
||||
|
/** |
||||
|
* Method to view starred mails. |
||||
|
*/ |
||||
|
async starredMail(){ |
||||
|
$(this.root.el.querySelector('.sent-mail')).addClass('active'); |
||||
|
$(this.root.el.querySelector('.archieved-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.outbox')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.all_mail')).removeClass('active'); |
||||
|
this.mailState.mailType = "starred" |
||||
|
this.resetView() |
||||
|
this.mailState.loadMail = await this.orm.call('mail.mail','get_starred_mail',[]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to view archived mails. |
||||
|
*/ |
||||
|
async archivedMail(){ |
||||
|
$(this.root.el.querySelector('.archieved-mail')).addClass('active'); |
||||
|
$(this.root.el.querySelector('.sent-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.outbox')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.all_mail')).removeClass('active'); |
||||
|
this.mailState.mailType = 'archive' |
||||
|
this.resetView() |
||||
|
this.mailState.loadMail = await this.orm.call('mail.mail','get_archived_mail',[]) |
||||
|
} |
||||
|
/** |
||||
|
* Method to view outbox mails. |
||||
|
*/ |
||||
|
async outboxMailView(){ |
||||
|
$(this.root.el.querySelector('.outbox')).addClass('active'); |
||||
|
$(this.root.el.querySelector('.archieved-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.all_mail')).removeClass('active'); |
||||
|
this.mailState.mailType = "outbox" |
||||
|
this.resetView() |
||||
|
this.mailState.loadMail = await this.orm.searchRead('mail.mail',[['create_uid', '=', session.uid],['state', '=', 'exception']],[], { order: "create_date desc"}) |
||||
|
} |
||||
|
/** |
||||
|
* Method to view sent mails. |
||||
|
*/ |
||||
|
async sentMail(){ |
||||
|
$(this.root.el.querySelector('.sent')).addClass('active'); |
||||
|
$(this.root.el.querySelector('.archieved-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.sent-mail')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.outbox')).removeClass('active'); |
||||
|
$(this.root.el.querySelector('.all_mail')).removeClass('active'); |
||||
|
this.resetView() |
||||
|
this.mailState.loadMail = await this.orm.searchRead('mail.mail',[['create_uid', '=', session.uid],['state', '=', 'sent']],[], { order: "create_date desc"}) |
||||
|
} |
||||
|
/** |
||||
|
* Method to redirect to the calendar view. |
||||
|
*/ |
||||
|
redirectCalender(){ |
||||
|
this.action.doAction({ |
||||
|
name: "Calender", |
||||
|
type: 'ir.actions.act_window', |
||||
|
res_model: 'calendar.event', |
||||
|
view_mode: 'calendar,tree', |
||||
|
view_type: 'calendar', |
||||
|
views: [[false, 'calendar'], [false, 'tree']], |
||||
|
target: 'current', |
||||
|
}); |
||||
|
} |
||||
|
/** |
||||
|
* Method to redirect to the notes view. |
||||
|
*/ |
||||
|
redirectNote(){ |
||||
|
this.action.doAction({ |
||||
|
name: "Notes", |
||||
|
type: 'ir.actions.act_window', |
||||
|
res_model: 'note.note', |
||||
|
view_mode: 'kanban,form,tree,activity', |
||||
|
view_type: 'kanban', |
||||
|
views: [[false, 'kanban'], [false, 'form'], [false, 'tree'], [false, 'activity']], |
||||
|
target: 'current', |
||||
|
}); |
||||
|
} |
||||
|
/** |
||||
|
* Method to redirect to the contacts view. |
||||
|
*/ |
||||
|
redirectContacts(){ |
||||
|
this.action.doAction({ |
||||
|
name: "Contacts", |
||||
|
type: 'ir.actions.act_window', |
||||
|
res_model: 'res.partner', |
||||
|
view_mode: 'kanban,form,tree,activity', |
||||
|
view_type: 'kanban', |
||||
|
views: [[false, 'kanban'], [false, 'form'], [false, 'tree'], [false, 'activity']], |
||||
|
target: 'current', |
||||
|
}); |
||||
|
} |
||||
|
/** |
||||
|
* Method to search mails based on user input. |
||||
|
*/ |
||||
|
searchMail(){ |
||||
|
var value= this.root.el.querySelector(".header-search-input").value.toLowerCase() |
||||
|
var inboxItems = this.root.el.querySelectorAll(".inbox-message-item"); |
||||
|
inboxItems.forEach(item => { |
||||
|
var itemText = item.textContent.toLowerCase(); |
||||
|
item.style.display = itemText.includes(value) ? "" : "none"; |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
odooMail.template = 'OdooMail' |
||||
|
odooMail.components = { |
||||
|
MailBody, SentMail, ComposeMail,MessageView,ImportDialog |
||||
|
} |
||||
|
registry.category('actions').add('odoo_mail', odooMail); |
@ -0,0 +1,41 @@ |
|||||
|
/* @odoo-module*/ |
||||
|
import { Component } from '@odoo/owl'; |
||||
|
import { useService } from "@web/core/utils/hooks"; |
||||
|
import { useState, onMounted, markup, useRef} from "@odoo/owl"; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* MessageView component for displaying a message. |
||||
|
* @extends Component |
||||
|
*/ |
||||
|
export class MessageView extends Component { |
||||
|
setup(){ |
||||
|
this.root = useRef("root-mail") |
||||
|
this.action = useService("action"); |
||||
|
this.html_content = markup(this.props.mail.body_html) |
||||
|
this.orm = useService("orm"); |
||||
|
this.state = useState({ |
||||
|
attachments: {}, |
||||
|
data: [], |
||||
|
|
||||
|
}) |
||||
|
onMounted(this.fetch_data); |
||||
|
} |
||||
|
async fetch_data(){ |
||||
|
var self = this |
||||
|
for (const ids in this.props.mail.attachment_ids) { |
||||
|
var value = this.props.mail.attachment_ids |
||||
|
await this.orm.call("ir.attachment", "get_fields", [value], {}).then((result) => { |
||||
|
self.state.attachments = result |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
onClickImage(value){ |
||||
|
this.action.doAction({ |
||||
|
type: "ir.actions.act_url", |
||||
|
url: "/web/content/" + value+ "?download=true", |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
MessageView.template = 'MessageView' |
@ -0,0 +1,9 @@ |
|||||
|
/* @odoo-module*/ |
||||
|
import { Component } from '@odoo/owl' |
||||
|
import { useBus, useService } from "@web/core/utils/hooks"; |
||||
|
/** |
||||
|
* SentMail component for displaying sent mails. |
||||
|
* @extends Component |
||||
|
*/ |
||||
|
export class SentMail extends Component {} |
||||
|
SentMail.template = 'SentMail' |
@ -0,0 +1,16 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<templates xml:space="preserve"> |
||||
|
<t t-name="ImportDialog" owl="1"> |
||||
|
<Dialog size="'md'" title="'Attachments'"> |
||||
|
<input type="file" name="file" id="file" |
||||
|
class="form-control" t-on-change="onChangeFileInput" |
||||
|
t-ref="root" required="1"/> |
||||
|
<t t-set-slot="footer"> |
||||
|
<button class="btn btn-primary" |
||||
|
t-on-click="onFileUpload">Add </button> |
||||
|
<button class="btn" t-on-click="cancel" |
||||
|
>Cancel</button> |
||||
|
</t> |
||||
|
</Dialog> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,75 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<templates id="template" xml:space="preserve"> |
||||
|
<!-- ComposeMail template for composing a new mail --> |
||||
|
<t t-name="ComposeMail" owl="1"> |
||||
|
<div class="container" t-ref="root" |
||||
|
style="position: fixed; bottom: 3px; right: 5%; width: 30%; border: 1px solid #ccc; z-index: 1000; background: white;" |
||||
|
id="send_message" tabindex="-1" |
||||
|
aria-labelledby="send_message_label" aria-hidden="true"><br /> |
||||
|
<div class="dialog "> |
||||
|
<form class="form_submit"> |
||||
|
<div class="content-group"> |
||||
|
<div class="header d-flex justify-content-between"> |
||||
|
<h1 class="title fs-5" id="send_message_label">New Message</h1> |
||||
|
<div class="ms-auto"> |
||||
|
<button class="btn" id="minimizeButton" |
||||
|
type="button" |
||||
|
style="margin-left: 297px; margin-top: -1px;" |
||||
|
t-on-click="minimizeMail"> |
||||
|
<i class="fa fa-window-minimize" |
||||
|
aria-hidden="true"/> |
||||
|
</button> |
||||
|
<button class="btn" t-on-click="maximizeMail"> |
||||
|
<img src="/odoo_mail_management/static/src/img/expand_icon.svg" |
||||
|
class="btn-icon btn-icon-sm"/> |
||||
|
</button> |
||||
|
<button type="button" class="btn-close" |
||||
|
aria-label="Close" t-on-click="Close"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="body"> |
||||
|
<input type="email" class="form-control" |
||||
|
id="Recipient" t-model="state.recipient" |
||||
|
aria-describedby="emailHelp" required="1" |
||||
|
placeholder="To"/> |
||||
|
<br/> |
||||
|
<input type="text" class="form-control" |
||||
|
id="subject" t-model="state.subject" |
||||
|
aria-describedby="emailHelp" |
||||
|
placeholder="Subject"/> |
||||
|
<br/> |
||||
|
<textarea class="dd form-control" id="content" |
||||
|
rows="5" t-model="state.content" |
||||
|
style="height:200px"> |
||||
|
|
||||
|
</textarea> |
||||
|
|
||||
|
<br/> |
||||
|
<t t-foreach="state.attachedFiles" t-as="attachment" t-key="attachment_index"> |
||||
|
<div class="custom-input" |
||||
|
style="width: max-content;min-width:240px;height: 23px;background-color: darkgrey;font: icon;display:flex;justify-content:space-between;align-items: center;padding:0.5rem;margin:0.5rem 0;"> |
||||
|
<t t-out="attachment.name"/> |
||||
|
<button type="button" class="btn close-button" id="attachments" |
||||
|
style="margin-left: 10px;line-height:0px;" |
||||
|
t-on-click="() => this.closeInput(attachment_index)">✖</button> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div class="footer d-flex justify-content-end"> |
||||
|
<button type="submit" |
||||
|
style="border-radius: 15px; width: 85px;" |
||||
|
class="btn btn-primary" |
||||
|
t-on-click="sentMail">Send</button> |
||||
|
<div class="image-upload" |
||||
|
t-on-click="attachmentAction"> |
||||
|
<label> |
||||
|
<img src="odoo_mail_management/static/src/img/attachment.svg"/> |
||||
|
</label> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,80 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<templates id="template" xml:space="preserve"> |
||||
|
<!-- MailBody template for displaying individual mail items in the inbox --> |
||||
|
<t t-name="MailBody" owl="1"> |
||||
|
<div class="inbox-message-item message-default-unread" |
||||
|
data-id="' + name.id + '" t-ref="root"> |
||||
|
<div class="checkbox" style="margin-right: -12px;"> |
||||
|
<button class="btn"> |
||||
|
<input type="checkbox" id="checkbox" |
||||
|
data-id="' + name.id + '" |
||||
|
class="checkbox checkbox_func mail_check_box" |
||||
|
t-on-click="onClickSelect"> |
||||
|
</input> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div> |
||||
|
<button class="btn star" data-id="' + name.id + '" style="margin: 0;" |
||||
|
t-on-click="starMail"> |
||||
|
<img t-if="!state.starred" |
||||
|
src="/odoo_mail_management/static/src/img/star_border_black_24dp.svg" |
||||
|
alt="Not starred" data-id="' + name.id + '" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover message-btn-icon" |
||||
|
id="not_starred"/> |
||||
|
<img t-else="" |
||||
|
src="/odoo_mail_management/static/src/img/yellow_star.svg" |
||||
|
alt="Not starred" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover message-btn-icon" |
||||
|
id="starred"/> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div class="message-default" data-id="' + name.id + '" |
||||
|
t-on-click="openMail"> |
||||
|
<div class="message-sender message-content"> |
||||
|
<span t-out="props.mail.email_to"/> |
||||
|
</div> |
||||
|
<div class="message-subject message-content"> |
||||
|
<span t-out="props.mail.description"/> |
||||
|
</div> |
||||
|
<div class="message-seperator message-content">-</div> |
||||
|
<div class="message-body message-content"> |
||||
|
<span t-out="html_content"/> |
||||
|
</div> |
||||
|
<div class="gap message-content"> </div> |
||||
|
<div class="message-date center-text"> |
||||
|
<span style="margin-left: 500px;" t-out="props.mail.date"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="message-group-hidden"> |
||||
|
<div class="inbox-message-item-options"> |
||||
|
<button class="btn"> |
||||
|
<img t-if="props.mailType !== 'archive'" |
||||
|
src="/odoo_mail_management/static/src/img/archive_black_24dp.svg" |
||||
|
alt="Archive" data-id="' + name.id + '" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover" |
||||
|
id="archive" t-on-click="archiveMail"/> |
||||
|
<img t-elif="props.mailType == 'archive'" |
||||
|
src="/odoo_mail_management/static/src/img/unarchive_FILL1_wght400_GRAD0_opsz48.svg" |
||||
|
alt="Archive" data-id="' + name.id + '" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover" |
||||
|
id="archive" t-on-click="unArchive"/> |
||||
|
</button> |
||||
|
<button class="btn"> |
||||
|
<img src="/odoo_mail_management/static/src/img/delete_black_24dp.svg" |
||||
|
alt="Delete" data-id="' + name.id + '" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover" |
||||
|
id="delete" t-on-click="deleteMail"/> |
||||
|
</button> |
||||
|
<button class="btn"> |
||||
|
<img t-if="props.mailType == 'outbox'" |
||||
|
src="/odoo_mail_management/static/src/img/refresh_black_24dp.svg" |
||||
|
alt="Retry" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover" |
||||
|
id="retry" |
||||
|
t-on-click="resendMail"/> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,262 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<templates id="tmp" xml:space="preserve"> |
||||
|
<!-- OdooMail template for the main application --> |
||||
|
<t t-name="OdooMail" owl="1"> |
||||
|
<div class="odoo_mails" t-ref="root"> |
||||
|
<div class="body-wrapper"> |
||||
|
<!-- HEADER --> |
||||
|
<header class="head"> |
||||
|
<div class="header-group"> |
||||
|
<img t-attf-src="data:image/png;base64,{{mailState.loadLogo}}" |
||||
|
style="width:25%"/> |
||||
|
</div> |
||||
|
<form class="header-search" action=""> |
||||
|
<div class="icons"> |
||||
|
<button id="js-header-search" |
||||
|
class="btn btn-nofill tooltip" |
||||
|
data-info="Search"> |
||||
|
<img src="/odoo_mail_management/static/src/img/search_black_24dp.svg" |
||||
|
alt="Search" |
||||
|
class="btn-icon btn-icon-alt"/> |
||||
|
</button> |
||||
|
</div> |
||||
|
<input type="search" class="header-search-input" |
||||
|
placeholder="Search mail" t-on-input="searchMail"/> |
||||
|
</form> |
||||
|
</header> |
||||
|
<!-- LEFT SIDEBAR --> |
||||
|
<section class="left-sidebar"> |
||||
|
<div class="left-sidebar-compose"> |
||||
|
<button class="sidebar-btn-compose compose" |
||||
|
t-on-click="composeMail"> |
||||
|
<img src="/odoo_mail_management/static/src/img/edit_square_FILL0_wght400_GRAD0_opsz48.svg" |
||||
|
alt="Compose a new email" |
||||
|
class="sidebar-btn-compose-icon"/> |
||||
|
<span class="sidebar-btn-compose-title">Compose</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div class="left-siderbar-label"> |
||||
|
<ul class="labels category-item-list"> |
||||
|
<li class="category-item active all_mail" |
||||
|
id="all_mail" t-on-click="allMailView"> |
||||
|
<div t-on-click="allMailView"> |
||||
|
<svg class="category-item-icon" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
height="24px" viewBox="0 0 24 24" |
||||
|
width="24px" fill="#000000"> |
||||
|
<path d="M0 0h24v24H0V0z" fill="none"/> |
||||
|
<path |
||||
|
d="M19 3H4.99c-1.11 0-1.98.89-1.98 2L3 19c0 1.1.88 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.11-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V5H19v10z"/> |
||||
|
</svg> |
||||
|
<span class="category-item-title " |
||||
|
t-on-click="allMailView">All mail |
||||
|
</span> |
||||
|
</div> |
||||
|
<span class="category-item-number all_count" |
||||
|
t-out="mailState.getCount.all_count"/> |
||||
|
</li> |
||||
|
<li class="category-item sent" id="sent" |
||||
|
t-on-click="sentMail"> |
||||
|
<div> |
||||
|
<svg class="category-item-icon" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
height="24px" viewBox="0 0 24 24" |
||||
|
width="24px" fill="#000000"> |
||||
|
<path d="M0 0h24v24H0z" fill="none"/> |
||||
|
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/> |
||||
|
</svg> |
||||
|
<span class="category-item-title ">Sent</span> |
||||
|
</div> |
||||
|
<span class="category-item-number sent_count" |
||||
|
t-out="mailState.getCount.sent_count"/> |
||||
|
</li> |
||||
|
<li class="category-item sent-mail" id="starred_mails" |
||||
|
t-on-click="starredMail"> |
||||
|
<div> |
||||
|
<svg class="category-item-icon" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
height="24px" viewBox="0 0 24 24" |
||||
|
width="24px" fill="#000000"> |
||||
|
<path d="M0 0h24v24H0z" fill="none"/> |
||||
|
<path d="M0 0h24v24H0z" fill="none"/> |
||||
|
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/> |
||||
|
</svg> |
||||
|
<span class="category-item-title">Starred |
||||
|
</span> |
||||
|
</div> |
||||
|
<span class="category-item-number starred_count" |
||||
|
t-out="mailState.getCount.starred_count"/> |
||||
|
</li> |
||||
|
<li class="category-item archieved-mail" id="archived_mails" |
||||
|
t-on-click="archivedMail"> |
||||
|
<div> |
||||
|
<svg class="category-item-icon" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
height="24px" viewBox="0 0 24 24" |
||||
|
width="24px" fill="#000000"> |
||||
|
<path d="M0 0h24v24H0z" fill="none"/> |
||||
|
<path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z"/> |
||||
|
</svg> |
||||
|
<span class="category-item-title">Archived |
||||
|
</span> |
||||
|
</div> |
||||
|
<span class="category-item-number archived_count" |
||||
|
t-out="mailState.getCount.archived_count"/> |
||||
|
</li> |
||||
|
<li class="category-item outbox" id="outbox" |
||||
|
t-on-click="outboxMailView"> |
||||
|
<div> |
||||
|
<svg class="category-item-icon" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
height="48" |
||||
|
viewBox="0 96 960 960" width="48"> |
||||
|
<path d="M453 634V445l-79 79-43-43 152-152 152 152-43 43-79-79v189h-60ZM180 936q-24 0-42-18t-18-42V276q0-24 18-42t42-18h600q24 0 42 18t18 42v600q0 24-18 42t-42 18H180Zm300-173q41 0 74-23.5t56-59.5h170V276H180v404h170q23 36 56 59.5t74 23.5Z"/> |
||||
|
</svg> |
||||
|
<span class="category-item-title">Outbox</span> |
||||
|
</div> |
||||
|
<span class="category-item-number outbox_count" |
||||
|
t-out="mailState.getCount.outbox_count"/> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</section> |
||||
|
<!-- BODY --> |
||||
|
<section class="inbox mail_inbox"> |
||||
|
<!-- MAIL --> |
||||
|
<div class="inbox-menu"> |
||||
|
<div class="inbox-menu-group"> |
||||
|
<div class="inbox-btn-group"> |
||||
|
<button class="btn-alt checkbox" |
||||
|
style="margin-top:6px;"> |
||||
|
<input type="checkbox" id="checkall" |
||||
|
t-on-click="onClickSelectAll"/> |
||||
|
</button> |
||||
|
</div> |
||||
|
<button class="btn refresh" t-on-click="refreshPage"> |
||||
|
<img src="/odoo_mail_management/static/src/img/refresh_black_24dp.svg" |
||||
|
alt="Refresh" |
||||
|
class="btn-icon btn-icon-sm btn-icon-alt btn-icon-hover"/> |
||||
|
</button> |
||||
|
<button class="btn delete_checked" |
||||
|
t-on-click="deleteMail"> |
||||
|
<img src="/odoo_mail_management/static/src/img/delete_black_24dp.svg" |
||||
|
alt="Delete" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover checkbox_delete"/> |
||||
|
</button> |
||||
|
<button class="btn archive_checked" |
||||
|
t-on-click="archiveMail"> |
||||
|
<img src="/odoo_mail_management/static/src/img/archive_black_24dp.svg" |
||||
|
alt="archive" |
||||
|
class="btn-icon-sm btn-icon-alt btn-icon-hover checkbox_archive"/> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="inbox-container"> |
||||
|
<div class="inbox-category"> |
||||
|
<div id="ctg-primary" |
||||
|
class="inbox-category-item active"> |
||||
|
<svg class="inbox-category-icon btn-icon btn-icon-sm btn-icon-alt active" |
||||
|
xmlns="http://www.w3.org/2000/svg" |
||||
|
height="24px" |
||||
|
viewBox="0 0 24 24" width="24px" |
||||
|
fill="#000000"> |
||||
|
<path d="M0 0h24v24H0V0z" fill="none"/> |
||||
|
<path d="M19 3H4.99c-1.11 0-1.98.89-1.98 2L3 19c0 1.1.88 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.11-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V5H19v10z"/> |
||||
|
</svg> |
||||
|
<span class="inbox-category-title">Primary</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- MAIL CONTENT --> |
||||
|
<div class="content"> |
||||
|
<t t-if="mailState.mode == 'tree'"> |
||||
|
<MailBody t-foreach="mailState.loadMail" |
||||
|
t-as="mail" t-key="mail_index" |
||||
|
mail="mail" t-props="mailProps"/> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<MessageView mail="mailState.formData"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<!-- RIGHT SIDEBAR --> |
||||
|
<section class="app-container"> |
||||
|
<div class="app-group"> |
||||
|
<div class="app-item"> |
||||
|
<button class="btn google_calender" |
||||
|
t-on-click="redirectCalender"> |
||||
|
<img src="/odoo_mail_management/static/src/img/calendar_month_FILL0_wght400_GRAD0_opsz48.svg" |
||||
|
alt="Calendar" |
||||
|
class="btn-icon btn-icon-sm"/> |
||||
|
</button> |
||||
|
<p t-on-click="redirectCalender">Calendar</p> |
||||
|
</div> |
||||
|
<div class="app-item"> |
||||
|
<button class="btn keep_note" |
||||
|
t-on-click="redirectNote"> |
||||
|
<img src="/odoo_mail_management/static/src/img/note_FILL0_wght400_GRAD0_opsz48.svg" |
||||
|
alt="Keep" |
||||
|
class="btn-icon btn-icon-sm"/> |
||||
|
</button> |
||||
|
<p style="margin-left: 4px;" t-on-click="redirectNote">Notes</p> |
||||
|
</div> |
||||
|
<div class="app-item" style="margin-top: -13px;"> |
||||
|
<button class=" btn contacts" |
||||
|
t-on-click="redirectContacts"> |
||||
|
<img src="/odoo_mail_management/static/src/img/contact_page_FILL0_wght400_GRAD0_opsz48.svg" |
||||
|
alt="Contacts" |
||||
|
class="btn-icon btn-icon-sm"/> |
||||
|
</button> |
||||
|
<p t-on-click="redirectContacts">Contacts</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<!-- large modal--> |
||||
|
<div class="modal fade" id="large_modal" tabindex="-1" |
||||
|
aria-labelledby="send_message_label" aria-hidden="true"> |
||||
|
<div class="modal-dialog modal-xl"> |
||||
|
<div class="modal-content large-modal"> |
||||
|
<form class="large_form_submit"> |
||||
|
<div class="modal-header"> |
||||
|
<h1 class="modal-title fs-5" |
||||
|
id="send_message_label">New Message |
||||
|
</h1> |
||||
|
<button type="button" class="btn-close" |
||||
|
data-bs-dismiss="modal" |
||||
|
aria-label="Close"/> |
||||
|
</div> |
||||
|
<div class="modal-body"> |
||||
|
<input type="email" class="form-control" |
||||
|
id="l_Recipient" |
||||
|
aria-describedby="emailHelp" |
||||
|
required="1" placeholder="To"/> |
||||
|
<br/> |
||||
|
<input type="text" class="form-control" |
||||
|
id="l_subject" |
||||
|
aria-describedby="emailHelp" |
||||
|
placeholder="Subject"/> |
||||
|
<br/> |
||||
|
<textarea class="form-control" id="l_content" |
||||
|
rows="6"/> |
||||
|
</div> |
||||
|
<div class="modal-footer"> |
||||
|
<button type="submit" |
||||
|
style="border-radius: 15px; width: 85px;" |
||||
|
class="btn btn-primary" |
||||
|
t-on-click="sentMail">Send |
||||
|
</button> |
||||
|
<div class="image-upload"> |
||||
|
<label for="file-input"> |
||||
|
<img src="/odoo_mail_management/static/src/img/attachment.svg"/> |
||||
|
</label> |
||||
|
<input id="file-input" type="file"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,59 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<templates id="tmp" xml:space="preserve"> |
||||
|
<!-- MessageView template for displaying a single mail message --> |
||||
|
<t t-name="MessageView" owl="1"> |
||||
|
<div class="message" t-ref="root-mail"> |
||||
|
<h4 t-out="props.mail.description" style="margin-right: auto;"/> |
||||
|
<br/> |
||||
|
<div> |
||||
|
<strong>From:</strong> |
||||
|
<span t-out="props.mail.email_from"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<strong>To:</strong> |
||||
|
<span t-out="props.mail.email_to"/> |
||||
|
</div> |
||||
|
<br/> |
||||
|
<div> |
||||
|
<t t-out="html_content"/> |
||||
|
</div> |
||||
|
<div style="display: flex; gap: 1rem; flex-wrap: wrap; "> |
||||
|
<t t-foreach="this.state.attachments" t-as="data" t-key="data_index"> |
||||
|
<div t-if="data.mimetype == 'image/jpeg' || data.mimetype == 'image/png' || data.mimetype == 'image/gif' || data.mimetype == 'image/svg+xml' || data.mimetype == 'image/webp'"> |
||||
|
<div class="row"> |
||||
|
<div class="img-container" style=""> |
||||
|
<div class="hover-card" t-on-click="() => this.onClickImage(data.attachment)"> |
||||
|
<i class="fa fa-download"/> |
||||
|
</div> |
||||
|
<img class="img-fluid" style="width: 300px;height: 100px" t-att-src="'data:image/png;base64,'+data.datas" |
||||
|
alt=""/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div t-if="data.mimetype == 'application/pdf'"> |
||||
|
<div class="row bg-secondary"> |
||||
|
<div class="d-flex flex-row"> |
||||
|
<div> |
||||
|
<img class="p-2" style="width: 45px; height:45px" |
||||
|
src="/odoo_mail_management/static/src/img/pdf.png" |
||||
|
alt="PDF Preview" |
||||
|
/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<p class="mt-3" t-out="data.name"/> |
||||
|
</div> |
||||
|
<div style="width: 50px"/> |
||||
|
<div> |
||||
|
<button type="download" class="btn mt-3" |
||||
|
t-on-click="() => this.onClickImage(data.attachment)"> |
||||
|
<i class="text-black fa fa-download" aria-hidden="true"/> |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</templates> |