@ -0,0 +1,45 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg |
||||
|
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html |
||||
|
:alt: License: LGPL-3 |
||||
|
|
||||
|
Backend Theme Infinito |
||||
|
====================== |
||||
|
* Backend Theme Infinito module for Odoo 17 community editions |
||||
|
|
||||
|
Installation |
||||
|
============ |
||||
|
- www.odoo.com/documentation/17.0/setup/install.html |
||||
|
- Install our custom addon |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
General Public License, Version 3 (LGPL v3). |
||||
|
(https://www.odoo.com/documentation/user/16.0/legal/licenses/licenses.html) |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* 'Cybrosys Techno Solutions <https://cybrosys.com/>'__ |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* 'Cybrosys Techno Solutions <https://cybrosys.com/>'__ |
||||
|
Author : Farseen, Musthafa , Gokul , Ajith @Cybrosys |
||||
|
|
||||
|
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 |
||||
|
========== |
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
|
||||
|
For support and more information, please visit https://www.cybrosys.com |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
||||
|
|
@ -0,0 +1,24 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from .icon_hooks import icons_post_init_hook |
||||
|
from . import controllers |
||||
|
from . import models |
@ -0,0 +1,98 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
{ |
||||
|
"name": "Infinito Backend Theme", |
||||
|
"description": """Utmost and dynamic backend theme for Odoo 17""", |
||||
|
"summary": """The Backend Theme Infinito Is A Dynamic And Ultimate Theme |
||||
|
For Your Odoo V17. This Theme Will Give You A New Experience With Odoo. |
||||
|
Main Highlight Of The Theme Is You Can Dynamically Change The Colors, |
||||
|
Views, Buttons, Different Types Sidebar...Etc""", |
||||
|
"category": "Themes/Backend", |
||||
|
"version": "17.0.1.0.0", |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'website': "https://www.cybrosys.com", |
||||
|
"depends": ['web', 'mail'], |
||||
|
"data": [ |
||||
|
'views/assets.xml', |
||||
|
'views/layout.xml', |
||||
|
'views/base_pwa.xml', |
||||
|
'views/icons.xml', |
||||
|
'views/editor_client_action.xml', |
||||
|
], |
||||
|
'assets': { |
||||
|
'web._assets_primary_variables': { |
||||
|
'backend_theme_infinito/static/src/scss/theme_variables.scss', |
||||
|
}, |
||||
|
'web.assets_backend': { |
||||
|
'/backend_theme_infinito/static/src/xml/systray.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/views.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/theme_editor.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/studio_elements.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/ThemeStudioMenu.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/style_add.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/sidebar.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/sidebar_simple_editor.xml', |
||||
|
'/backend_theme_infinito/static/src/xml/MenuBookmark.xml', |
||||
|
'https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap', |
||||
|
'/backend_theme_infinito/static/src/css/style.css', |
||||
|
'/backend_theme_infinito/static/src/css/loaders.css', |
||||
|
'backend_theme_infinito/static/src/scss/sidebar.scss', |
||||
|
'backend_theme_infinito/static/src/scss/responsive.scss', |
||||
|
'backend_theme_infinito/static/src/scss/theme_date_picker.scss', |
||||
|
'backend_theme_infinito/static/src/scss/theme_styles.scss', |
||||
|
'backend_theme_infinito/static/src/scss/theme_rtl.scss', |
||||
|
'backend_theme_infinito/static/src/scss/app_menu.scss', |
||||
|
'backend_theme_infinito/static/src/scss/extra_styles.scss', |
||||
|
'backend_theme_infinito/static/src/scss/views.scss', |
||||
|
'/backend_theme_infinito/static/src/js/checkService.js', |
||||
|
'/backend_theme_infinito/static/src/js/systray.js', |
||||
|
'/backend_theme_infinito/static/src/js/loaders.js', |
||||
|
'/backend_theme_infinito/static/src/js/editor_client_action.js', |
||||
|
'/backend_theme_infinito/static/src/js/ThemeStudioWidget.js', |
||||
|
'/backend_theme_infinito/static/src/js/Tool.js', |
||||
|
'/backend_theme_infinito/static/src/js/VisualEditor.js', |
||||
|
'/backend_theme_infinito/static/src/js/change.js', |
||||
|
'/backend_theme_infinito/static/src/js/style_add.js', |
||||
|
'/backend_theme_infinito/static/src/js/sidebar.js', |
||||
|
'/backend_theme_infinito/static/src/js/navbar.js', |
||||
|
'/backend_theme_infinito/static/src/js/theme_editor_sidebar.js', |
||||
|
'/backend_theme_infinito/static/src/js/recentApps.js', |
||||
|
'/backend_theme_infinito/static/src/js/editor_menu.js', |
||||
|
'/backend_theme_infinito/static/src/js/timepicker.js', |
||||
|
'/backend_theme_infinito/static/src/js/MenuBookmark.js', |
||||
|
'/backend_theme_infinito/static/src/js/SaveChanges.js', |
||||
|
'/backend_theme_infinito/static/src/js/ThemeStudioMenu.js', |
||||
|
'/backend_theme_infinito/static/src/js/variables.js', |
||||
|
}, |
||||
|
}, |
||||
|
'post_init_hook': 'icons_post_init_hook', |
||||
|
'images': [ |
||||
|
'static/description/banner.jpg', |
||||
|
'static/description/theme_screenshot.jpg', |
||||
|
], |
||||
|
'license': 'LGPL-3', |
||||
|
'installable': True, |
||||
|
'application': False, |
||||
|
'auto_install': False, |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import base_pwa |
||||
|
from . import main |
@ -0,0 +1,68 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
import json |
||||
|
from odoo import http |
||||
|
from odoo.http import request |
||||
|
|
||||
|
|
||||
|
class BasePwa(http.Controller): |
||||
|
""" |
||||
|
Controller class for handling Progressive Web App (PWA) related functionalities. |
||||
|
""" |
||||
|
|
||||
|
def pwa_data(self): |
||||
|
""" |
||||
|
Define the data required for the PWA manifest file. |
||||
|
|
||||
|
Returns: |
||||
|
dict: Dictionary containing PWA manifest data. |
||||
|
""" |
||||
|
return { |
||||
|
'short_name': 'Odoo', |
||||
|
'name': 'Odoo-infinito', |
||||
|
'description': 'PWA provided by backend theme infinito', |
||||
|
'icons': [ |
||||
|
{ |
||||
|
'src': '/backend_theme_infinito/static/src/img/menu.png', |
||||
|
'type': 'image/png', |
||||
|
'sizes': '144x144', |
||||
|
'purpose': 'any maskable' |
||||
|
}, |
||||
|
], |
||||
|
'start_url': 'http://cybrosys:8015/web', |
||||
|
'background_color': 'white', |
||||
|
'display': 'standalone', |
||||
|
'theme_color': 'white', |
||||
|
} |
||||
|
|
||||
|
@http.route('/manifest/webmanifest', type='http', |
||||
|
auth='public', website=True, sitemap=False) |
||||
|
def base_pwa_data(self): |
||||
|
""" |
||||
|
Endpoint for serving the PWA manifest file. |
||||
|
|
||||
|
Returns: |
||||
|
odoo.http.Response: HTTP response containing the PWA manifest data. |
||||
|
""" |
||||
|
return request.make_response(json.dumps(self.pwa_data()), |
||||
|
headers=[('Content-Type', |
||||
|
'application/json;charset=utf-8')]) |
@ -0,0 +1,585 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
import json |
||||
|
import os |
||||
|
import re |
||||
|
|
||||
|
from odoo import http |
||||
|
from odoo.http import request |
||||
|
|
||||
|
|
||||
|
def minify_css(path): |
||||
|
""" |
||||
|
Minify CSS file located at the specified path. |
||||
|
|
||||
|
Parameters: |
||||
|
path (str): The file path to the CSS file to be minified. |
||||
|
|
||||
|
Returns: |
||||
|
None |
||||
|
|
||||
|
This function reads the CSS file specified by the given path, removes |
||||
|
comments,excess whitespace, and redundant CSS properties. It then writes |
||||
|
the minified CSS back to the same file, overwriting its previous contents. |
||||
|
|
||||
|
Note: |
||||
|
This function modifies the CSS file in place. |
||||
|
|
||||
|
Example: |
||||
|
minify_css('/path/to/style.css') |
||||
|
""" |
||||
|
with open(path, 'r') as f: |
||||
|
css = f.read() |
||||
|
css = re.sub(r'/\*[\s\S]*?\*/', "", css) |
||||
|
css = re.sub(r'url\((["\'])([^)]*)\1\)', r'url(\2)', css) |
||||
|
css = re.sub(r'\s+', ' ', css) |
||||
|
css = re.sub(r'#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)', r'#\1\2\3\4', |
||||
|
css) |
||||
|
css = re.sub(r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css) |
||||
|
rules = re.findall(r'([^{]+){([^}]*)}', css) |
||||
|
selectors_list = [] |
||||
|
css_values = {} |
||||
|
for rule in rules: |
||||
|
selector = rule[0] |
||||
|
content = rule[1] |
||||
|
if selector not in selectors_list: |
||||
|
selectors_list.append(selector) |
||||
|
css_values[selector] = content |
||||
|
else: |
||||
|
css_values[selector] = css_values[selector] + content |
||||
|
with open(path, 'w') as f: |
||||
|
selector_dict = {} |
||||
|
for selector in selectors_list: |
||||
|
rule = css_values[selector].split(';') |
||||
|
dict_rule = {} |
||||
|
for r in rule: |
||||
|
if r: |
||||
|
split_rule = r.split(':') |
||||
|
if len(split_rule) == 2: |
||||
|
dict_rule[split_rule[0].strip()] = split_rule[1] |
||||
|
selector_dict[selector] = dict_rule |
||||
|
f.write('/* This Styles are generated automatically by Theme Studio' |
||||
|
' */\n') |
||||
|
for selector in selector_dict: |
||||
|
f.write(selector + '{') |
||||
|
for rule_data in selector_dict[selector]: |
||||
|
if rule_data != 'pointer-events': |
||||
|
if selector_dict[selector][rule_data].find( |
||||
|
'!important') == -1: |
||||
|
f.write(rule_data + ':' + |
||||
|
selector_dict[selector][rule_data] + |
||||
|
' !important;') |
||||
|
else: |
||||
|
f.write(rule_data + ':' + |
||||
|
selector_dict[selector][rule_data] + ';') |
||||
|
f.write('}') |
||||
|
|
||||
|
|
||||
|
class ThemeStudio(http.Controller): |
||||
|
""" |
||||
|
Controller class for managing themes in a web application. |
||||
|
|
||||
|
This controller handles requests related to managing themes, such as |
||||
|
applying themes, customizing themes, and saving theme settings. |
||||
|
""" |
||||
|
|
||||
|
@http.route(['/theme_studio/save_styles'], type="json") |
||||
|
def save_styles(self, kwargs): |
||||
|
""" |
||||
|
Save dynamic styles to a CSS file. |
||||
|
|
||||
|
Parameters: |
||||
|
kwargs (dict): A dictionary containing the changed_styles and |
||||
|
object_class. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the styles are successfully saved, otherwise False. |
||||
|
|
||||
|
This function takes the changed_styles and object_class from the |
||||
|
kwargs dictionary and saves them to a CSS file. It appends the styles |
||||
|
to an existing file or creates a new file if it doesn't exist. |
||||
|
After saving the styles, it minifies the CSS file. |
||||
|
|
||||
|
Example: |
||||
|
To save styles for a specific object class: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import save_styles |
||||
|
|
||||
|
save_styles({ |
||||
|
'changed_styles': { |
||||
|
'color': 'red', |
||||
|
'font-size': '16px' |
||||
|
}, |
||||
|
'object_class': 'my-object' |
||||
|
}) |
||||
|
``` |
||||
|
""" |
||||
|
changed_styles_str = kwargs.get('changed_styles', '{}') |
||||
|
object_class = kwargs.get('object_class', '') |
||||
|
changed_styles = json.loads(changed_styles_str) |
||||
|
working_dir = os.path.dirname(os.path.realpath(__file__)) |
||||
|
working_dir = working_dir.replace('/controllers', '') |
||||
|
file_path = working_dir + '/static/src/css/dynamic_styles.css' |
||||
|
style_file = open(file_path, 'a') |
||||
|
|
||||
|
if os.stat(file_path).st_size == 0: |
||||
|
style_file.write('/* This file is generated automatically by ' |
||||
|
'Theme Infinito */\n') |
||||
|
|
||||
|
style_file.write('\n.' + object_class + ' {\n') |
||||
|
|
||||
|
for style in changed_styles: |
||||
|
style_file.write( |
||||
|
'\t' + style + ': ' + changed_styles[style] + ';\n') |
||||
|
|
||||
|
style_file.write('}\n') |
||||
|
style_file.close() |
||||
|
minify_css(file_path) |
||||
|
return True |
||||
|
|
||||
|
@http.route(['/theme_studio/get_current_style'], type="json") |
||||
|
def get_current_style(self, kwargs): |
||||
|
""" |
||||
|
Retrieve the current styles for a given CSS selector. |
||||
|
|
||||
|
Parameters: |
||||
|
kwargs (dict): A dictionary containing the 'selector' key |
||||
|
specifying the CSS selector. |
||||
|
|
||||
|
Returns: |
||||
|
list or bool: A list of style properties and values for the |
||||
|
specified selector, or False if the selector is not found. |
||||
|
|
||||
|
This function reads the CSS file containing dynamic styles and |
||||
|
searches for the specified CSS selector. If the selector is found, |
||||
|
it returns a list of style properties and values associated with that |
||||
|
selector. Each style property-value pair is represented as a list |
||||
|
containing the property and its corresponding value. |
||||
|
If the selector is not found,it returns False. |
||||
|
|
||||
|
Example: |
||||
|
To retrieve the current styles for a specific CSS selector: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import get_current_style |
||||
|
|
||||
|
current_styles = get_current_style({ |
||||
|
'selector': '.my-selector' |
||||
|
}) |
||||
|
print(current_styles) |
||||
|
# Output: [['color', 'red'], ['font-size', '16px']] |
||||
|
``` |
||||
|
""" |
||||
|
selector = kwargs.get('selector', '') |
||||
|
working_dir = os.path.dirname(os.path.realpath(__file__)) |
||||
|
file_path = working_dir.replace('controllers', |
||||
|
'static/src/css/dynamic_styles.css') |
||||
|
style_file = open(file_path, 'r') |
||||
|
css = style_file.read() |
||||
|
css = re.sub(r'/\*[\s\S]*?\*/', "", css) |
||||
|
css = re.sub(r'url\((["\'])([^)]*)\1\)', r'url(\2)', css) |
||||
|
css = re.sub(r'\s+', ' ', css) |
||||
|
css = re.sub(r'#([0-9a-f])\1([\da-f])\2([0-9a-f])\3(\s|;)', |
||||
|
r'#\1\2\3\4', css) |
||||
|
css = re.sub(r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css) |
||||
|
rules = re.findall(r'([^{]+){([^}]*)}', css) |
||||
|
for rule in rules: |
||||
|
selector_now = rule[0] |
||||
|
content = rule[1] |
||||
|
if selector == selector_now.strip(): |
||||
|
contents = content.split(';') |
||||
|
content = [] |
||||
|
for c in contents: |
||||
|
c = c.split(':') |
||||
|
if c[0] != '' and len(c) > 1: |
||||
|
content.append( |
||||
|
[c[0], c[1].strip().replace('!important', '')]) |
||||
|
return content |
||||
|
|
||||
|
return False |
||||
|
|
||||
|
@http.route(['/theme_studio/reset_to_default'], type="json") |
||||
|
def reset_to_default(self): |
||||
|
""" |
||||
|
Reset dynamic styles to default. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the styles are successfully reset, otherwise False. |
||||
|
|
||||
|
This function clears the content of the CSS file containing |
||||
|
dynamic styles, effectively resetting all styles to their default |
||||
|
values. |
||||
|
|
||||
|
Example: |
||||
|
To reset dynamic styles to default: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import reset_to_default |
||||
|
|
||||
|
reset_to_default() |
||||
|
``` |
||||
|
""" |
||||
|
working_dir = os.path.dirname(os.path.realpath(__file__)) |
||||
|
file_path = working_dir.replace('controllers', |
||||
|
'static/src/css/dynamic_styles.css') |
||||
|
style_file = open(file_path, 'w') |
||||
|
style_file.write('') |
||||
|
return True |
||||
|
|
||||
|
@http.route(['/theme_studio/set_advanced_data'], type="json") |
||||
|
def set_advanced_data(self, args): |
||||
|
""" |
||||
|
Set advanced theme configuration data. |
||||
|
|
||||
|
Parameters: |
||||
|
args (list): A list containing a dictionary with the advanced |
||||
|
theme configuration values. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the configuration data is successfully set, |
||||
|
otherwise False. |
||||
|
|
||||
|
This function sets advanced theme configuration data based on the |
||||
|
provided dictionary of values. It updates the configuration |
||||
|
parameters in the database accordingly. |
||||
|
|
||||
|
Example: |
||||
|
To set advanced theme configuration data: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import set_advanced_data |
||||
|
|
||||
|
data = [{ |
||||
|
'vals': { |
||||
|
'sidebar': True, |
||||
|
'fullscreen': False, |
||||
|
'sidebarIcon': True, |
||||
|
'sidebarName': True, |
||||
|
'sidebarCompany': False, |
||||
|
'sidebarUser': True, |
||||
|
'recentApps': False, |
||||
|
'fullScreenApp': True, |
||||
|
'infinitoRtl': False, |
||||
|
'infinitoDark': True, |
||||
|
'infinitoDarkMode': 'dark', |
||||
|
'infinitoBookmark': True |
||||
|
} |
||||
|
}] |
||||
|
|
||||
|
set_advanced_data(data) |
||||
|
``` |
||||
|
""" |
||||
|
if args and 'vals' in args[0]: |
||||
|
vals = args[0]['vals'] |
||||
|
set_param = request.env['ir.config_parameter'].sudo().set_param |
||||
|
set_param('backend_theme_infinito.is_sidebar_enabled', |
||||
|
vals['sidebar']) |
||||
|
set_param('backend_theme_infinito.is_fullscreen_enabled', |
||||
|
vals['fullscreen']) |
||||
|
set_param('backend_theme_infinito.is_sidebar_icon', |
||||
|
vals['sidebarIcon']) |
||||
|
set_param('backend_theme_infinito.is_sidebar_name', |
||||
|
vals['sidebarName']) |
||||
|
set_param('backend_theme_infinito.is_sidebar_company', |
||||
|
vals['sidebarCompany']) |
||||
|
set_param('backend_theme_infinito.is_sidebar_user', |
||||
|
vals['sidebarUser']) |
||||
|
set_param('backend_theme_infinito.is_recent_apps', |
||||
|
vals['recentApps']) |
||||
|
set_param('backend_theme_infinito.is_fullscreen_app', |
||||
|
vals['fullScreenApp']) |
||||
|
set_param('backend_theme_infinito.is_rtl', vals['infinitoRtl']) |
||||
|
set_param('backend_theme_infinito.is_dark', vals['infinitoDark']) |
||||
|
set_param('backend_theme_infinito.dark_mode', |
||||
|
vals['infinitoDarkMode']) |
||||
|
set_param('backend_theme_infinito.is_menu_bookmark', |
||||
|
vals['infinitoBookmark']) |
||||
|
|
||||
|
@http.route(['/theme_studio/set_advanced_data_user'], type="json") |
||||
|
def set_advanced_data_user(self, args): |
||||
|
""" |
||||
|
Set advanced theme configuration data for the current user. |
||||
|
|
||||
|
Parameters: |
||||
|
args (list): A list containing a dictionary with the advanced |
||||
|
theme configuration values. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the configuration data is successfully set for the |
||||
|
user, otherwise False. |
||||
|
|
||||
|
This function sets advanced theme configuration data for the current |
||||
|
user based on the provided dictionary of values. It updates the |
||||
|
corresponding fields in the user record accordingly. |
||||
|
|
||||
|
Example: |
||||
|
To set advanced theme configuration data for the current user: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import set_advanced_data_user |
||||
|
|
||||
|
data = [{ |
||||
|
'vals': { |
||||
|
'sidebar': True, |
||||
|
'fullscreen': False, |
||||
|
'sidebarIcon': True, |
||||
|
'sidebarName': True, |
||||
|
'sidebarCompany': False, |
||||
|
'sidebarUser': True, |
||||
|
'recentApps': False, |
||||
|
'fullScreenApp': True, |
||||
|
'infinitoRtl': False, |
||||
|
'infinitoDark': True, |
||||
|
'infinitoDarkMode': 'dark', |
||||
|
'infinitoBookmark': True, |
||||
|
'loaderClass': 'custom-loader' |
||||
|
} |
||||
|
}] |
||||
|
|
||||
|
set_advanced_data_user(data) |
||||
|
``` |
||||
|
""" |
||||
|
if args and 'vals' in args[0]: |
||||
|
vals = args[0]['vals'] |
||||
|
request.env.user.write({ |
||||
|
'is_sidebar_enabled': vals['sidebar'], |
||||
|
'is_fullscreen_enabled': vals['fullscreen'], |
||||
|
'is_sidebar_icon': vals['sidebarIcon'], |
||||
|
'is_sidebar_name': vals['sidebarName'], |
||||
|
'is_sidebar_company': vals['sidebarCompany'], |
||||
|
'is_sidebar_user': vals['sidebarUser'], |
||||
|
'is_recent_apps': vals['recentApps'], |
||||
|
'is_fullscreen_app': vals['fullScreenApp'], |
||||
|
'is_rtl': vals['infinitoRtl'], |
||||
|
'is_dark': vals['infinitoDark'], |
||||
|
'dark_mode': vals['infinitoDarkMode'], |
||||
|
'is_menu_bookmark': vals['infinitoBookmark'], |
||||
|
'loader_class': vals['loaderClass'] |
||||
|
}) |
||||
|
|
||||
|
return True |
||||
|
|
||||
|
@http.route(['/theme_studio/add_recent_app'], type="json") |
||||
|
def add_recent_app(self, args): |
||||
|
""" |
||||
|
Add a recent application to the user's recent apps list. |
||||
|
|
||||
|
Parameters: |
||||
|
args (list): A list containing a dictionary with the 'appId' key |
||||
|
specifying the ID of the application. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the recent app is successfully added, otherwise False. |
||||
|
|
||||
|
This function adds a recent application to the user's recent apps list |
||||
|
based on the provided application ID. It checks if the provided |
||||
|
arguments are valid and if the user has already reached the maximum |
||||
|
limit of recent apps (5), it removes the oldest one before adding the |
||||
|
new one. |
||||
|
|
||||
|
Example: |
||||
|
To add a recent application with ID 123 to the user's recent apps |
||||
|
list: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import add_recent_app |
||||
|
|
||||
|
add_recent_app([{'appId': 123}]) |
||||
|
``` |
||||
|
""" |
||||
|
if args and isinstance(args, list) and len(args) > 0: |
||||
|
app_id = args[0].get('appId') |
||||
|
if app_id is not None: # Check if appId exists |
||||
|
app_id = int(app_id) |
||||
|
else: |
||||
|
# Handle the case where appId is not provided |
||||
|
# You might want to raise an error, log a message, or handle |
||||
|
# it differently based on your requirements |
||||
|
# For now, I'll assign a default value of 0 |
||||
|
app_id = 0 |
||||
|
else: |
||||
|
# Handle the case where args is empty or not a list |
||||
|
# You might want to raise an error or handle it differently based |
||||
|
# on your requirements For now, I'll assign a default value of 0 |
||||
|
app_id = 0 |
||||
|
|
||||
|
recent_app = request.env['recent.apps'].sudo() |
||||
|
exist = recent_app.search([ |
||||
|
('app_id', '=', app_id), |
||||
|
('user_id', '=', request.env.user.id) |
||||
|
]) |
||||
|
exist.unlink() if exist else None |
||||
|
total_recent = recent_app.search( |
||||
|
[('user_id', '=', request.env.user.id)]) |
||||
|
if len(total_recent) > 4: |
||||
|
total_recent[0].unlink() |
||||
|
recent_app.create({ |
||||
|
'app_id': app_id, |
||||
|
'user_id': request.env.user.id |
||||
|
}) |
||||
|
|
||||
|
@http.route(['/theme_studio/get_recent_apps'], type="json") |
||||
|
def get_recent_apps(self): |
||||
|
""" |
||||
|
Retrieve the list of recent applications for the current user. |
||||
|
|
||||
|
Returns: |
||||
|
list: A list of dictionaries containing the recent applications' |
||||
|
information, |
||||
|
or an empty list if no recent apps are found. |
||||
|
|
||||
|
This function retrieves the list of recent applications for the current |
||||
|
user from the database. It returns a list of dictionaries containing the |
||||
|
information of each recent application, such as its ID, name, and other |
||||
|
relevant details. |
||||
|
|
||||
|
Example: |
||||
|
To retrieve the list of recent applications for the current user: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import get_recent_apps |
||||
|
|
||||
|
recent_apps = get_recent_apps() |
||||
|
print(recent_apps) |
||||
|
``` |
||||
|
""" |
||||
|
recent_app = request.env['recent.apps'].sudo() |
||||
|
return recent_app.search_read([ |
||||
|
('user_id', '=', request.env.user.id) |
||||
|
]) |
||||
|
|
||||
|
@http.route(['/theme_studio/add_menu_bookmarks'], type="json") |
||||
|
def add_menu_bookmarks(self, args): |
||||
|
""" |
||||
|
Add a menu bookmark for the current user. |
||||
|
|
||||
|
Parameters: |
||||
|
args (dict): A dictionary containing the menu data including |
||||
|
'actionId' and 'menuUrl'. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the menu bookmark is successfully added, otherwise |
||||
|
False. |
||||
|
|
||||
|
This function adds a menu bookmark for the current user based on the |
||||
|
provided |
||||
|
menu data. It extracts the action ID and URL from the menu data and |
||||
|
creates a |
||||
|
new menu bookmark record in the database. |
||||
|
|
||||
|
Example: |
||||
|
To add a menu bookmark with action ID 123 and URL '/dashboard' for |
||||
|
the current user: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import add_menu_bookmarks |
||||
|
|
||||
|
menu_data = { |
||||
|
'actionId': 123, |
||||
|
'menuUrl': '/dashboard' |
||||
|
} |
||||
|
add_menu_bookmarks({'menu': menu_data}) |
||||
|
``` |
||||
|
""" |
||||
|
menu_data = args.get('menu', {}) |
||||
|
action_id = menu_data.get('actionId') |
||||
|
user_id = request.env.user.id |
||||
|
url = menu_data.get('menuUrl') |
||||
|
menu_bookmark = request.env['infinito.menu.bookmark'].sudo() |
||||
|
menu_bookmark.create({ |
||||
|
'action_id': int((action_id)), |
||||
|
'user_id': user_id, |
||||
|
'url': url, |
||||
|
}) |
||||
|
|
||||
|
@http.route(['/theme_studio/remove_menu_bookmarks'], type="json") |
||||
|
def remove_menu_bookmarks(self, args): |
||||
|
""" |
||||
|
Remove a menu bookmark for the current user. |
||||
|
|
||||
|
Parameters: |
||||
|
args (dict): A dictionary containing the menu data including |
||||
|
'actionId'. |
||||
|
|
||||
|
Returns: |
||||
|
bool: True if the menu bookmark is successfully removed, |
||||
|
otherwise False. |
||||
|
|
||||
|
This function removes a menu bookmark for the current user based on |
||||
|
the provided |
||||
|
action ID. It searches for the menu bookmark record in the database and |
||||
|
deletes |
||||
|
it if found. |
||||
|
|
||||
|
Example: |
||||
|
To remove a menu bookmark with action ID 123 for the current user: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import remove_menu_bookmarks |
||||
|
|
||||
|
menu_data = { |
||||
|
'actionId': 123 |
||||
|
} |
||||
|
remove_menu_bookmarks({'menu': menu_data}) |
||||
|
``` |
||||
|
""" |
||||
|
menu_data = args.get('menu', {}) |
||||
|
action_id = menu_data.get('actionId') |
||||
|
user_id = request.env.user.id |
||||
|
menu_bookmark = request.env['infinito.menu.bookmark'].sudo().search([ |
||||
|
('action_id', '=', int(action_id)), |
||||
|
('user_id', '=', user_id) |
||||
|
]) |
||||
|
if menu_bookmark: |
||||
|
menu_bookmark.unlink() |
||||
|
|
||||
|
@http.route(['/theme_studio/get_presets'], type="json") |
||||
|
def get_presets(self): |
||||
|
""" |
||||
|
Retrieve the list of available presets. |
||||
|
|
||||
|
Returns: |
||||
|
list: A list of dictionaries containing the available presets. |
||||
|
|
||||
|
This function reads the presets data from a JSON file and returns |
||||
|
it as a list of dictionaries. |
||||
|
Each dictionary in the list represents a preset with |
||||
|
its configuration details. |
||||
|
|
||||
|
Example: |
||||
|
To retrieve the list of available presets: |
||||
|
|
||||
|
```python |
||||
|
from my_theme_module import get_presets |
||||
|
|
||||
|
presets = get_presets() |
||||
|
print(presets) |
||||
|
``` |
||||
|
""" |
||||
|
working_dir = os.path.dirname(os.path.realpath(__file__)) |
||||
|
working_dir = working_dir.replace('/controllers', '') |
||||
|
file_path = working_dir + '/static/src/json/presets.json' |
||||
|
file = open(file_path, 'r') |
||||
|
presets = json.load(file) |
||||
|
|
||||
|
return presets |
@ -0,0 +1,6 @@ |
|||||
|
## Module <backend_theme_infinito> |
||||
|
|
||||
|
#### 03.10.2024 |
||||
|
#### Version 17.0.1.0.0 |
||||
|
#### ADD |
||||
|
Initial Commit for Infinito Backend Theme |
@ -0,0 +1,158 @@ |
|||||
|
"""Hooks for Changing Menu Web_icon""" |
||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
import base64 |
||||
|
|
||||
|
from odoo import api, SUPERUSER_ID |
||||
|
from odoo.modules import get_module_resource |
||||
|
|
||||
|
|
||||
|
def icons_post_init_hook(cr): |
||||
|
"""post init hook for changing module icons""" |
||||
|
# env = api.Environment(cr, SUPERUSER_ID, {}) |
||||
|
menu_item = cr['ir.ui.menu'].search([('parent_id', '=', False)]) |
||||
|
|
||||
|
for menu in menu_item: |
||||
|
if menu.name == 'Contacts': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'contact.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Link Tracker': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'link-tracker.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Dashboards': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'dashboard.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Sales': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'sales.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Invoicing': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'invoice.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Inventory': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'inventory.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Purchase': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'purchase.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Calendar': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'calendar.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'CRM': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'crm.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Notes': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'notes.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Website': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'website.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Point of Sale': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'pos.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Manufacturing': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'manufacturing.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Repairs': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'repairs.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Email Marketing': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'marketing.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'SMS Marketing': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'sms-marketing.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Project': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'project.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Surveys': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'surveys.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Employees': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'employees.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Recruitment': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'recruitment.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Attendances': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'attendance.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Time Off': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'time-off.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Expenses': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'expense.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Maintenance': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'maintenance.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Live Chat': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'live-chat.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Lunch': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'lunch.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Fleet': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'fleet.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Timesheets': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'timesheets.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Events': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'events.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'eLearning': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'elearning.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
||||
|
if menu.name == 'Members': |
||||
|
img_path = get_module_resource( |
||||
|
'backend_theme_infinito', 'static', 'src', 'img', 'icons', 'members.png') |
||||
|
menu.write({'web_icon_data': base64.b64encode(open(img_path, "rb").read())}) |
@ -0,0 +1,26 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from . import ir_http |
||||
|
from . import menu_bookmark |
||||
|
from . import recent_apps |
||||
|
from . import res_config_settings |
||||
|
from . import res_users |
@ -0,0 +1,120 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
def float_to_time(time): |
||||
|
""" |
||||
|
Convert a floating-point number representing time in hours to a string |
||||
|
formatted as 'HH:MM'. |
||||
|
|
||||
|
Parameters: |
||||
|
- time (float): The time in hours to be converted. |
||||
|
|
||||
|
Returns: |
||||
|
- str: A string representing the time in the format 'HH:MM'. |
||||
|
""" |
||||
|
return '{0:02.0f}:{1:02.0f}'.format(*divmod(float(time) * 60, 60)) |
||||
|
|
||||
|
|
||||
|
class IrHttp(models.AbstractModel): |
||||
|
""" |
||||
|
Extends the 'ir.http' model to customize session information for the |
||||
|
web client. |
||||
|
""" |
||||
|
_inherit = 'ir.http' |
||||
|
|
||||
|
def session_info(self): |
||||
|
""" |
||||
|
Overrides the default session_info method to customize session |
||||
|
information based on user preferences. |
||||
|
|
||||
|
Returns: |
||||
|
- dict: A dictionary containing session information customized for |
||||
|
the current user. |
||||
|
""" |
||||
|
res = super(IrHttp, self).session_info() |
||||
|
get_param = self.env['ir.config_parameter'].sudo().get_param |
||||
|
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['sidebar'] = self.env.user.is_sidebar_enabled |
||||
|
res['fullscreen'] = self.env.user.is_fullscreen_enabled |
||||
|
res['sidebarIcon'] = self.env.user.is_sidebar_icon |
||||
|
res['sidebarName'] = self.env.user.is_sidebar_name |
||||
|
res['sidebarCompany'] = self.env.user.is_sidebar_company |
||||
|
res['sidebarUser'] = self.env.user.is_sidebar_user |
||||
|
res['recentApps'] = self.env.user.is_recent_apps |
||||
|
res['fullScreenApp'] = self.env.user.is_fullscreen_app |
||||
|
res['infinitoRtl'] = self.env.user.is_rtl |
||||
|
res['infinitoDark'] = self.env.user.is_dark |
||||
|
res['infinitoDarkMode'] = self.env.user.dark_mode |
||||
|
res['infinitoDarkStart'] = float_to_time( |
||||
|
self.env.user.dark_start) |
||||
|
res['infinitoDarkEnd'] = float_to_time(self.env.user.dark_end) |
||||
|
res['infinitoBookmark'] = self.env.user.is_menu_bookmark |
||||
|
res['loaderClass'] = self.env.user.loader_class |
||||
|
else: |
||||
|
res['sidebar'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_enabled', default=False) |
||||
|
res['fullscreen'] = get_param( |
||||
|
'backend_theme_infinito.is_fullscreen_enabled', |
||||
|
default=False) |
||||
|
res['sidebarIcon'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_icon', default=False) |
||||
|
res['sidebarName'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_name', default=False) |
||||
|
res['sidebarCompany'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_company', default=False) |
||||
|
res['sidebarUser'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_user', default=False) |
||||
|
res['recentApps'] = get_param( |
||||
|
'backend_theme_infinito.is_recent_apps', default=False) |
||||
|
res['fullScreenApp'] = get_param( |
||||
|
'backend_theme_infinito.is_fullscreen_app', default=False) |
||||
|
res['infinitoRtl'] = get_param( |
||||
|
'backend_theme_infinito.is_rtl', default=False) |
||||
|
res['infinitoDark'] = get_param( |
||||
|
'backend_theme_infinito.is_dark', default=False) |
||||
|
res['infinitoDarkMode'] = get_param( |
||||
|
'backend_theme_infinito.dark_mode', default=False) |
||||
|
res['infinitoDarkStart'] = float_to_time(get_param( |
||||
|
'backend_theme_infinito.dark_start', default=19.0)) |
||||
|
res['infinitoDarkEnd'] = float_to_time(get_param( |
||||
|
'backend_theme_infinito.dark_end', default=5.0)) |
||||
|
res['infinitoBookmark'] = get_param( |
||||
|
'backend_theme_infinito.is_menu_bookmark', default=False) |
||||
|
res['loaderClass'] = get_param( |
||||
|
'backend_theme_infinito.loader_class', default=False) |
||||
|
menu_bookmark = self.env['infinito.menu.bookmark'].sudo(). \ |
||||
|
search([('user_id', '=', self.env.user.id)]) |
||||
|
list_bookmark = [] |
||||
|
for bookmark in menu_bookmark: |
||||
|
bkm = bookmark.read(['action_id', 'url', 'name'])[0] |
||||
|
bkm['short_name'] = bkm['name'][:2].upper() |
||||
|
list_bookmark.append(bkm) |
||||
|
res['infinitoBookmarks'] = menu_bookmark.action_id.ids |
||||
|
res['infinitoMenuBookmarks'] = list_bookmark |
||||
|
|
||||
|
return res |
@ -0,0 +1,35 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class InfinitoMenuBookmark(models.Model): |
||||
|
""" |
||||
|
Model representing bookmarks for menu items in the Infinito system. |
||||
|
""" |
||||
|
_name = 'infinito.menu.bookmark' |
||||
|
_description = 'Menu Bookmark' |
||||
|
|
||||
|
name = fields.Char(related='action_id.name') |
||||
|
action_id = fields.Many2one('ir.actions.act_window') |
||||
|
url = fields.Text('Url') |
||||
|
user_id = fields.Many2one('res.users') |
@ -0,0 +1,81 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import api,fields, models |
||||
|
|
||||
|
|
||||
|
class RecentApps(models.Model): |
||||
|
""" |
||||
|
Model representing recent applications accessed by users in the system. |
||||
|
""" |
||||
|
|
||||
|
_name = 'recent.apps' |
||||
|
_description = 'Recent Apps' |
||||
|
|
||||
|
name = fields.Char(compute='_compute_icon', store=True) |
||||
|
app_id = fields.Integer() |
||||
|
icon = fields.Binary(compute='_compute_icon', store=True) |
||||
|
type = fields.Char(compute='_compute_type', store=True) |
||||
|
user_id = fields.Many2one('res.users') |
||||
|
|
||||
|
@api.depends('app_id') |
||||
|
def _compute_type(self): |
||||
|
""" |
||||
|
Compute method to determine the type of the recent app based on its |
||||
|
associated menu. |
||||
|
|
||||
|
This method computes the type of the recent app by retrieving its |
||||
|
associated menu, |
||||
|
extracting the type information from the menu's web icon, and |
||||
|
updating the 'type' |
||||
|
field accordingly. |
||||
|
|
||||
|
""" |
||||
|
menu_ui = self.env['ir.ui.menu'] |
||||
|
for rec in self: |
||||
|
app = menu_ui.browse(rec.app_id) |
||||
|
la = str(app.web_icon) |
||||
|
spl_word = '.' |
||||
|
res = la.split(spl_word, 1) |
||||
|
if len(res) > 1: |
||||
|
splitString = res[1] |
||||
|
rec.type = splitString |
||||
|
else: |
||||
|
# Handle the case where splitting doesn't result in two parts |
||||
|
# You might want to set a default value or raise an error, depending on your requirements |
||||
|
# For now, I'll set rec.type to an empty string |
||||
|
rec.type = "" |
||||
|
|
||||
|
@api.depends('app_id') |
||||
|
def _compute_icon(self): |
||||
|
""" |
||||
|
Compute method to determine the icon for the recent app based on its associated menu. |
||||
|
|
||||
|
This method computes the icon for the recent app by retrieving its associated menu, |
||||
|
extracting the icon information from the menu's web icon, and updating the 'icon' |
||||
|
field accordingly. It also updates the 'name' field with the name of the associated menu. |
||||
|
|
||||
|
""" |
||||
|
menu_ui = self.env['ir.ui.menu'] |
||||
|
for rec in self: |
||||
|
app = menu_ui.browse(rec.app_id) |
||||
|
rec.icon = app._compute_web_icon_data(app.web_icon) |
||||
|
rec.name = app.name |
@ -0,0 +1,151 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class ResConfigSettings(models.TransientModel): |
||||
|
""" |
||||
|
Model representing configuration settings for the system. |
||||
|
|
||||
|
This model allows the administrator to configure various settings |
||||
|
related to the user interface and system behavior. |
||||
|
""" |
||||
|
|
||||
|
_inherit = 'res.config.settings' |
||||
|
|
||||
|
is_user_edit = fields.Boolean('User edit', default=False) |
||||
|
is_sidebar_enabled = fields.Boolean('Sidebar Enabled', default=False) |
||||
|
is_fullscreen_enabled = fields.Boolean('Full screen Enabled', default=False) |
||||
|
is_sidebar_icon = fields.Boolean('Sidebar icon Enabled', default=True) |
||||
|
is_sidebar_name = fields.Boolean('Sidebar name Enabled', default=True) |
||||
|
is_sidebar_company = fields.Boolean('Sidebar Company Enabled', |
||||
|
default=False) |
||||
|
is_sidebar_user = fields.Boolean('Sidebar User Enabled', default=False) |
||||
|
is_recent_apps = fields.Boolean('Recent Apps Enabled', default=False) |
||||
|
is_fullscreen_app = fields.Boolean('Full screen Apps Enabled', |
||||
|
default=False) |
||||
|
is_rtl = fields.Boolean('Rtl Enabled', default=False) |
||||
|
is_dark = fields.Boolean('Dark mode Enabled', default=False) |
||||
|
is_menu_bookmark = fields.Boolean('Menu Bookmark mode Enabled', |
||||
|
default=False) |
||||
|
is_chameleon = fields.Boolean('Chameleon mode Enabled', default=False) |
||||
|
dark_mode = fields.Selection([ |
||||
|
('all', 'All'), |
||||
|
('schedule', 'Schedule'), |
||||
|
('auto', 'Automatic'), |
||||
|
], default='all') |
||||
|
dark_start = fields.Float('Dark Start', default=19.0) |
||||
|
dark_end = fields.Float('Dark End', default=5.0) |
||||
|
loader_class = fields.Char('Loader', default='default') |
||||
|
|
||||
|
@api.model |
||||
|
def get_values(self): |
||||
|
""" |
||||
|
Retrieve the current configuration values for the system. |
||||
|
|
||||
|
This method retrieves the current configuration values for the system, |
||||
|
including settings related to the user interface and system behavior. |
||||
|
|
||||
|
Returns: |
||||
|
- dict: A dictionary containing the current configuration values. |
||||
|
""" |
||||
|
res = super(ResConfigSettings, self).get_values() |
||||
|
get_param = self.env['ir.config_parameter'].sudo().get_param |
||||
|
res['is_user_edit'] = get_param('backend_theme_infinito.is_user_edit', |
||||
|
default=False) |
||||
|
res['is_sidebar_enabled'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_enabled', default=False) |
||||
|
res['is_fullscreen_enabled'] = get_param( |
||||
|
'backend_theme_infinito.is_fullscreen_enabled', default=False) |
||||
|
res['is_sidebar_icon'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_icon', default=False) |
||||
|
res['is_sidebar_name'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_name', default=False) |
||||
|
res['is_sidebar_company'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_company', default=False) |
||||
|
res['is_sidebar_user'] = get_param( |
||||
|
'backend_theme_infinito.is_sidebar_user', default=False) |
||||
|
res['is_recent_apps'] = get_param( |
||||
|
'backend_theme_infinito.is_recent_apps', default=False) |
||||
|
res['is_rtl'] = get_param('backend_theme_infinito.is_rtl', |
||||
|
default=False) |
||||
|
res['is_dark'] = get_param('backend_theme_infinito.is_dark', |
||||
|
default=False) |
||||
|
res['is_menu_bookmark'] = get_param( |
||||
|
'backend_theme_infinito.is_menu_bookmark', default=False) |
||||
|
res['dark_mode'] = get_param('backend_theme_infinito.dark_mode', |
||||
|
default='all') |
||||
|
res['dark_start'] = get_param('backend_theme_infinito.dark_start', |
||||
|
default=19.0) |
||||
|
res['dark_end'] = get_param('backend_theme_infinito.dark_end', |
||||
|
default=5.0) |
||||
|
res['loader_class'] = get_param('backend_theme_infinito.loader_class', |
||||
|
default=5.0) |
||||
|
res['is_chameleon'] = get_param('backend_theme_infinito.is_chameleon', |
||||
|
default=False) |
||||
|
|
||||
|
return res |
||||
|
|
||||
|
@api.model |
||||
|
def set_values(self): |
||||
|
""" |
||||
|
Update the configuration values for the system. |
||||
|
|
||||
|
This method updates the configuration values for the system based on the current |
||||
|
settings provided by the administrator. |
||||
|
|
||||
|
""" |
||||
|
set_param = self.env['ir.config_parameter'].sudo().set_param |
||||
|
set_param('backend_theme_infinito.is_user_edit', |
||||
|
self.is_user_edit) |
||||
|
set_param('backend_theme_infinito.is_sidebar_enabled', |
||||
|
self.is_sidebar_enabled) |
||||
|
set_param('backend_theme_infinito.is_fullscreen_enabled', |
||||
|
self.is_fullscreen_enabled) |
||||
|
set_param('backend_theme_infinito.is_sidebar_icon', |
||||
|
self.is_sidebar_icon) |
||||
|
set_param('backend_theme_infinito.is_sidebar_name', |
||||
|
self.is_sidebar_name) |
||||
|
set_param('backend_theme_infinito.is_sidebar_company', |
||||
|
self.is_sidebar_company) |
||||
|
set_param('backend_theme_infinito.is_sidebar_user', |
||||
|
self.is_sidebar_user) |
||||
|
set_param('backend_theme_infinito.is_recent_apps', |
||||
|
self.is_recent_apps) |
||||
|
set_param('backend_theme_infinito.is_rtl', |
||||
|
self.is_rtl) |
||||
|
set_param('backend_theme_infinito.is_dark', |
||||
|
self.is_dark) |
||||
|
set_param('backend_theme_infinito.dark_mode', |
||||
|
self.dark_mode) |
||||
|
set_param('backend_theme_infinito.dark_start', |
||||
|
self.dark_start) |
||||
|
set_param('backend_theme_infinito.dark_end', |
||||
|
self.dark_end) |
||||
|
set_param('backend_theme_infinito.is_menu_bookmark', |
||||
|
self.is_menu_bookmark) |
||||
|
set_param('backend_theme_infinito.loader_class', |
||||
|
self.loader_class) |
||||
|
set_param('backend_theme_infinito.is_chameleon', |
||||
|
self.is_chameleon) |
||||
|
|
||||
|
super(ResConfigSettings, self).set_values() |
@ -0,0 +1,56 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ResUser(models.Model): |
||||
|
""" |
||||
|
Model representing system users with additional customization options. |
||||
|
|
||||
|
This model extends the base 'res.users' model to include additional fields |
||||
|
for customizing user interface preferences and system behavior. |
||||
|
""" |
||||
|
_inherit = 'res.users' |
||||
|
|
||||
|
is_sidebar_enabled = fields.Boolean('Sidebar Enabled', default=False) |
||||
|
is_fullscreen_enabled = fields.Boolean('Full screen Enabled', default=False) |
||||
|
is_sidebar_icon = fields.Boolean('Sidebar icon Enabled', default=True) |
||||
|
is_sidebar_name = fields.Boolean('Sidebar name Enabled', default=True) |
||||
|
is_sidebar_company = fields.Boolean('Sidebar Company Enabled', |
||||
|
default=False) |
||||
|
is_sidebar_user = fields.Boolean('Sidebar User Enabled', default=False) |
||||
|
is_recent_apps = fields.Boolean('Recent Apps Enabled', default=False) |
||||
|
is_fullscreen_app = fields.Boolean('Full screen Apps Enabled', |
||||
|
default=False) |
||||
|
is_rtl = fields.Boolean('Rtl Enabled', default=False) |
||||
|
is_dark = fields.Boolean('Dark mode Enabled', default=False) |
||||
|
is_menu_bookmark = fields.Boolean('Menu Bookmark mode Enabled', |
||||
|
default=False) |
||||
|
is_chameleon = fields.Boolean('Chameleon mode Enabled', default=False) |
||||
|
dark_mode = fields.Selection([ |
||||
|
('all', 'All'), |
||||
|
('schedule', 'Schedule'), |
||||
|
('auto', 'Automatic'), |
||||
|
], default='all') |
||||
|
dark_start = fields.Float('Dark Start', default=19.0) |
||||
|
dark_end = fields.Float('Dark End', default=5.0) |
||||
|
loader_class = fields.Char('Loader', default='default') |
After Width: | Height: | Size: 349 KiB |
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: 258 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 197 KiB |
After Width: | Height: | Size: 16 MiB |
After Width: | Height: | Size: 11 MiB |
After Width: | Height: | Size: 6.6 MiB |
After Width: | Height: | Size: 3.4 MiB |
After Width: | Height: | Size: 2.1 MiB |
After Width: | Height: | Size: 8.8 MiB |
After Width: | Height: | Size: 10 MiB |
After Width: | Height: | Size: 27 MiB |
After Width: | Height: | Size: 4.9 MiB |
After Width: | Height: | Size: 2.8 MiB |
After Width: | Height: | Size: 6.6 MiB |
After Width: | Height: | Size: 174 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 174 KiB |
After Width: | Height: | Size: 239 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 197 KiB |
After Width: | Height: | Size: 221 KiB |
After Width: | Height: | Size: 187 KiB |
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 1012 KiB |
After Width: | Height: | Size: 202 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 197 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 179 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 406 KiB |
@ -0,0 +1,2 @@ |
|||||
|
/* This Styles are generated automatically by Theme Studio */ |
||||
|
. {background-color: rgb(250, 0, 0) !important;} |
@ -0,0 +1,34 @@ |
|||||
|
.o_web_client { |
||||
|
background-color: var(--bg_white); |
||||
|
} |
||||
|
|
||||
|
.o_web_client > header { |
||||
|
margin: 10px 10px 0px 10px; |
||||
|
border-radius: 10px; |
||||
|
box-shadow: 1px 1px 15px 0; |
||||
|
} |
||||
|
|
||||
|
.o_main_navbar { |
||||
|
border-radius: 10px; |
||||
|
} |
||||
|
|
||||
|
.o_web_client > .o_action_manager, #sidebar_panel, .oe_kanban_card { |
||||
|
margin: 15px; |
||||
|
border-radius: 10px; |
||||
|
box-shadow: 1px 1px 15px 0; |
||||
|
padding: 15px; |
||||
|
background-color: var(--bg_white); |
||||
|
} |
||||
|
|
||||
|
#sidebar_panel { |
||||
|
margin-left: 0px; |
||||
|
background-color: var(--nav_bar_color); |
||||
|
} |
||||
|
|
||||
|
.o_main_navbar .o_navbar_apps_menu.show .o-dropdown--menu dropdown-menu { |
||||
|
border-radius: 10px 0 10px 10px; |
||||
|
} |
||||
|
|
||||
|
.oe_kanban_card { |
||||
|
box-shadow: none; |
||||
|
} |
@ -0,0 +1,128 @@ |
|||||
|
/* Rotation */ |
||||
|
|
||||
|
.rotating::before{ |
||||
|
content: " "; |
||||
|
position: absolute; |
||||
|
top: calc(50% - 25px); |
||||
|
left: calc(50% - 25px); |
||||
|
height: 50px; |
||||
|
width: 50px; |
||||
|
background-image: linear-gradient(to bottom,black 50%, white 50%); |
||||
|
border-radius: 50%; |
||||
|
animation: rotate 1s; |
||||
|
animation-iteration-count: infinite; |
||||
|
} |
||||
|
|
||||
|
.rotating::after{ |
||||
|
content: " "; |
||||
|
position: absolute; |
||||
|
top: calc(50% - 20px); |
||||
|
left: calc(50% - 20px); |
||||
|
height: 40px; |
||||
|
width: 40px; |
||||
|
background-color: #020202; |
||||
|
border-radius: 50%; |
||||
|
} |
||||
|
|
||||
|
/* Blinking */ |
||||
|
|
||||
|
.blinking::after{ |
||||
|
content: " "; |
||||
|
position: absolute; |
||||
|
top: calc(50% - 25px); |
||||
|
left: calc(50% - 25px); |
||||
|
height: 50px; |
||||
|
width: 50px; |
||||
|
border-radius: 50%; |
||||
|
background-color:#fff; |
||||
|
animation: blink 2000ms ease infinite; |
||||
|
} |
||||
|
|
||||
|
.blinking-2::after{ |
||||
|
background-color: transparent; |
||||
|
border: 2px solid white; |
||||
|
transform: scale(0); |
||||
|
animation: blink-2 2000ms ease-out infinite,blink-2a 2s ease-out infinite; |
||||
|
animation-fill-mode: forwards; |
||||
|
} |
||||
|
|
||||
|
.bounce::after{ |
||||
|
content: " "; |
||||
|
position: absolute; |
||||
|
top: calc(50% - 50px); |
||||
|
left: calc(50% - 25px); |
||||
|
height: 50px; |
||||
|
width: 50px; |
||||
|
box-sizing: border-box; |
||||
|
background-image: linear-gradient(to bottom,rgb(255, 255, 255) 60%, rgb(235, 235, 235) 80%, rgb(210, 210, 210)); |
||||
|
border-radius: 50%; |
||||
|
animation: bounce 2s; |
||||
|
animation-iteration-count: infinite; |
||||
|
} |
||||
|
|
||||
|
.ring:after { |
||||
|
content: " "; |
||||
|
display: block; |
||||
|
width: 64px; |
||||
|
height: 64px; |
||||
|
margin: 8px; |
||||
|
border-radius: 50%; |
||||
|
border: 6px solid #fff; |
||||
|
border-color: #fff transparent #fff transparent; |
||||
|
animation: ring 1.2s linear infinite; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* Key frames */ |
||||
|
|
||||
|
@keyframes rotate{ |
||||
|
from{ |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
to{ |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes blink{ |
||||
|
0%{ |
||||
|
transform: scale(1); |
||||
|
} |
||||
|
50%{ |
||||
|
transform: scale(1.5); |
||||
|
} |
||||
|
100%{ |
||||
|
transform: scale(1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes blink-2{ |
||||
|
0%{ |
||||
|
transform: scale(0.2); |
||||
|
} |
||||
|
100%{ |
||||
|
transform: scale(1.5); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes bounce{ |
||||
|
0%,100%{ |
||||
|
transform: translateY(0); |
||||
|
height: 50px; |
||||
|
width: 50px; |
||||
|
} |
||||
|
50%{ |
||||
|
transform: translateY(50px); |
||||
|
height: 45px; |
||||
|
width: 55px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes ring { |
||||
|
0% { |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
100% { |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
After Width: | Height: | Size: 274 B |
After Width: | Height: | Size: 260 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 324 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 527 B |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 506 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 25 KiB |