diff --git a/odex30_base/expert_theme/__manifest__.py b/odex30_base/expert_theme/__manifest__.py index dca6dbc..c64bbad 100644 --- a/odex30_base/expert_theme/__manifest__.py +++ b/odex30_base/expert_theme/__manifest__.py @@ -33,6 +33,7 @@ 'expert_theme/static/src/scss/expert_login.scss', 'expert_theme/static/src/scss/login_minimal.scss', 'expert_theme/static/src/js/expert_login_template.js', + 'expert_theme/static/src/scss/frontend.scss', ], 'web.assets_backend': [ 'expert_theme/static/src/fonts/en_fonts.scss', diff --git a/odex30_base/expert_theme/controllers/main.py b/odex30_base/expert_theme/controllers/main.py index fc6cbac..d8ac941 100644 --- a/odex30_base/expert_theme/controllers/main.py +++ b/odex30_base/expert_theme/controllers/main.py @@ -10,8 +10,7 @@ class IntroLoaderController(http.Controller): img_b64 = request.env['ir.config_parameter'].sudo().get_param('intro_loader.image_data') if not img_b64: - # Return a 1x1 transparent pixel or default Odoo logo if none set - return request.redirect('/web/static/img/logo2.png') + return request.redirect('/expert_theme/static/src/img/logo.webp') image_data = base64.b64decode(img_b64) headers = [('Content-Type', 'image/png')] diff --git a/odex30_base/expert_theme/models/res_config_settings.py b/odex30_base/expert_theme/models/res_config_settings.py index d6023cc..e9dd3e0 100644 --- a/odex30_base/expert_theme/models/res_config_settings.py +++ b/odex30_base/expert_theme/models/res_config_settings.py @@ -8,6 +8,17 @@ class ResConfigSettings(models.TransientModel): # Text Configuration intro_loader_text = fields.Char(string="Loader Text", config_parameter='intro_loader.text', default="Loading...") intro_loader_show_text = fields.Boolean(string="Show Text", config_parameter='intro_loader.show_text') + # Text Styling + intro_loader_text_color = fields.Char( + string="Text Color", + config_parameter='intro_loader.text_color', + default="#6c757d" # Standard Bootstrap muted gray + ) + intro_loader_text_size = fields.Integer( + string="Text Size (px)", + config_parameter='intro_loader.text_size', + default=24 + ) # Spinner Configuration intro_loader_show_spinner = fields.Boolean(string="Show Spinner", config_parameter='intro_loader.show_spinner') @@ -21,6 +32,20 @@ class ResConfigSettings(models.TransientModel): ('none', 'Static') ], string="Image Animation", config_parameter='intro_loader.animation', default='pulse') + # Exit Animation Configuration + intro_loader_exit_type = fields.Selection([ + ('fade', 'Fade Out'), + ('slide_up', 'Slide Up (Curtain)'), + ('zoom_out', 'Zoom Out'), + ('circle_mask', 'Circle Mask') + ], string="Exit Animation", config_parameter='intro_loader.exit_type', default='fade') + + intro_loader_exit_duration = fields.Float( + string="Exit Duration (Seconds)", + config_parameter='intro_loader.exit_duration', + default=0.8 + ) + @api.model def get_values(self): res = super(ResConfigSettings, self).get_values() diff --git a/odex30_base/expert_theme/static/src/img/logo.webp b/odex30_base/expert_theme/static/src/img/logo.webp new file mode 100644 index 0000000..f737c38 Binary files /dev/null and b/odex30_base/expert_theme/static/src/img/logo.webp differ diff --git a/odex30_base/expert_theme/static/src/js/intro_loader.js b/odex30_base/expert_theme/static/src/js/intro_loader.js index 9996b41..93adc27 100644 --- a/odex30_base/expert_theme/static/src/js/intro_loader.js +++ b/odex30_base/expert_theme/static/src/js/intro_loader.js @@ -9,26 +9,23 @@ patch(WebClient.prototype, { super.setup(); onMounted(() => { - // Select the loader element const loader = document.getElementById("o_intro_loader"); if (loader) { - // Optional: Check sessionStorage if you want it ONCE per browser session - // const hasLoaded = sessionStorage.getItem('odoo_intro_shown'); - - // Add the hidden class to trigger CSS transition - // We add a small delay (e.g., 500ms) to ensure the UI is visually stable behind it + // Read duration from HTML attribute (default to 800ms if missing) + const duration = parseInt(loader.dataset.durationMs) || 800; + + // Add delay for visual stability (optional 500ms) setTimeout(() => { - loader.classList.add("o_hidden"); + // Trigger CSS animation + loader.classList.add("o_hiddens"); - // Cleanup DOM after animation finishes (optional but cleaner) + // Remove from DOM exactly when animation finishes setTimeout(() => { loader.remove(); - }, 1000); + }, duration + 100); // +100ms buffer }, 500); - - // sessionStorage.setItem('odoo_intro_shown', 'true'); } }); } diff --git a/odex30_base/expert_theme/static/src/scss/expert_theme.scss b/odex30_base/expert_theme/static/src/scss/expert_theme.scss index 026ff27..e86df56 100644 --- a/odex30_base/expert_theme/static/src/scss/expert_theme.scss +++ b/odex30_base/expert_theme/static/src/scss/expert_theme.scss @@ -376,4 +376,4 @@ body { .expert-home-container { padding: 15px; } -} \ No newline at end of file +} diff --git a/odex30_base/expert_theme/static/src/scss/frontend.scss b/odex30_base/expert_theme/static/src/scss/frontend.scss new file mode 100644 index 0000000..5c35e8a --- /dev/null +++ b/odex30_base/expert_theme/static/src/scss/frontend.scss @@ -0,0 +1,3 @@ +.o_loader_content{ + display: none !important; +} \ No newline at end of file diff --git a/odex30_base/expert_theme/static/src/scss/intro_loader.scss b/odex30_base/expert_theme/static/src/scss/intro_loader.scss index f416be7..59e63ff 100644 --- a/odex30_base/expert_theme/static/src/scss/intro_loader.scss +++ b/odex30_base/expert_theme/static/src/scss/intro_loader.scss @@ -6,7 +6,10 @@ display: flex; align-items: center; justify-content: center; - transition: opacity 0.8s ease-out, visibility 0.8s; + + /* Default Transition Base */ + transition-timing-function: ease-in-out; + transition-duration: var(--exit-duration, 0.8s); /* Use dynamic var */ .o_loader_content { display: flex; @@ -33,10 +36,45 @@ animation: loader-spin 1s linear infinite; } - &.o_hidden { - opacity: 0; - visibility: hidden; - pointer-events: none; + // &.o_hiddens { + // opacity: 0; + // visibility: hidden; + // pointer-events: none; + // } + + /* 1. Fade Out */ + &.exit-fade { + transition-property: opacity, visibility; + &.o_hiddens { + opacity: 0; + // visibility: hidden; + } + } + + /* 2. Slide Up (Curtain) */ + &.exit-slide_up { + transition-property: transform; + &.o_hiddens { + transform: translateY(-100%); + } + } + + /* 3. Zoom Out */ + &.exit-zoom_out { + transition-property: opacity, transform; + &.o_hiddens { + opacity: 0; + transform: scale(1.5); /* Expands out while fading */ + } + } + + /* 4. Circle Mask (Advanced CSS Clip Path) */ + &.exit-circle_mask { + transition-property: clip-path; + clip-path: circle(150% at 50% 50%); + &.o_hiddens { + clip-path: circle(0% at 50% 50%); + } } } diff --git a/odex30_base/expert_theme/views/res_config_settings_views.xml b/odex30_base/expert_theme/views/res_config_settings_views.xml index b7c294d..0bff925 100644 --- a/odex30_base/expert_theme/views/res_config_settings_views.xml +++ b/odex30_base/expert_theme/views/res_config_settings_views.xml @@ -6,24 +6,38 @@ - - - + + + + + + + + + + + diff --git a/odex30_base/expert_theme/views/web_layout.xml b/odex30_base/expert_theme/views/web_layout.xml index 3f26ec8..f2184a8 100644 --- a/odex30_base/expert_theme/views/web_layout.xml +++ b/odex30_base/expert_theme/views/web_layout.xml @@ -2,25 +2,43 @@ - - - - - - - + + + + + + + + + + + + + + + - - - + - - + diff --git a/odex30_base/odex_sidebar_backend_theme2/static/src/img/logo.webp b/odex30_base/odex_sidebar_backend_theme2/static/src/img/logo.webp new file mode 100644 index 0000000..f737c38 Binary files /dev/null and b/odex30_base/odex_sidebar_backend_theme2/static/src/img/logo.webp differ diff --git a/odex30_base/odex_sidebar_backend_theme2/static/src/img/logo1.png b/odex30_base/odex_sidebar_backend_theme2/static/src/img/logo1.png deleted file mode 100644 index cd74056..0000000 Binary files a/odex30_base/odex_sidebar_backend_theme2/static/src/img/logo1.png and /dev/null differ diff --git a/odex30_base/odex_sidebar_backend_theme2/static/src/js/sidebar_menu.js b/odex30_base/odex_sidebar_backend_theme2/static/src/js/sidebar_menu.js index 512cb6e..2d01942 100644 --- a/odex30_base/odex_sidebar_backend_theme2/static/src/js/sidebar_menu.js +++ b/odex30_base/odex_sidebar_backend_theme2/static/src/js/sidebar_menu.js @@ -116,7 +116,7 @@ export class SidebarMenu extends Component { } // Load sidebar menu icon URL - this.state.sidebarMenuIconUrl = result.sidebar_icon_url || '/odex_sidebar_backend_theme2/static/src/img/logo1.png'; + this.state.sidebarMenuIconUrl = result.sidebar_icon_url || '/odex_sidebar_backend_theme2/static/src/img/logo.webp'; } catch (error) { console.error('Error loading sidebar setting:', error); diff --git a/odex30_base/odex_sidebar_backend_theme2/views/res_config_settings.xml b/odex30_base/odex_sidebar_backend_theme2/views/res_config_settings.xml index 3691463..aced0d6 100644 --- a/odex30_base/odex_sidebar_backend_theme2/views/res_config_settings.xml +++ b/odex30_base/odex_sidebar_backend_theme2/views/res_config_settings.xml @@ -9,31 +9,17 @@ + + + + + + - - - - - Enable or disable the sidebar menu in the backend - interface - - - - - - - Enable or disable the top navigation bar menu section - in the backend interface - - - - - - - - - + + +