diff --git a/backend_theme_infinito_plus/README.rst b/backend_theme_infinito_plus/README.rst new file mode 100644 index 000000000..3926142ce --- /dev/null +++ b/backend_theme_infinito_plus/README.rst @@ -0,0 +1,47 @@ +.. 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 + +Backend Theme Infinito Plus +=========================== +* Backend Theme Infinito Plus module for Odoo 15 community editions + +Configuration +============= +* No additional configurations needed + +Company +======= +* `Cybrosys Techno Solutions `__ + +License +------- +General Public License, Version 3 (LGPL v3). +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Credits +======= +Developer: (V15) Ramees Jaman KT , Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@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 https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ + diff --git a/backend_theme_infinito_plus/__init__.py b/backend_theme_infinito_plus/__init__.py new file mode 100644 index 000000000..f644ac3ea --- /dev/null +++ b/backend_theme_infinito_plus/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import controllers +from . import models diff --git a/backend_theme_infinito_plus/__manifest__.py b/backend_theme_infinito_plus/__manifest__.py new file mode 100644 index 000000000..cd821e50a --- /dev/null +++ b/backend_theme_infinito_plus/__manifest__.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': 'Backend Theme Infinito Plus', + 'version': "15.0.1.0.0", + 'category': 'Extra Tools', + 'summary': 'The Backend Theme Infinito Is A Dynamic And Ultimate Theme' + 'For Your Odoo V15. This Theme Will Give You A New Experience ' + 'With Odoo.Main Highlight Of The Theme Is You Can Dynamically ' + 'Change The Fonts,Animations, Languages,...Etc', + 'description': """Utmost and dynamic backend theme for Odoo 15""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['web', 'backend_theme_infinito'], + 'data': [ + 'security/ir.model.access.csv' + ], + 'assets': { + 'web.assets_backend': { + 'backend_theme_infinito_plus/static/src/css/chatter.css', + 'backend_theme_infinito_plus/static/src/css/font.css', + 'backend_theme_infinito_plus/static/src/scss/animation.scss', + 'backend_theme_infinito_plus/static/src/js/AdvancedFeautres.js', + 'backend_theme_infinito_plus/static/src/js/navbar.js', + 'backend_theme_infinito_plus/static/src/js/ThemeStudioMenu.js', + 'backend_theme_infinito_plus/static/src/js/systray.js' + }, + 'web.assets_qweb': { + 'backend_theme_infinito_plus/static/src/xml/sidebar_templates.xml', + 'backend_theme_infinito_plus/static/src/xml/AddGoogleFonts_templates.xml', + 'backend_theme_infinito_plus/static/src/xml/refresh_templates.xml', + 'backend_theme_infinito_plus/static/src/xml/systray_templates.xml' + } + }, + 'images': [ + 'static/description/banner.jpg', + 'static/description/theme_screenshot.jpg', + ], + 'license': 'LGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/backend_theme_infinito_plus/controllers/__init__.py b/backend_theme_infinito_plus/controllers/__init__.py new file mode 100644 index 000000000..5813655ee --- /dev/null +++ b/backend_theme_infinito_plus/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import backend_theme_infinito_plus diff --git a/backend_theme_infinito_plus/controllers/backend_theme_infinito_plus.py b/backend_theme_infinito_plus/controllers/backend_theme_infinito_plus.py new file mode 100644 index 000000000..7d96cb13c --- /dev/null +++ b/backend_theme_infinito_plus/controllers/backend_theme_infinito_plus.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +import json +import os + +from odoo import http +from odoo.http import request +from odoo.addons.backend_theme_infinito.controllers.main import ThemeStudio +from odoo.addons.backend_theme_infinito.controllers.main import minify_css + + +class ThemeStudioPlus(ThemeStudio): + """Controller for updating the changes from infinito control panel""" + + @http.route(['/theme_studio/save_styles_plus'], type="json") + def save_styles_plus(self, new_style): + """Create Dynamic Styles css file for chat box layout""" + changed_styles = json.loads(new_style) + working_dir = os.path.dirname(os.path.realpath(__file__)) + working_dir = working_dir.replace('/controllers', '') + file_path = working_dir + '/static/src/css/chatter.css' + style_file = open(file_path, 'a') + style_file.truncate(0) + if os.stat(file_path).st_size == 0: + style_file.write('/* This file is generated automatically by ' + 'Theme Infinito Plus */\n') + style_file.write('.o_ChatWindow' + ' {\n') + for i in changed_styles[0]: + style_file.write('\t' + i + ':' + changed_styles[0][i] + ';\n') + style_file.write('}\n') + style_file.close() + minify_css(file_path) + return True + + @http.route(['/theme_studio/animation_styles'], type="json") + def animation_styles(self, style): + """ create the Dynamic css file for animation""" + animated = json.loads(style) + saved_style = animated[0] + working_dir = os.path.dirname(os.path.realpath(__file__)) + file_path = working_dir.replace('/controllers', + '/static/src/scss/animation.scss') + read_file = open(file_path, 'r') + css = read_file.read() + write_file = open(file_path, 'w') + for line in css.split('\n'): + if 'ease-in' in line: + write_file.write(css.replace(line.strip(), + 'animation:' + saved_style + ' #{$tr * .1}s ease-in !important;')) + write_file.close() + read_file.close() + + @http.route(['/theme_studio/font_style'], type="json") + def font_style(self, font_id): + """updating th e google fonts""" + font_obj = request.env['infinito.google.font'] + if font_id == 0: + font_obj.remove_fonts() + else: + font_obj.browse(font_id).set_css() + + @http.route(['/theme_studio/set_advanced_plus_data'], type="json") + def set_advanced_data_plus(self, vals): + """ save the features from theme studio""" + set_param = request.env['ir.config_parameter'].sudo().set_param + set_param('backend_theme_infinito_plus.is_refresh', + vals['infinitoRefresh']) + set_param('backend_theme_infinito_plus.chatbox_position', + vals['chatBoxPosition']) + set_param('backend_theme_infinito_plus.google_font', + vals['infinitoGoogleFont']) + if 'infinitoAnimation' in vals.keys(): + set_param('backend_theme_infinito_plus.animation_plus', + vals['infinitoAnimation']) + + @http.route(['/theme_studio/set_advanced_plus_data_user'], type="json") + def set_advanced_plus_data_user(self, vals): + """"updating the user inifnito data""" + request.env.user.write({ + 'is_refresh': vals['infinitoRefresh'], + 'chatbox_position': vals['chatBoxPosition'], + 'animation_plus': vals['infinitoAnimation'] + }) + return True + + @http.route(['/theme_studio_plus/reset_to_default_style'], type="json") + def reset_to_default_style(self): + """rest to default styles""" + working_dir = os.path.dirname(os.path.realpath(__file__)) + style_file_path = working_dir.replace('controllers', + 'static/src/css/font.css') + animation_file_path = working_dir.replace('controllers', + 'static/src/scss/animation.scss') + chat_file_path = working_dir.replace('controllers', + 'static/src/css/chatter.css') + style_file = open(style_file_path, 'w') + style_file.write('') + animation_read_file = open(animation_file_path, 'r') + animation_css = animation_read_file.read() + animation_file = open(animation_file_path, 'w') + for line in animation_css.split('\n'): + if 'ease-in' in line: + animation_file.write(animation_css.replace(line.strip(), + 'animation:' + 'infinito_kanban_shake' + ' #{$tr * .1}s ease-in !important;')) + chat_file = open(chat_file_path, 'w') + chat_file.write('') + request.env['ir.config_parameter'].sudo().set_param( + 'backend_theme_infinito_plus.is_refresh', False) + return True diff --git a/backend_theme_infinito_plus/doc/RELEASE_NOTES.md b/backend_theme_infinito_plus/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..48d56c2ff --- /dev/null +++ b/backend_theme_infinito_plus/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 05.10.2023 +#### Version 15.0.1.0.0 +#### ADD +- Initial Commit for Infinito Backend Theme Plus diff --git a/backend_theme_infinito_plus/models/__init__.py b/backend_theme_infinito_plus/models/__init__.py new file mode 100644 index 000000000..2bf29b8bb --- /dev/null +++ b/backend_theme_infinito_plus/models/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import infinito_google_font +from . import ir_http +from . import res_config_settings +from . import res_users diff --git a/backend_theme_infinito_plus/models/infinito_google_font.py b/backend_theme_infinito_plus/models/infinito_google_font.py new file mode 100644 index 000000000..f2fa53b54 --- /dev/null +++ b/backend_theme_infinito_plus/models/infinito_google_font.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +import os +import requests + +from odoo import api, fields, models, _ + + +class GoogleFont(models.Model): + """Model for storing Google fonts. + This class is used to add and manage Google fonts in the Odoo + application.""" + _name = 'infinito.google.font' + _description = 'Add Google Fonts' + + name = fields.Char(string='Name', help='Google font name') + font_url = fields.Text(string='Url', + help='Add the url for downloading the ' + 'google fons') + font = fields.Text(string='Font', help='Used for css file writing purpose') + + @api.model + def save_google_fonts(self, g_font): + """Function to store fonts in the database""" + record = self.search([('font_url', '=', g_font[1])]) + if not record: + font = self.get_css(g_font[0]) + rec = self.create({ + 'name': g_font[0], + 'font_url': g_font[1], + 'font': font + }) + rec.set_css() + + def get_css(self, name): + """get the css file of selected google font""" + headers_woff2 = { + 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' + '(KHTML, like Gecko) ' + 'Chrome/101.0.4951.41 Safari/537.36', + } + url = f'https://fonts.googleapis.com/css?family={name}&display=swap' + req = requests.get(url, timeout=5, headers=headers_woff2) + return req.content + + def set_css(self): + """open the file write the style in to the css file""" + working_dir = os.path.dirname(os.path.realpath(__file__)) + working_dir = working_dir.replace('/models', + '/static/src/css/font.css') + # open the file in write mode + with open(working_dir, 'w') as file: + style = f""" + {self.font} + * {{ + font-family: '{self.name}' !important; + }} + .fa {{ + font: normal normal normal 14px/1 FontAwesome !important;}} + .oi {{ + font-family: 'odoo_ui_icons' !important;}} + """ + file.write(style) + + @staticmethod + def remove_fonts(): + """remove the style when changing the font""" + working_dir = os.path.dirname(os.path.realpath(__file__)) + working_dir = working_dir.replace('/models', + '/static/src/css/font.css') + open(working_dir, "r") + with open(working_dir, 'w') as file: + file.write('') diff --git a/backend_theme_infinito_plus/models/ir_http.py b/backend_theme_infinito_plus/models/ir_http.py new file mode 100644 index 000000000..04b6069ae --- /dev/null +++ b/backend_theme_infinito_plus/models/ir_http.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import models + + +class IrHttp(models.AbstractModel): + """Inhering ir.http class for storing data in session.""" + _inherit = 'ir.http' + + def session_info(self): + """pass the session information """ + res = super(IrHttp, self).session_info() + get_param = self.env['ir.config_parameter'].sudo().get_param + all_langs = self.env['res.lang'].get_installed() + res['currentLang'] = \ + list(filter(lambda x: x[0] == self.env.user.lang, all_langs))[0] + res['availableLanguages'] = all_langs + if self.env.user.has_group('base.group_user'): + user_edit = get_param( + 'backend_theme_infinito.is_user_edit', default=False) + res['userEdit'] = user_edit + if user_edit: + res['infinitoRefresh'] = self.env.user.is_refresh + res['chatBoxPosition'] = self.env.user.chatbox_position + res['infinitoAnimation'] = self.env.user.animation_plus + else: + res['infinitoRefresh'] = get_param( + 'backend_theme_infinito_plus.is_refresh', default=False) + res['chatBoxPosition'] = get_param( + 'backend_theme_infinito_plus.chatbox_position', + default=False) + res['infinitoAnimation'] = get_param( + 'backend_theme_infinito_plus.animation_plus', + default=False) + res['infinitoGoogleFont'] = \ + get_param('backend_theme_infinito_plus.google_font', + default=0) + return res diff --git a/backend_theme_infinito_plus/models/res_config_settings.py b/backend_theme_infinito_plus/models/res_config_settings.py new file mode 100644 index 000000000..b4e2e9c27 --- /dev/null +++ b/backend_theme_infinito_plus/models/res_config_settings.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import api, fields, models + + +class ResConfigSettings(models.TransientModel): + """Inhering res.config.settings class for adding new fields.""" + _inherit = 'res.config.settings' + + is_refresh = fields.Boolean(string='Tree,Kanban Refresh mode Enabled', + help='To check refresh button enabled or not', + default=False) + chatbox_position = fields.Char(string='Chat box position', + help='To set chat box position') + animation_plus = fields.Char(string='Animation', + help='To set animation position') + google_font = fields.Integer(string='Google font', + help='To set google font') + + @api.model + def get_values(self): + """Get the current values for the configuration settings""" + res = super(ResConfigSettings, self).get_values() + get_param = self.env['ir.config_parameter'].sudo().get_param + res['is_refresh'] = get_param('backend_theme_infinito_plus.is_refresh', + default=False) + res['chatbox_position'] = get_param( + 'backend_theme_infinito_plus.chatbox_position') + res['animation_plus'] = get_param( + 'backend_theme_infinito_plus.animation_plus') + res['google_font'] = get_param( + 'backend_theme_infinito_plus.google_font') + return res + + @api.model + def set_values(self): + """Update the values of the configuration settings""" + set_param = self.env['ir.config_parameter'].sudo().set_param + set_param('backend_theme_infinito_plus.is_refresh', self.is_refresh) + set_param('backend_theme_infinito_plus.chatbox_position', + self.chatbox_position) + set_param('backend_theme_infinito_plus.animation_plus', + self.animation_plus) + set_param('backend_theme_infinito_plus.google_font', + self.google_font) + super(ResConfigSettings, self).set_values() diff --git a/backend_theme_infinito_plus/models/res_users.py b/backend_theme_infinito_plus/models/res_users.py new file mode 100644 index 000000000..11e6bf6d9 --- /dev/null +++ b/backend_theme_infinito_plus/models/res_users.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################### +from odoo import fields, models + + +class Users(models.Model): + """Inhering 'res.users' for adding new fields""" + _inherit = 'res.users' + + is_refresh = fields.Boolean(string='Tree,Kanban Refresh mode Enabled', + help="Refreshing feature for specific users", + default=False) + chatbox_position = fields.Char(string="ChatBox position", + help="different layouts for chatBox") + animation_plus = fields.Char(stirng="Animation", + help="Different Animations", defult='Default') diff --git a/backend_theme_infinito_plus/security/ir.model.access.csv b/backend_theme_infinito_plus/security/ir.model.access.csv new file mode 100644 index 000000000..19bc222b3 --- /dev/null +++ b/backend_theme_infinito_plus/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_infinito_google_font_user,access.infinito.google.font.user,model_infinito_google_font,base.group_user,1,1,1,1 diff --git a/backend_theme_infinito_plus/static/description/assets/hero.png b/backend_theme_infinito_plus/static/description/assets/hero.png new file mode 100644 index 000000000..a65f511e5 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/hero.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/check.png b/backend_theme_infinito_plus/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/check.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/chevron.png b/backend_theme_infinito_plus/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/chevron.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/cogs.png b/backend_theme_infinito_plus/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/cogs.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/consultation.png b/backend_theme_infinito_plus/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/consultation.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/ecom-black.png b/backend_theme_infinito_plus/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/ecom-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/education-black.png b/backend_theme_infinito_plus/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/education-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/hotel-black.png b/backend_theme_infinito_plus/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/hotel-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/license.png b/backend_theme_infinito_plus/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/license.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/lifebuoy.png b/backend_theme_infinito_plus/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/lifebuoy.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/logo.png b/backend_theme_infinito_plus/static/description/assets/icons/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/logo.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/manufacturing-black.png b/backend_theme_infinito_plus/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/manufacturing-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/pos-black.png b/backend_theme_infinito_plus/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/pos-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/puzzle.png b/backend_theme_infinito_plus/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/puzzle.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/restaurant-black.png b/backend_theme_infinito_plus/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/restaurant-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/service-black.png b/backend_theme_infinito_plus/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/service-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/trading-black.png b/backend_theme_infinito_plus/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/trading-black.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/training.png b/backend_theme_infinito_plus/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/training.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/update.png b/backend_theme_infinito_plus/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/update.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/user.png b/backend_theme_infinito_plus/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/user.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/icons/wrench.png b/backend_theme_infinito_plus/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/icons/wrench.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/screenshots/chatbox_layout.png b/backend_theme_infinito_plus/static/description/assets/screenshots/chatbox_layout.png new file mode 100644 index 000000000..e6058191f Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/screenshots/chatbox_layout.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/screenshots/gif/animation.gif b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/animation.gif new file mode 100644 index 000000000..00fb3fe5a Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/animation.gif differ diff --git a/backend_theme_infinito_plus/static/description/assets/screenshots/gif/chatbox_layout.png b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/chatbox_layout.png new file mode 100644 index 000000000..e6058191f Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/chatbox_layout.png differ diff --git a/backend_theme_infinito_plus/static/description/assets/screenshots/gif/google_font.gif b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/google_font.gif new file mode 100644 index 000000000..1e111eecb Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/google_font.gif differ diff --git a/backend_theme_infinito_plus/static/description/assets/screenshots/gif/refresh_icon.gif b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/refresh_icon.gif new file mode 100644 index 000000000..9015fecf8 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/refresh_icon.gif differ diff --git a/backend_theme_infinito_plus/static/description/assets/screenshots/gif/swtich_languages.gif b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/swtich_languages.gif new file mode 100644 index 000000000..4fbcc9ca2 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/assets/screenshots/gif/swtich_languages.gif differ diff --git a/backend_theme_infinito_plus/static/description/banner.jpg b/backend_theme_infinito_plus/static/description/banner.jpg new file mode 100644 index 000000000..5693bb632 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/banner.jpg differ diff --git a/backend_theme_infinito_plus/static/description/icon.png b/backend_theme_infinito_plus/static/description/icon.png new file mode 100644 index 000000000..ce81ff658 Binary files /dev/null and b/backend_theme_infinito_plus/static/description/icon.png differ diff --git a/backend_theme_infinito_plus/static/description/index.html b/backend_theme_infinito_plus/static/description/index.html new file mode 100644 index 000000000..ced5711d4 --- /dev/null +++ b/backend_theme_infinito_plus/static/description/index.html @@ -0,0 +1,526 @@ +
+
+
+
+ +
+
+
+ Community +
+
+
+
+
+ +
+
+
+

+ INFINITO PLUSBackend Theme +

+

+ Utmost and dynamic backend theme for Odoo 15

+
+
+ +
+
+
+ + + +
+
+
+

+ The Backend Theme Infinito Is A Dynamic And Ultimate Theme For + Your Odoo V15. + This Theme Will Give You A New Experience + With Odoo. Main Highlight Of The Theme Is You Can Dynamically + Change The Fonts, animation, Chatbox Layout,...Etc. + Moreover, it acts as a studio-based theme. + It Is A Perfect Choice For Your Odoo Backend And An Attractive + Theme For Your Odoo 15. +

+
+
+ +
+
+
+ + + +
+
+
+

+ Features

+
+
+ + +
+
+
+ +
+
+
+
+ New +
+

View Refresh

+
+
+
+
+
+
+ + + +
+
+
+

Infinito + Animation

+
+ The significant and attractive feature of the Backend Theme + Infinito is its dynamic and powerful styling. + The user can select different animation. The new Backend + Theme Infinito V15 delivers you an entirely redesigned + Kanban view + and Kanban Group View. The animated view provides a + comfortable experience for the users. +
+
+
+
+ +

Dynamic Styles

+
+
+ +

Clean Layout

+
+
+
+
+
+ +
+
+
+ + + +
+
+

+ ChatBox Layout Customization

+
+ Backend Theme Infinito V15 ensures stunning themes for your + Odoo + 15 platform. + The new chatbox layout with more customization options provides + a better experience. + The system encompasses the Left, Right, Top, Bottom positions, + user can select position from these positions. +
+
+
+ +

Bottom Left

+
+
+ +

Bottom Right

+
+
+ +

Top Right

+
+
+ +

Top Left

+
+
+
+
+ +
+
+
+ +
+
+
+

Google Font

+
+ User can customize fonts.This customization options provides a + better experience. +
+
+
+ +
+
+
+
+
+
+

Language Switching

+
+ You can switch languages easily. All added languages will be + visible on systray option from where you can select the + language. +
+
+
+ +
+
+
+ + + + +
+
+
+

+ Our Services

+
+
+
+ +
+
+ Odoo + Customization
+
+
+
+ +
+
+ Odoo + Implementation
+
+
+
+ +
+
+ Odoo + Support
+
+
+
+ +
+
+ Hire + Odoo + Developer
+
+
+
+ +
+
+ Odoo + Integration
+
+
+
+ +
+
+ Odoo + Migration
+
+
+
+ +
+
+ Odoo + Consultancy
+
+
+
+ +
+
+ Odoo + Implementation
+
+
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+
+ + +
+
+
+

+ Our Industries

+
+
+
+ +
+ Trading +
+

+ Easily + procure + and + sell your products

+
+
+
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+
+
+ +
+ Education +
+

+ A + platform for + educational management

+
+
+
+
+ +
+ Manufacturing +
+

+ Plan, + track and + schedule your operations

+
+
+
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+
+
+ +
+ Service Management +
+

+ Keep + track of + services and invoice

+
+
+
+
+ +
+ Restaurant +
+

+ Run + your bar or + restaurant methodically

+
+
+
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+
+
+ + +
+
+
+

+ Need Help?

+
+
+ + + +
+ +
+
+ +
+ +
+ +
+
+ diff --git a/backend_theme_infinito_plus/static/description/theme_screenshot.jpg b/backend_theme_infinito_plus/static/description/theme_screenshot.jpg new file mode 100644 index 000000000..3a32f118d Binary files /dev/null and b/backend_theme_infinito_plus/static/description/theme_screenshot.jpg differ diff --git a/backend_theme_infinito_plus/static/src/css/chatter.css b/backend_theme_infinito_plus/static/src/css/chatter.css new file mode 100644 index 000000000..e69de29bb diff --git a/backend_theme_infinito_plus/static/src/css/font.css b/backend_theme_infinito_plus/static/src/css/font.css new file mode 100644 index 000000000..16d126e97 --- /dev/null +++ b/backend_theme_infinito_plus/static/src/css/font.css @@ -0,0 +1,28 @@ + + /* latin-ext */ +@font-face { + font-family: 'Titan One'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/titanone/v15/mFTzWbsGxbbS_J5cQcjCmjgm6Es.woff2) format('woff2'); + unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Titan One'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/titanone/v15/mFTzWbsGxbbS_J5cQcjClDgm.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + + * { + font-family: 'Titan One' !important; + } + .fa { + font: normal normal normal 14px/1 FontAwesome !important;} + .oi { + font-family: 'odoo_ui_icons' !important;} + \ No newline at end of file diff --git a/backend_theme_infinito_plus/static/src/js/AdvancedFeautres.js b/backend_theme_infinito_plus/static/src/js/AdvancedFeautres.js new file mode 100644 index 000000000..9d79fc7d6 --- /dev/null +++ b/backend_theme_infinito_plus/static/src/js/AdvancedFeautres.js @@ -0,0 +1,165 @@ +odoo.define('backend_theme_infinito_plus.AdvancedFeatures', function (require) { + "use strict"; + var AdvancedFeatures = require('backend_theme_infinito.AdvancedFeatures'); + var session = require('web.session'); + var ajax = require('web.ajax'); + var Dialog = require('web.Dialog'); + var core = require('web.core'); + var rpc = require('web.rpc'); + var _t = core._t; + //Overriding the AdvancedFeatures component for adding new features to module + AdvancedFeatures.include({ + events: _.extend({}, AdvancedFeatures.prototype.events, { + 'change #chatBoxPosition': 'onPositionChange', + 'change #infinito_font_select': 'onFontChange', + 'click #infinito_font_select_google': '_onAddGoogleFontClick', + 'change #animatedView': 'onAnimationChange' + }), + //Initializes the Chat Widget settings. + init: function (parent, type) { + this._super.apply(this, arguments); + this.chatBoxPosition = ['Top Right', 'Top Left', 'Bottom Right', 'Bottom Left']; + this.infinitoAnimation = ['Default', 'Scale', 'Slide in']; }, + //This function is responsible for rendering the Chat Widget data and initializing the settings. + async renderData() { + this._super.apply(this, arguments); + this.chat_style = []; + rpc.query({ + model: "infinito.google.font", + method: 'search_read', + args: [], + }).then((res) =>{ + var selectElement = this.$el.find('#infinito_font_select'); + var font_id = session.infinitoGoogleFont + res.forEach(function(option){ + var newOption = $("`; + } + this.$el.find('#chatBoxPosition').html(position_content); + this.$el.find('#chatBoxPosition').val(session.chatBoxPosition); + + let animationContent = ''; + let index = 0 + for (let animation of this.infinitoAnimation) { + animationContent += ``; + index +=1; + } + this.$el.find('#animatedView').html(animationContent); + this.$el.find('#animatedView').val(session.infinitoAnimation) + this.$el.find('#navbarRefreshToggler').prop('checked', session.infinitoRefresh); + }, + //This function is responsible for saving the changes made to the Chat Widget settings. + async _SaveChanges() { + this._super.apply(this, arguments); + let vals = { + 'infinitoRefresh': this.$el.find('#navbarRefreshToggler').is(':checked'), + 'chatBoxPosition': this.$el.find('#chatBoxPosition').val(), + 'infinitoAnimation': this.$el.find('#animatedView').val(), + 'animations' : this.animated_id, + 'infinitoGoogleFont' : this.font_id ? this.font_id : 0, + }; + var chat_style = this.chat_style; + session.chatBoxPosition = vals.chatBoxPosition; + session.infinitoAnimation = vals.infinitoAnimation; + session.infinitoRefresh = vals.infinitoRefresh + var style = []; + if (vals.animations === '1') { + style.push('infinito_kanban_scale'); + } else if (vals.animations === '0') { + style.push('infinito_kanban_shake'); + } else if (vals.animations === '2') { + style.push('infinito_kanban_slide_in'); + } + if (style.length != 0){ + await ajax.jsonRpc('/theme_studio/animation_styles', 'call', { 'style': JSON.stringify(style)}); + } + if (chat_style.length !== 0) { + await ajax.jsonRpc('/theme_studio/save_styles_plus', 'call', { 'new_style': JSON.stringify(chat_style) }); + } + if (vals.infinitoGoogleFont.length !== 0){ + await ajax.jsonRpc('/theme_studio/font_style', 'call', { font_id: vals.infinitoGoogleFont });} + if (this.type == 'global'){ + await ajax.jsonRpc('/theme_studio/set_advanced_plus_data', 'call', {vals}) + } + if(this.type == 'user'){ + await ajax.jsonRpc('/theme_studio/set_advanced_plus_data_user', 'call', {vals}).then((_) => { + this._Close(); }) + } + }, + //ChatBox position change function. + async onPositionChange(ev) { + let val = ev.target.value; + const positionMap = { + 'Top Right': { 'top': '10px', 'left': 'auto' }, + 'Top Left': { 'top': '10px', 'left': '10px', 'right': 'auto' }, + 'Bottom Left': { 'left': '10px', 'bottom': '10px', 'top': 'auto', 'right': 'auto' }, + 'Bottom Right': { 'right': '10px', 'bottom': '10px', 'top': 'auto', 'left': 'auto' } + }; + this.chat_style = [positionMap[val]] || []; + }, + //Animation change function. + onAnimationChange: function(ev) { + this.animated_id = ev.target.value; + }, + //Font change function. + onFontChange: function(ev){ + let options = ev.target.options + let selected = this.$(options[options.selectedIndex]) + if(selected.hasClass('add-font')){ + this.addGoogleFont() + } + else if(selected.hasClass('system-font')){ + this.font_id = 0} + else { + this.font_id = parseInt(selected.val())} + }, + //AddGoogleFont - Function to open a dialog for adding a Google Font and save it to the backend. + addGoogleFont: function(){ + const dialog = new Dialog(this, { + title: _t("Add a Google Font"), + $content: $(core.qweb.render('backend_theme_infinito_plus.dialog.addGoogleFont')), + // open a wizard for selecting google font + buttons: [ + { text: _t("Save & Reload"), + classes: 'btn-primary', + click: async () => { + const inputEl = dialog.el.querySelector('.o_input_google_font'); + let m = inputEl.value.match(/\bfamily=([\w+]+)/); + // validation of link + if(m){ + const font = m[1].replace(/\+/g, ' '); + var self = this; + rpc.query({ + model: "infinito.google.font", + method: 'save_google_fonts', + args: [[font,m.input]], + }).then(function (data) { + window.location.reload(); + }); + } + }, + }, + { + text: _t("Discard"), + close: true,},], + }); + dialog.open(); + } + }); + return AdvancedFeatures; +}); diff --git a/backend_theme_infinito_plus/static/src/js/ThemeStudioMenu.js b/backend_theme_infinito_plus/static/src/js/ThemeStudioMenu.js new file mode 100644 index 000000000..ae9db2885 --- /dev/null +++ b/backend_theme_infinito_plus/static/src/js/ThemeStudioMenu.js @@ -0,0 +1,12 @@ +odoo.define('backend_theme_infinito_plus.ThemeStudioMenu', function (require) { + "use strict"; + var ThemeStudioMenu = require('backend_theme_infinito.ThemeStudioMenu'); + var ajax = require('web.ajax'); + ThemeStudioMenu.include({ + //Reset all the features. + _onResetClick: async function(ev){ + this._super.apply(this, arguments); + await ajax.jsonRpc('/theme_studio_plus/reset_to_default_style', 'call', {}); + }, + }) +}); diff --git a/backend_theme_infinito_plus/static/src/js/navbar.js b/backend_theme_infinito_plus/static/src/js/navbar.js new file mode 100644 index 000000000..5faacbb8a --- /dev/null +++ b/backend_theme_infinito_plus/static/src/js/navbar.js @@ -0,0 +1,15 @@ +/** @odoo-module **/ +import ControlPanel from "web.ControlPanel"; +import { patch } from 'web.utils'; +var session = require('web.session'); +//Patching the ControlPanel for adding new clicks +patch(ControlPanel.prototype, 'backend_theme_infinito_plus/static/src/js/navbar.js', { + //Function to refresh the model data. + onRefreshClick(){ + this.model.dispatch() + }, + //Function for enable and disable the refresh button in navbar. + RefreshOn(){ + return session.infinitoRefresh; + } +}) \ No newline at end of file diff --git a/backend_theme_infinito_plus/static/src/js/systray.js b/backend_theme_infinito_plus/static/src/js/systray.js new file mode 100644 index 000000000..bba8c14d4 --- /dev/null +++ b/backend_theme_infinito_plus/static/src/js/systray.js @@ -0,0 +1,32 @@ +/** @odoo-module **/ +import SystrayMenu from 'web.SystrayMenu'; +import Widget from 'web.Widget'; +import session from "web.session"; +var rpc = require('web.rpc'); +var ExampleWidget = Widget.extend({ + template: 'LanguageSwitch', + events: { + 'click .dropdown-menu': '_onLanguageSelect', + }, +// Initializes the object by copying the current language and available languages +// from the session object. + init: function () { + this.currentLang = [session.currentLang[0], session.currentLang[1]]; + this.availableLanguages = session.availableLanguages + }, +// Handle the selection of language. + _onLanguageSelect: function (ev) { + var lang = ev.target.dataset.langKey + rpc.query({ + model: 'res.users', + method: 'write', + args: [[session.uid], { + "lang": lang + }], + }).then(() => { + window.location.reload(); + }); + } +}); +SystrayMenu.Items.push(ExampleWidget); +export default ExampleWidget; \ No newline at end of file diff --git a/backend_theme_infinito_plus/static/src/scss/animation.scss b/backend_theme_infinito_plus/static/src/scss/animation.scss new file mode 100644 index 000000000..0fe7ff975 --- /dev/null +++ b/backend_theme_infinito_plus/static/src/scss/animation.scss @@ -0,0 +1,49 @@ +.o_kanban_view { + .oe_kanban_card, .o_kanban_record { + @for $tr from 1 through 80 { + &:nth-child(#{$tr}) { + animation:infinito_kanban_shake #{$tr * .1}s ease-in !important; + } + } + } +} + +@keyframes infinito_kanban_slide_in { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(0); } +} +@keyframes infinito_kanban_scale { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-10px); } +} +@keyframes infinito_kanban_shake { + 0% { + transform: rotate(-5deg); + opacity: 0; + } + + 20% { + transform: rotate(5deg); + } + + 40% { + transform: rotate(-3deg); + } + + 60% { + transform: rotate(3deg); + } + + 80% { + transform: rotate(-1deg); + } + + 90% { + transform: rotate(1deg); + } + + 100% { + transform: rotate(0deg); + opacity: 1; + } +} diff --git a/backend_theme_infinito_plus/static/src/xml/AddGoogleFonts_templates.xml b/backend_theme_infinito_plus/static/src/xml/AddGoogleFonts_templates.xml new file mode 100644 index 000000000..3ff700d64 --- /dev/null +++ b/backend_theme_infinito_plus/static/src/xml/AddGoogleFonts_templates.xml @@ -0,0 +1,17 @@ + + + +
+
+ +
+