Browse Source

Nov 26: [FIX] Bug Fixed 'backend_theme_infinito'

pull/331/merge
Risvana Cybro 3 weeks ago
parent
commit
6f8bd52f47
  1. 2
      backend_theme_infinito/__manifest__.py
  2. 4
      backend_theme_infinito/controllers/base_pwa.py
  3. 46
      backend_theme_infinito/controllers/main.py
  4. 17
      backend_theme_infinito/doc/RELEASE_NOTES.md
  5. 1
      backend_theme_infinito/icon_hooks.py
  6. 2
      backend_theme_infinito/static/src/css/dynamic_styles.css
  7. 7
      backend_theme_infinito/static/src/css/style.css
  8. 138
      backend_theme_infinito/static/src/js/theme_editor_sidebar.js
  9. 2
      backend_theme_infinito/static/src/js/variables.js
  10. 8
      backend_theme_infinito/static/src/json/presets.json
  11. 1
      backend_theme_infinito/static/src/scss/sidebar.scss
  12. 2
      backend_theme_infinito/static/src/scss/theme_styles.scss
  13. 1
      backend_theme_infinito/static/src/scss/theme_variables.scss
  14. 30
      backend_theme_infinito/static/src/xml/studio_elements.xml
  15. 12
      backend_theme_infinito/static/src/xml/theme_editor.xml

2
backend_theme_infinito/__manifest__.py

@ -27,7 +27,7 @@
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.3",
"version": "17.0.1.0.1",
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',

4
backend_theme_infinito/controllers/base_pwa.py

@ -23,7 +23,6 @@ import json
from odoo import http
from odoo.http import request
from odoo.modules.module import get_module_resource
class BasePwa(http.Controller):
"""
@ -37,14 +36,13 @@ class BasePwa(http.Controller):
Returns:
dict: Dictionary containing PWA manifest data.
"""
src = get_module_resource('backend_theme_infinito', 'static', 'src', 'img', 'menu.png')
return {
'short_name': 'Odoo',
'name': 'Odoo-infinito',
'description': 'PWA provided by backend theme infinito',
'icons': [
{
'src': f'{src}',
'src': '/backend_theme_infinito/static/src/img/menu.png',
'type': 'image/png',
'sizes': '144x144',
'purpose': 'any maskable'

46
backend_theme_infinito/controllers/main.py

@ -26,8 +26,6 @@ import re
from odoo import http
from odoo.http import request
from odoo.modules.module import get_module_resource
def minify_css(path):
"""
@ -139,8 +137,11 @@ class ThemeStudio(http.Controller):
changed_styles_str = kwargs.get('changed_styles', '{}')
object_class = kwargs.get('object_class', '')
changed_styles = json.loads(changed_styles_str)
file_path = get_module_resource('backend_theme_infinito', 'static', 'src', 'css', 'dynamic_styles.css')
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')
@ -190,7 +191,9 @@ class ThemeStudio(http.Controller):
```
"""
selector = kwargs.get('selector', '')
file_path = get_module_resource('backend_theme_infinito', 'static', 'src', 'css', 'dynamic_styles.css')
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)
@ -236,7 +239,9 @@ class ThemeStudio(http.Controller):
reset_to_default()
```
"""
file_path = get_module_resource('backend_theme_infinito', 'static', 'src', 'css', 'dynamic_styles.css')
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
@ -433,7 +438,7 @@ class ThemeStudio(http.Controller):
'user_id': request.env.user.id
})
@http.route(['/theme_studio/get_recent_apps'], type="json")
@http.route(['/theme_studio/get_recent_apps'], type="json", auth="user")
def get_recent_apps(self):
"""
Retrieve the list of recent applications for the current user.
@ -458,10 +463,26 @@ class ThemeStudio(http.Controller):
print(recent_apps)
```
"""
recent_app = request.env['recent.apps'].sudo()
return recent_app.search_read([
('user_id', '=', request.env.user.id)
])
recent_apps_model = request.env['recent.apps'].sudo()
menu_model = request.env['ir.ui.menu'].sudo()
results = []
recent_records = recent_apps_model.search(
[('user_id', '=', request.env.user.id)],
order="id desc")
for rec in recent_records:
menu = menu_model.browse(rec.app_id)
if not menu.exists():
continue
icon_data = menu.web_icon_data # base64
icon_type = "svg" if (menu.web_icon and menu.web_icon.endswith("svg")) else "png"
results.append({
"app_id": menu.id,
"name": menu.name,
"icon": icon_data,
"type": icon_type,
})
return results
@http.route(['/theme_studio/add_menu_bookmarks'], type="json")
def add_menu_bookmarks(self, args):
@ -571,7 +592,10 @@ class ThemeStudio(http.Controller):
print(presets)
```
"""
file_path = get_module_resource("backend_theme_infinito", "static", "src", "json", "presets.json")
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

17
backend_theme_infinito/doc/RELEASE_NOTES.md

@ -5,18 +5,7 @@
#### ADD
Initial Commit for Infinito Backend Theme
#### 04.12.2024
#### 25.11.2025
#### Version 17.0.1.0.1
##### BUGFIX
- Fixed the style issue in the sidebar menu buttons.
#### 23.06.2025
#### Version 17.0.1.0.2
##### BUGFIX
- Updated the functionality to fetch the module resource.
#### 05.07.2025
#### Version 17.0.1.0.3
##### BUGFIX
- Updated the functionality to fetch the module resource.
-
#### UPDT
Resolved the issue of recent apps

1
backend_theme_infinito/icon_hooks.py

@ -22,6 +22,7 @@
#############################################################################
import base64
from odoo import api, SUPERUSER_ID
from odoo.modules import get_module_resource

2
backend_theme_infinito/static/src/css/dynamic_styles.css

@ -1,2 +0,0 @@
/* This Styles are generated automatically by Theme Studio */
. {background-color: rgb(250, 0, 0) !important;}

7
backend_theme_infinito/static/src/css/style.css

@ -1528,7 +1528,7 @@ label:hover div.popover.fade.in {
#theme_editor_sidebar {
margin-left: 1587px !important;
height: inherit;
height: 934px;
}
.oe_kanban_action_button {
@ -1642,6 +1642,9 @@ label:hover div.popover.fade.in {
.infinito-form-select > option {
background-color: var(--sub-color-i-3);
}
select > option {
background: inherit;
}
.o_filter_menu > .fa-filter {
color: var(--button-bg) !important;
@ -1676,7 +1679,7 @@ label:hover div.popover.fade.in {
}
.o_form_button_create {
background-color: #5279be;
background-color: var(--button-bg) !important;
transition: background-color 0.3s ease
}

138
backend_theme_infinito/static/src/js/theme_editor_sidebar.js

@ -13,6 +13,8 @@ import {useService, useBus} from "@web/core/utils/hooks";
import {InfinitoDialog} from "./style_add"
import {jsonrpc} from "@web/core/network/rpc_service";
import {Dialog} from "@web/core/dialog/dialog";
import { variables, colors, to_color } from './variables';
const {useRef, onWillStart, xml, onMounted} = owl;
@ -45,7 +47,7 @@ export class ThemeEditorSidebar extends Component {
id="presets" t-on-change="_onPresetChange">
<t t-if="state.presets">
<t t-foreach="state.presets.button" t-as="preset" t-key="preset.name">
<option t-att-value="preset.name" t-att-style="_convertStyle(preset.style)"><t t-esc="preset.name"/></option>
<option t-att-value="preset.name" t-att-data="_convertStyle(preset.style)"><t t-esc="preset.name"/></option>
</t>
</t>
</select>
@ -131,6 +133,7 @@ export class ThemeEditorSidebar extends Component {
DesignDictionary: {},
preset_type: null,
presets: null,
style:'',
})
this.renderPresets();
// Set display name based on props
@ -191,7 +194,7 @@ export class ThemeEditorSidebar extends Component {
<h6>${displayName}</h6>
<div class="form-group">
<select class="form-control" id="select" t-att-name="${this.state.DesignDictionary[key].name}" aria-label="Default select example"
t-att-data-alt="${this.state.DesignDictionary[key].alt}" t-on-click="_onClickInput">
t-att-data-alt="${this.state.DesignDictionary[key].alt}" t-on-change="_onClickInput">
${this.state.DesignDictionary[key].options.map(option => `
<option t-att-value="${option}">${option}</option>
`).join('')}
@ -256,11 +259,12 @@ export class ThemeEditorSidebar extends Component {
* @param {Event} ev - The event object representing the change event.
*/
_onPresetChange(ev) {
document.querySelector(".infinito-remove").innerHTML = ''; // Clear existing content
// Get the index and selected option element
let index = ev.target.selectedIndex;
let elem = ev.target.children[index];
// Extract inline style string from the selected option element
let styleString = elem.getAttribute('style');
let styleString = elem.getAttribute('data');
// Split the style string into individual style declarations and create a dictionary of styles
const styleDeclarations = styleString.split(';');
const styles_dict = {}
@ -328,16 +332,26 @@ export class ThemeEditorSidebar extends Component {
var styles = this.props.object.target.style
// Open a dialog to save changes with the target styles and class
this.dialog.add(SaveChanges, {tools: styles, targetClass: targetClass});
this.toggleSidebar()
}
/**
* Handles the event when resetting changes.
*/
_onResetChanges() {
// Remove the element with class 'infinito-remove'
document.querySelector('.infinito-remove').remove();
const attr = this.props.object.target;
const styleStr = this.state.style || '';
styleStr.split(';').forEach(rule => {
const [prop] = rule.split(':');
if (prop) $(attr).css(prop.trim(), '');
});
document.querySelector('.infinito-remove').innerHTML = '';
}
/**
* Handles the click event on input elements.
* @param {Event} ev - The event object representing the click event.
@ -346,7 +360,7 @@ export class ThemeEditorSidebar extends Component {
// Initialize variables
var input_value, new_attr = '';
// Extract input type, unit, and alt from the target element
var input_type = $(ev.target).attr('name');
var input_type = ev.target.getAttribute('name') || ev.target.getAttribute('t-att-name')
var all_alts = [input_type];
var unit = $(ev.target).data('unit');
var alt = $(ev.target).data('alt');
@ -355,7 +369,7 @@ export class ThemeEditorSidebar extends Component {
let value = $(ev.target).val();
if (unit) {
value += unit;
}
}[[]]
value = $(ev.target).val() == '-1' ? 'infinite' : value;
$(ev.target).next().html(value);
}
@ -374,9 +388,10 @@ export class ThemeEditorSidebar extends Component {
all_alts.push(alt[i] + input_type)
}
}
this.state.style = this.state.style + style
// Apply the style to the target element
var attr = this.props.object.target;
$(attr).css('cssText', style);
$(attr).css('cssText', this.state.style);
}
/**
@ -385,100 +400,56 @@ export class ThemeEditorSidebar extends Component {
* @param {string} [val=null] - Optional value to override the default value of the tool.
*/
renderNewTool(tool, val = null) {
if (tool) {
// Get default value or use provided value
var value = this.getDefaultValue(tool.name);
if (val) {
value = val;
}
if (tool.type == 'range') {
value = value.replace(/[^0-9,.]+/g, "")
}
// Set the tool default value
this.state.widget = tool;
if (!tool) return null;
let value = this.getDefaultValue(tool.name);
if (val) value = val;
if (tool.type == 'range') value = value.replace(/[^0-9,.]+/g, "");
tool.default = value;
// Create a new div element for the tool
var newDiv = document.createElement("div");
newDiv.classList.add("optss", "infinito-remove");
// Generate HTML based on the tool type
let newDiv = document.createElement("div");
if (tool.type == 'color') {
// Color type tool
newDiv.innerHTML = `<div class="bg_color">
<h6>${tool.displayName}</h6>
<div class="color_picker">
<input class="favcolor" id="favcolor" type="color" name="${tool.name}" value="${tool.default}" property="color" data-alt="${tool.alt}"/>
</div>
</div>`;
var customizeButton = document.querySelector('.button_cutomise');
customizeButton.appendChild(newDiv);
}
var rangeDiv = document.createElement("div");
rangeDiv.classList.add("optss", "infinito-remove");
if (tool.type == 'range') {
// Range type tool
rangeDiv.innerHTML = `<div class="b_slider">
<h6>
${tool.displayName}
</h6>
<h6>
${tool.unit}
</h6>
} else if (tool.type == 'range') {
newDiv.innerHTML = `<div class="b_slider">
<h6>${tool.displayName}</h6>
<h6>${tool.unit}</h6>
</div>
<div class="b_width">
<div class="sliderContainer">
<input type="range" t-att-name="${tool.name}" t-att-data-unit="${tool.unit}"
value="${tool.default}" t-att-min="${tool.min}" t-att-max="${tool.max}"
id="slider" t-att-data-alt="${tool.alt}"/>
<input type="range" name="${tool.name}" data-unit="${tool.unit}"
value="${tool.default}" min="${tool.min}" max="${tool.max}"
id="slider" data-alt="${tool.alt}"/>
<span id="output"/>
</div>
</div>`
var customizeButton = document.querySelector('.button_cutomise');
customizeButton.appendChild(rangeDiv);
var rangeInput = document.getElementById('slider');
rangeInput.addEventListener('click', function () {
// Handle click event if needed
});
}
var SelectDiv = document.createElement("div");
SelectDiv.classList.add("optss", "infinito-remove");
if (tool.type == 'select') {
// Select type tool
SelectDiv.innerHTML = `<div class="b_slider">
<h6>
${tool.displayName}
</h6>
</div>`;
} else if (tool.type == 'select') {
newDiv.innerHTML = `<div class="b_slider">
<h6>${tool.displayName}</h6>
<div class="form-group">
<select class="form-control" id="select" t-att-name="${tool.name}" aria-label="Default select example" t-att-data-alt="${tool.alt}">
<t t-foreach="${tool.options}" t-as="option" t-key="option">
<option t-att-value="option"><t t-esc="option"/></option>
</t>
<select class="form-control" id="select" name="${tool.name}" aria-label="Default select example" data-alt="${tool.alt}">
${tool.options.map(option => `<option value="${option}">${option}</option>`).join('')}
</select>
</div>
</div>`;
var customizeButton = document.querySelector('.button_cutomise');
customizeButton.appendChild(SelectDiv);
}
var InputDiv = document.createElement("div");
InputDiv.classList.add("optss", "infinito-remove");
if (tool.type == 'input') {
// Input type tool
InputDiv.innerHTML = `<div class="b_slider">
<h6>
${tool.displayName}
</h6>
} else if (tool.type == 'input') {
newDiv.innerHTML = `<div class="b_slider">
<h6>${tool.displayName}</h6>
</div>
<ul class="b_style">
<li>
<input type="text" id="text" t-att-name="${tool.name}"
t-att-value="${tool.default}" t-att-placeholder="${tool.displayName}"
t-att-data-alt="${tool.alt}"/>
<input type="text" id="text" name="${tool.name}"
value="${tool.default}" placeholder="${tool.displayName}"
data-alt="${tool.alt}"/>
</li>
</ul>`
// Append the new tool to the DOM
var customizeButton = document.querySelector('.button_cutomise');
customizeButton.appendChild(InputDiv);
}
</ul>`;
}
return newDiv;
}
/**
@ -487,13 +458,18 @@ export class ThemeEditorSidebar extends Component {
*/
renderExistingTool(data) {
// Iterate over each rule in the data
const infinito = document.querySelector(".infinito-remove");
infinito.innerHTML = ''; // Clear existing content
for (var rule of data) {
// Find the corresponding tool based on the rule name
var current = NewTools.property.filter(tool => tool.name == rule[0].replace(' ', ''));
// Push the tool name to the current_tools array
this.current_tools.push(rule[0].replace(' ', ''));
// Render the new tool based on the found tool configuration
this.renderNewTool(current[0]);
if(current.length !=0){
var styleDiv = this.renderNewTool(current[0]);
infinito.appendChild(styleDiv);
}
}
}

2
backend_theme_infinito/static/src/js/variables.js

@ -1,9 +1,9 @@
/** @odoo-module **/
import { useState } from "@odoo/owl";
/**
* Object containing CSS variable names and their corresponding ranges for generating color variations.
* @type {Object.<string, number[]>}
*/
console.log("1234567327453245735")
const variables = {
"--bg_white": [1, 1],
"--bg_black": [5, 1],

8
backend_theme_infinito/static/src/json/presets.json

@ -17,7 +17,7 @@
{
"name": "Rounded",
"style": {
"background-color": "var(--primary_accent)",
"background-color": "var(--button-bg)",
"border-radius": "30px",
"color": "var(--bg_white)"
}
@ -40,7 +40,7 @@
"border-width": "1px",
"border-style": " solid",
"border-color": " var(--primary_accent)",
"color": "var(--primary_accent)",
"color": "var(--bg_white)",
"border-radius": "0"
}
},
@ -52,7 +52,7 @@
"border-style": " solid",
"border-color": " var(--primary_accent)",
"border-radius": "30px",
"color": "var(--primary_accent)"
"color": "var(--bg_white)"
}
},
{
@ -66,7 +66,7 @@
"border-top-right-radius": "20px",
"border-bottom-right-radius": "0px",
"border-bottom-left-radius": "20px",
"color": "var(--primary_accent)"
"color": "var(--bg_white)"
}
}
]

1
backend_theme_infinito/static/src/scss/sidebar.scss

@ -6,7 +6,6 @@ a#closeSidebar, a#openSidebar {
#sidebar_panel {
height: 100%;
position: fixed;
background-color: var(--tr-button-bg);
box-shadow: 0px 4px 11px 0px #888;
display: none;
width: 200px;

2
backend_theme_infinito/static/src/scss/theme_styles.scss

@ -158,7 +158,6 @@ background-color: white !important;
border-left-width: 12px;
}
.o_wrap_field > .o_cell >.o_field_widget > .o_field_tags > .rounded-pill{
background-color: var(--tr-button-bg) !important;
font-weight: 500 !important;
color: var(--button-bg) !important;
width: 63px !important;
@ -973,7 +972,6 @@ color: #fff;
background-color: var(--button-bg);
}
.o-dropdown.dropup > .o-dropdown--menu, .o-dropdown.dropdown > .o-dropdown--menu, .o-dropdown.dropleft > .o-dropdown--menu, .o-dropdown.dropright > .o-dropdown--menu {
left: auto !important;
}
o_list_renderer .o_list_table > thead > tr > :last-child, .o_list_renderer .o_list_table > tbody > tr > :last-child, .o_list_renderer .o_list_table > tfoot > tr > :last-child {
padding-right: var(--ListRenderer-table-padding-h);

1
backend_theme_infinito/static/src/scss/theme_variables.scss

@ -42,6 +42,7 @@ $dark_secondary_btn_hover_border: var(--dark_secondary_btn_hover_border) !defaul
--border-color: #dad6d6;
--button-bg-dark: #3b588a;
--button-bg-darker: #2b4269;
--primary_accent: #5279be;
}
$bg_white: var(--bg_white) !default;

30
backend_theme_infinito/static/src/xml/studio_elements.xml

@ -1,9 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<!--
This template defines a range input widget for the backend theme.
It allows users to adjust a value within a specified range.
-->
<t t-name="backend_theme_infinito.range">
<div class="optss infinito-remove">
<div class="b_slider">
@ -24,25 +20,18 @@
</div>
</div>
</t>
<!--
This template defines a color picker widget for the backend theme.
It allows users to select a color using a color picker input.
-->
<t t-name="backend_theme_infinito.color">
<div class="optss infinito-remove">
<div class="bg_color">
<h6 t-esc="widget.displayName"/>
<div class="color_picker">
<input class="favcolor" id="favcolor" type="color" t-att-name="widget.name" t-att-value="widget.default" property="color"
<input class="favcolor" id="favcolor" type="color" t-att-name="widget.name"
t-att-value="widget.default" property="color"
t-att-data-alt="widget.alt"/>
</div>
</div>
</div>
</t>
<!--
This template defines an input field widget for the backend theme.
It allows users to input text values.
-->
<t t-name="backend_theme_infinito.input">
<div class="optss">
<div class="b_slider">
@ -59,17 +48,18 @@
</ul>
</div>
</t>
<!--
This template defines a select dropdown widget for the backend theme.
It allows users to select options from a dropdown list.
-->
<t t-name="backend_theme_infinito.select">
<h6 class="infinito-remove"><t t-esc="widget.displayName"/></h6>
<h6 class="infinito-remove">
<t t-esc="widget.displayName"/>
</h6>
<div class="optss infinito-remove">
<div class="form-group">
<select class="form-control" id="select" t-att-name="widget.name" aria-label="Default select example" t-att-data-alt="widget.alt">
<select class="form-control" id="select" t-att-name="widget.name" aria-label="Default select example"
t-att-data-alt="widget.alt">
<t t-foreach="widget.options" t-as="option">
<option t-att-value="option"><t t-esc="option"/></option>
<option t-att-value="option">
<t t-esc="option"/>
</option>
</t>
</select>
</div>

12
backend_theme_infinito/static/src/xml/theme_editor.xml

@ -1,9 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<!--
Template for the theme editor in the backend theme.
It consists of a header, a main body, and a preview area.
-->
<t t-name="backend_theme_infinito.theme_editor">
<header class="main_header backend_theme_studio_menu theme_editor"/>
<section class="main_bodY backend_theme_studio_sidebar theme_editor">
@ -30,10 +26,6 @@
</div>
</section>
</t>
<!--
Template for the sidebar in the theme editor.
It contains options to customize the theme elements.
-->
<t t-name="backend_theme_infinito.theme_editor_sidebar">
<div id="theme_editor_sidebar" class="main_sidebar">
<div class="toggle-btn">
@ -123,10 +115,6 @@
</div>
</div>
</t>
<!--
Template for the advanced theme settings.
This template contains options for adjusting various settings such as time, hours, minutes, and periods.
-->
<t t-name="backend_theme_infinito.theme_advance" owl="1">
<div id="tp-wrap" class="d-none">
<div id="tp-box">

Loading…
Cancel
Save