From 575bb504ee896bf02a1181992e1881c253fe8ed4 Mon Sep 17 00:00:00 2001 From: Altahir Hassan Date: Mon, 5 Jan 2026 15:58:18 +0400 Subject: [PATCH] Remove multiple login and signup templates from expert_theme, consolidating to a more streamlined design approach. --- odex30_base/expert_theme/__manifest__.py | 42 +- .../controllers/expert_controller.py | 144 +-- .../models/expert_login_template.py | 46 +- .../expert_theme/static/description/icon.png | Bin 0 -> 41639 bytes .../static/src/css/login_minimal.css | 269 ----- .../static/src/css/login_modern.css | 234 ---- .../expert_login.scss} | 0 .../expert_theme.scss} | 8 +- .../expert_theme_config.scss} | 0 .../static/src/scss/login_minimal.scss | 280 +++++ .../static/src/scss/login_modern.scss | 312 ++--- .../expert_theme/views/expert_home_views.xml | 1 - .../expert_theme/views/expert_menu_views.xml | 56 +- .../expert_theme/views/login_templates.xml | 1033 ++++------------- .../views/login_templates_temp.xml | 785 ------------- 15 files changed, 737 insertions(+), 2473 deletions(-) create mode 100644 odex30_base/expert_theme/static/description/icon.png delete mode 100644 odex30_base/expert_theme/static/src/css/login_minimal.css delete mode 100644 odex30_base/expert_theme/static/src/css/login_modern.css rename odex30_base/expert_theme/static/src/{css/expert_login.css => scss/expert_login.scss} (100%) rename odex30_base/expert_theme/static/src/{css/expert_theme.css => scss/expert_theme.scss} (98%) rename odex30_base/expert_theme/static/src/{css/expert_theme_config.css => scss/expert_theme_config.scss} (100%) create mode 100644 odex30_base/expert_theme/static/src/scss/login_minimal.scss delete mode 100644 odex30_base/expert_theme/views/login_templates_temp.xml diff --git a/odex30_base/expert_theme/__manifest__.py b/odex30_base/expert_theme/__manifest__.py index fd5b3b7..0a5f8d3 100644 --- a/odex30_base/expert_theme/__manifest__.py +++ b/odex30_base/expert_theme/__manifest__.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- { 'name': 'Expert Theme', - 'version': '18.0.1.0.0', - 'category': 'Theme/Backend', + 'version': '1.0.0', + 'category': 'Themes', 'summary': 'Custom backend theme with installed modules home page', 'description': """ Expert Theme @@ -14,8 +14,8 @@ - Easy navigation to installed applications """, 'author': 'Expert', - 'website': '', - 'depends': ['base', 'web'], + 'website': 'https://www.exp-sa.com', + 'depends': ['base', 'web','website'], 'data': [ 'security/ir.model.access.csv', 'data/expert_login_template_data.xml', @@ -25,23 +25,23 @@ 'views/expert_home_views.xml', 'views/expert_menu_views.xml', ], - 'assets': { - 'web.assets_backend': [ - 'expert_theme/static/src/css/expert_theme_config.css', - 'expert_theme/static/src/css/expert_theme.css', - 'expert_theme/static/src/js/expert_theme_dynamic.js', - 'expert_theme/static/src/js/expert_theme_config.js', - 'expert_theme/static/src/js/expert_home.js', - 'expert_theme/static/src/js/expert_login_template_list.js', - 'expert_theme/static/src/xml/expert_home.xml', - ], - 'web.assets_frontend': [ - 'expert_theme/static/src/css/expert_login.css', - 'expert_theme/static/src/css/login_modern.css', - 'expert_theme/static/src/css/login_minimal.css', - 'expert_theme/static/src/js/expert_login_template.js', - ], - }, + 'assets': { + 'web.assets_frontend': [ + 'expert_theme/static/src/scss/login_modern.scss', + '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', + ], + 'web.assets_backend': [ + 'expert_theme/static/src/scss/expert_theme_config.scss', + 'expert_theme/static/src/scss/expert_theme.scss', + 'expert_theme/static/src/js/expert_theme_dynamic.js', + 'expert_theme/static/src/js/expert_theme_config.js', + 'expert_theme/static/src/js/expert_home.js', + 'expert_theme/static/src/js/expert_login_template_list.js', + 'expert_theme/static/src/xml/expert_home.xml', + ] + }, 'installable': True, 'auto_install': False, 'application': False, diff --git a/odex30_base/expert_theme/controllers/expert_controller.py b/odex30_base/expert_theme/controllers/expert_controller.py index 4f5b646..83365c2 100644 --- a/odex30_base/expert_theme/controllers/expert_controller.py +++ b/odex30_base/expert_theme/controllers/expert_controller.py @@ -55,46 +55,6 @@ class ExpertController(http.Controller): 'error': str(e) }) - @http.route('/web/login', type='http', auth='none', methods=['GET', 'POST'], csrf=False) - def web_login(self, redirect=None, **kw): - """Override Odoo login to use expert login templates when configured. - - - POST: delegate to standard Odoo login logic (authentication, redirects, etc.). - - GET: render the active expert login template if not 'default', otherwise use standard login. - """ - # Import Home from its new location in Odoo 18 - from odoo.addons.web.controllers.home import Home - - # Handle login submission via standard controller - if request.httprequest.method == 'POST': - home = Home() - return home.web_login(redirect=redirect, **kw) - - # GET: decide which template to render - try: - login_template = request.env['expert.login.template'].sudo().get_active_template() - template_name = login_template.get_template_name() - except Exception as e: - _logger.error("Error getting active login template: %s", e) - template_name = 'web.login' - - # For default template, just call the standard login - if template_name == 'web.login': - home = Home() - return home.web_login(redirect=redirect, **kw) - - # Try to render the selected expert template; fall back to default on error - try: - return request.render(template_name, { - 'redirect': redirect or '', - 'login': kw.get('login', ''), - 'login_template': login_template, - }) - except Exception as e: - _logger.error("Error rendering login template '%s': %s", template_name, e) - home = Home() - return home.web_login(redirect=redirect, **kw) - @http.route('/expert_theme/get_login_template_styles', type='http', auth='public', methods=['GET']) def get_login_template_styles(self): """Get CSS styles for the active login template (public access for login page)""" @@ -181,106 +141,4 @@ class ExpertController(http.Controller): 'error': str(e) }) - @http.route('/web/signup', type='http', auth='public', methods=['GET', 'POST'], website=True, csrf=False) - def web_auth_signup(self, redirect=None, **kw): - """Override Odoo signup to use expert signup templates when modern template is active. - - - POST: delegate to standard Odoo signup logic (authentication, redirects, etc.). - - GET: render the active expert signup template if modern template is active, otherwise use standard signup. - """ - # Import AuthSignupHome from auth_signup module - try: - from odoo.addons.auth_signup.controllers.main import AuthSignupHome - except ImportError: - # If auth_signup is not installed, return 404 - from werkzeug.exceptions import NotFound - raise NotFound() - - # Handle signup submission via standard controller - if request.httprequest.method == 'POST': - auth_signup_home = AuthSignupHome() - return auth_signup_home.web_auth_signup(redirect=redirect, **kw) - - # GET: decide which template to render - try: - login_template = request.env['expert.login.template'].sudo().get_active_template() - template_name = login_template.get_signup_template_name() - except Exception as e: - _logger.error("Error getting active signup template: %s", e) - template_name = 'auth_signup.signup' - - # For default template, just call the standard signup - if template_name == 'auth_signup.signup': - auth_signup_home = AuthSignupHome() - return auth_signup_home.web_auth_signup(redirect=redirect, **kw) - - # Try to render the selected expert template; fall back to default on error - try: - # Get signup context from auth_signup - auth_signup_home = AuthSignupHome() - qcontext = auth_signup_home.get_auth_signup_qcontext() - qcontext.update({ - 'redirect': redirect or '', - 'login': kw.get('login', ''), - 'login_template': login_template, - }) - response = request.render(template_name, qcontext) - response.headers['X-Frame-Options'] = 'SAMEORIGIN' - response.headers['Content-Security-Policy'] = "frame-ancestors 'self'" - return response - except Exception as e: - _logger.error("Error rendering signup template '%s': %s", template_name, e) - auth_signup_home = AuthSignupHome() - return auth_signup_home.web_auth_signup(redirect=redirect, **kw) - - @http.route('/web/reset_password', type='http', auth='public', methods=['GET', 'POST'], website=True, csrf=False) - def web_auth_reset_password(self, redirect=None, **kw): - """Override Odoo reset password to use expert reset password templates when modern template is active. - - - POST: delegate to standard Odoo reset password logic (authentication, redirects, etc.). - - GET: render the active expert reset password template if modern template is active, otherwise use standard reset password. - """ - # Import AuthSignupHome from auth_signup module - try: - from odoo.addons.auth_signup.controllers.main import AuthSignupHome - except ImportError: - # If auth_signup is not installed, return 404 - from werkzeug.exceptions import NotFound - raise NotFound() - - # Handle reset password submission via standard controller - if request.httprequest.method == 'POST': - auth_signup_home = AuthSignupHome() - return auth_signup_home.web_auth_reset_password(redirect=redirect, **kw) - - # GET: decide which template to render - try: - login_template = request.env['expert.login.template'].sudo().get_active_template() - template_name = login_template.get_reset_password_template_name() - except Exception as e: - _logger.error("Error getting active reset password template: %s", e) - template_name = 'auth_signup.reset_password' - - # For default template, just call the standard reset password - if template_name == 'auth_signup.reset_password': - auth_signup_home = AuthSignupHome() - return auth_signup_home.web_auth_reset_password(redirect=redirect, **kw) - - # Try to render the selected expert template; fall back to default on error - try: - # Get reset password context from auth_signup - auth_signup_home = AuthSignupHome() - qcontext = auth_signup_home.get_auth_signup_qcontext() - qcontext.update({ - 'redirect': redirect or '', - 'login': kw.get('login', ''), - 'login_template': login_template, - }) - response = request.render(template_name, qcontext) - response.headers['X-Frame-Options'] = 'SAMEORIGIN' - response.headers['Content-Security-Policy'] = "frame-ancestors 'self'" - return response - except Exception as e: - _logger.error("Error rendering reset password template '%s': %s", template_name, e) - auth_signup_home = AuthSignupHome() - return auth_signup_home.web_auth_reset_password(redirect=redirect, **kw) + \ No newline at end of file diff --git a/odex30_base/expert_theme/models/expert_login_template.py b/odex30_base/expert_theme/models/expert_login_template.py index a17dce2..1d3c1da 100644 --- a/odex30_base/expert_theme/models/expert_login_template.py +++ b/odex30_base/expert_theme/models/expert_login_template.py @@ -9,7 +9,7 @@ class ExpertLoginTemplate(models.Model): _rec_name = 'name' _order = 'sequence, name' - name = fields.Char(string='Template Name', required=True, help='Name of the login page template') + name = fields.Char(string='Template Name', required=True, translate=True, help='Name of the login page template') active = fields.Boolean(string='Active', default=False, help='Only one template can be active at a time. Activate this template to use it on the login page.') sequence = fields.Integer(string='Sequence', default=10, help='Order of display') @@ -37,47 +37,47 @@ class ExpertLoginTemplate(models.Model): corporate_template_logo = fields.Binary(string='Corporate Template Logo', help='Company logo to display on Corporate login, signup, and reset password pages') # Modern Template Text Fields - modern_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', help='Title text for Modern template login page') - modern_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', help='Subtitle text for Modern template login page') - modern_login_button_text = fields.Char(string='Login Button Text', default='Sign In', help='Button text for Modern template login page') + modern_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', translate=True, help='Title text for Modern template login page') + modern_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', translate=True, help='Subtitle text for Modern template login page') + modern_login_button_text = fields.Char(string='Login Button Text', default='Sign In', translate=True, help='Button text for Modern template login page') modern_login_button_bg_color = fields.Char(string='Login Button Background', default='#007bff', help='Background color for login button') modern_login_button_text_color = fields.Char(string='Login Button Text Color', default='#FFFFFF', help='Text color for login button') modern_login_button_bg_hover = fields.Char(string='Login Button BG Hover', default='#0056b3', help='Background color for login button on hover') modern_login_button_text_hover = fields.Char(string='Login Button Text Hover', default='#FFFFFF', help='Text color for login button on hover') - modern_signup_title = fields.Char(string='Signup Title', default='Create an account', help='Title text for Modern template signup page') - modern_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', help='Subtitle text for Modern template signup page') - modern_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', help='Button text for Modern template signup page') + modern_signup_title = fields.Char(string='Signup Title', default='Create an account', translate=True, help='Title text for Modern template signup page') + modern_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', translate=True, help='Subtitle text for Modern template signup page') + modern_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', translate=True, help='Button text for Modern template signup page') modern_signup_button_bg_color = fields.Char(string='Signup Button Background', default='#28a745', help='Background color for signup button') modern_signup_button_text_color = fields.Char(string='Signup Button Text Color', default='#FFFFFF', help='Text color for signup button') modern_signup_button_bg_hover = fields.Char(string='Signup Button BG Hover', default='#218838', help='Background color for signup button on hover') modern_signup_button_text_hover = fields.Char(string='Signup Button Text Hover', default='#FFFFFF', help='Text color for signup button on hover') - modern_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', help='Title text for Modern template reset password page') - modern_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', help='Subtitle text for Modern template reset password page') + modern_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', translate=True, help='Title text for Modern template reset password page') + modern_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', translate=True, help='Subtitle text for Modern template reset password page') # Minimal Template Text Fields - minimal_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', help='Title text for Minimal template login page') - minimal_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', help='Subtitle text for Minimal template login page') - minimal_login_button_text = fields.Char(string='Login Button Text', default='Sign In', help='Button text for Minimal template login page') + minimal_login_title = fields.Char(string='Login Title', default='Welcome to Expert 👋', translate=True, help='Title text for Minimal template login page') + minimal_login_subtitle = fields.Char(string='Login Subtitle', default='Kindly fill in your details below to sign in to your account', translate=True, help='Subtitle text for Minimal template login page') + minimal_login_button_text = fields.Char(string='Login Button Text', default='Sign In', translate=True, help='Button text for Minimal template login page') minimal_login_button_bg_color = fields.Char(string='Login Button Background', default='#E5E5E5', help='Background color for login button') minimal_login_button_text_color = fields.Char(string='Login Button Text Color', default='#000000', help='Text color for login button') minimal_login_button_bg_hover = fields.Char(string='Login Button BG Hover', default='#D0D0D0', help='Background color for login button on hover') minimal_login_button_text_hover = fields.Char(string='Login Button Text Hover', default='#000000', help='Text color for login button on hover') - minimal_signup_title = fields.Char(string='Signup Title', default='Create an account', help='Title text for Minimal template signup page') - minimal_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', help='Subtitle text for Minimal template signup page') - minimal_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', help='Button text for Minimal template signup page') + minimal_signup_title = fields.Char(string='Signup Title', default='Create an account', translate=True, help='Title text for Minimal template signup page') + minimal_signup_subtitle = fields.Char(string='Signup Subtitle', default='Join us today and get started', translate=True, help='Subtitle text for Minimal template signup page') + minimal_signup_button_text = fields.Char(string='Signup Button Text', default='Create an account', translate=True, help='Button text for Minimal template signup page') minimal_signup_button_bg_color = fields.Char(string='Signup Button Background', default='#000000', help='Background color for signup button') minimal_signup_button_text_color = fields.Char(string='Signup Button Text Color', default='#FFFFFF', help='Text color for signup button') minimal_signup_button_bg_hover = fields.Char(string='Signup Button BG Hover', default='#333333', help='Background color for signup button on hover') minimal_signup_button_text_hover = fields.Char(string='Signup Button Text Hover', default='#FFFFFF', help='Text color for signup button on hover') - minimal_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', help='Title text for Minimal template reset password page') - minimal_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', help='Subtitle text for Minimal template reset password page') + minimal_reset_title = fields.Char(string='Reset Password Title', default='Reset your password', translate=True, help='Title text for Minimal template reset password page') + minimal_reset_subtitle = fields.Char(string='Reset Password Subtitle', default='Enter your email to receive reset instructions', translate=True, help='Subtitle text for Minimal template reset password page') # Description - description = fields.Text(string='Description', help='Description of this template') + description = fields.Text(string='Description', translate=True, help='Description of this template') @api.model def get_active_template(self): @@ -111,13 +111,14 @@ class ExpertLoginTemplate(models.Model): def create(self, vals): """Ensure only one template is active at a time""" # If no active value is set, default to False (don't auto-activate new templates) - if 'active' not in vals: - vals['active'] = False + if 'active' not in vals[0]: + vals[0]['active'] = False # Only deactivate others if this one is being set to active - if vals.get('active'): + print(vals[0]) + if vals[0].get('active'): # Deactivate all other templates (excluding the one being created) self.search([('active', '=', True)]).write({'active': False}) - return super(ExpertLoginTemplate, self).create(vals) + return super(ExpertLoginTemplate, self).create(vals[0]) def write(self, vals): """Ensure only one template is active at a time""" @@ -133,6 +134,7 @@ class ExpertLoginTemplate(models.Model): super(ExpertLoginTemplate, other_templates).write({'active': False}) need_reload = True + view = self.env.ref('custom_auth_theme.view_custom_login_inherit', raise_if_not_found=False) result = super(ExpertLoginTemplate, self).write(vals) # Update template views if active state changed diff --git a/odex30_base/expert_theme/static/description/icon.png b/odex30_base/expert_theme/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d3b8d45a7512d5e2b7f508c0e9002bac12730f4f GIT binary patch literal 41639 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 literal 0 HcmV?d00001 diff --git a/odex30_base/expert_theme/static/src/css/login_minimal.css b/odex30_base/expert_theme/static/src/css/login_minimal.css deleted file mode 100644 index df4cbc8..0000000 --- a/odex30_base/expert_theme/static/src/css/login_minimal.css +++ /dev/null @@ -1,269 +0,0 @@ -/* Expert Theme - Minimal Login Template Styles */ - -.expert-login-minimal { - background: #FFFFFF; - min-height: 100vh; - padding: 20px; -} - -.expert-login-minimal .container-fluid { - height: calc(100vh - 40px); -} - -.expert-login-minimal .row { - height: 100%; - margin: 0; -} - -/* Left Column: Login Form */ -.expert-login-minimal .expert-login-left { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - padding: 40px; - text-align: center; -} - -/* Logo Section */ -.expert-login-minimal .expert-login-logo { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 40px; - width: 100%; -} - -.expert-login-minimal .expert-login-logo .expert-logo-icon { - width: 40px; - height: 40px; - background: #000000; - border-radius: 8px; - margin-right: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.expert-login-minimal .expert-login-logo .expert-logo-icon span { - color: white; - font-weight: bold; - font-size: 20px; -} - -.expert-login-minimal .expert-login-logo .expert-logo-text { - color: #000000; - font-size: 20px; - font-weight: 600; -} - -/* Welcome Section */ -.expert-login-minimal .expert-login-welcome { - width: 100%; - text-align: center; - margin-bottom: 40px; -} - -.expert-login-minimal .expert-login-welcome h1 { - color: #000000; - font-size: 32px; - font-weight: 700; - margin-bottom: 12px; - line-height: 1.2; - text-align: center; -} - -.expert-login-minimal .expert-login-welcome h1 .welcome-emoji { - font-size: 32px; -} - -.expert-login-minimal .expert-login-welcome p { - color: rgba(0, 0, 0, 0.7); - font-size: 16px; - margin-bottom: 0; - text-align: center; -} - -/* Form Section */ -.expert-login-minimal .expert-login-form { - max-width: 450px; - width: 100%; - margin: 0 auto; - background-color: transparent !important; -} - -.expert-login-minimal .expert-login-form .form-group { - margin-bottom: 24px; -} - -.expert-login-minimal .expert-login-form .form-group label { - font-weight: 500; - color: #000000; - display: block; - margin-bottom: 8px; - font-size: 14px; - text-align: start; -} - -.expert-login-minimal .expert-login-form .form-group input[type="text"], -.expert-login-minimal .expert-login-form .form-group input[type="password"] { - background: #FFFFFF !important; - border: 1px solid #000000 !important; - border-radius: 8px; - padding: 12px 16px; - width: 100%; - box-sizing: border-box; - color: #000000 !important; - font-size: 14px; -} - -.expert-login-minimal .expert-login-form .form-group input[type="text"]::placeholder, -.expert-login-minimal .expert-login-form .form-group input[type="password"]::placeholder { - color: rgba(0, 0, 0, 0.5) !important; -} - -.expert-login-minimal .expert-login-form .form-group input[type="text"]:focus, -.expert-login-minimal .expert-login-form .form-group input[type="password"]:focus { - background: #FFFFFF !important; - border-color: #000000 !important; - outline: none; - color: #000000 !important; -} - -.expert-login-minimal .expert-login-form .form-check { - margin-bottom: 32px; -} - -.expert-login-minimal .expert-login-form .form-check label { - color: #000000; - display: flex; - align-items: center; - justify-content: flex-start; - flex-wrap: wrap; - gap: 5px; - font-size: 14px; - cursor: pointer; -} - -.expert-login-minimal .expert-login-form .form-check label input[type="checkbox"] { - margin-right: 8px; - width: 18px; - height: 18px; - cursor: pointer; - accent-color: #000000; -} - -.expert-login-minimal .expert-login-form button[type="submit"] { - width: 100%; - background: #E5E5E5; - border: none; - border-radius: 8px; - padding: 14px; - font-weight: 600; - color: #000000; - font-size: 16px; - cursor: pointer; - transition: background 0.2s; -} - -.expert-login-minimal .expert-login-form button[type="submit"]:hover { - background: #D5D5D5; -} - -.expert-login-minimal .expert-login-form button[type="submit"]:active { - background: #CCCCCC; -} - -/* Login Link Section */ -.expert-login-minimal .expert-login-link { - margin-top: 24px; - max-width: 450px; - width: 100%; - text-align: center; -} - -.expert-login-minimal .expert-login-link p { - color: rgba(0, 0, 0, 0.7); - font-size: 14px; - margin: 0; -} - -.expert-login-minimal .expert-login-link p a { - color: #000000; - text-decoration: underline; - font-weight: 500; -} - -.expert-login-minimal .expert-login-link p a:hover { - text-decoration: none; -} - -/* Right Column: Image Section */ -.expert-login-minimal .expert-login-right { - padding: 0; - height: 100%; - overflow: hidden; - border-radius: 0; -} - -.expert-login-minimal .expert-login-right .expert-login-image { - width: 100%; - height: 100%; - background: #FFFFFF; - display: flex; - align-items: center; - justify-content: center; - position: relative; -} - -.expert-login-minimal .expert-login-right .expert-login-image img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.expert-login-minimal .expert-minimal-illustration { - width: 600px !important; - height: 600px !important; - object-fit: contain; -} - -/* Alert Messages */ -.expert-login-minimal .alert { - border-radius: 8px; - padding: 12px 16px; - margin-bottom: 20px; - text-align: start; -} - -.expert-login-minimal .alert-danger { - background-color: #F8D7DA; - border: 1px solid #F5C6CB; - color: #721C24; -} - -.expert-login-minimal .alert-success { - background-color: #D4EDDA; - border: 1px solid #C3E6CB; - color: #155724; -} - -/* Responsive adjustments */ -@media (max-width: 991.98px) { - .expert-login-minimal .expert-login-left { - padding: 30px 20px; - } - - .expert-login-minimal .expert-login-welcome h1 { - font-size: 28px; - } - - .expert-login-minimal .expert-login-welcome h1 .welcome-emoji { - font-size: 28px; - } - - .expert-login-minimal .expert-login-welcome p { - font-size: 14px; - } -} - diff --git a/odex30_base/expert_theme/static/src/css/login_modern.css b/odex30_base/expert_theme/static/src/css/login_modern.css deleted file mode 100644 index 8bd771b..0000000 --- a/odex30_base/expert_theme/static/src/css/login_modern.css +++ /dev/null @@ -1,234 +0,0 @@ -/* Expert Theme - Modern Login Template Styles */ - -.expert-login-modern { - background: #19181F !important; - min-height: 100vh; - padding: 20px; -} - -.expert-login-modern .container-fluid { - height: calc(100vh - 40px); -} - -.expert-login-modern .row { - height: 100%; - margin: 0; -} - -/* Left Column: Login Form */ -.expert-login-modern .expert-login-left { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - padding: 40px; - text-align: center; -} - -/* Logo Section */ -.expert-login-modern .expert-login-logo { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 40px; - width: 100%; -} - -.expert-login-modern .expert-login-logo .expert-logo-icon { - width: 40px; - height: 40px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - border-radius: 8px; - margin-right: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.expert-login-modern .expert-login-logo .expert-logo-icon span { - color: white; - font-weight: bold; - font-size: 20px; -} - -.expert-login-modern .expert-login-logo .expert-logo-text { - color: white; - font-size: 20px; - font-weight: 600; -} - -/* Welcome Section */ -.expert-login-modern .expert-login-welcome { - width: 100%; - text-align: center; -} - -.expert-login-modern .expert-login-welcome h1 { - color: white; - font-size: 36px; - font-weight: 700; - margin-bottom: 12px; - line-height: 1.2; - text-align: center; -} - -.expert-login-modern .expert-login-welcome h1 .welcome-emoji { - font-size: 36px; -} - -.expert-login-modern .expert-login-welcome p { - color: rgba(255, 255, 255, 0.7); - font-size: 16px; - margin-bottom: 40px; - text-align: center; -} - -/* Form Section */ -.expert-login-modern .expert-login-form { - max-width: 450px; - width: 100%; - margin: 0 auto; - background-color: transparent !important; -} - -.expert-login-modern .expert-login-form .form-group { - margin-bottom: 24px; -} - -.expert-login-modern .expert-login-form .form-group label { - font-weight: 500; - color: rgba(255, 255, 255, 0.9); - display: block; - margin-bottom: 8px; - font-size: 14px; - text-align: start; -} - -.expert-login-modern .expert-login-form .form-group input[type="text"], -.expert-login-modern .expert-login-form .form-group input[type="password"] { - background: rgba(255, 255, 255, 0.1) !important; - border: 1px solid rgba(255, 255, 255, 0.2) !important; - border-radius: 8px; - padding: 12px 16px; - width: 100%; - box-sizing: border-box; - color: white !important; - font-size: 14px; -} - -.expert-login-modern .expert-login-form .form-group input[type="text"]::placeholder, -.expert-login-modern .expert-login-form .form-group input[type="password"]::placeholder { - color: rgba(255, 255, 255, 0.5) !important; -} - -.expert-login-modern .expert-login-form .form-group input[type="text"]:focus, -.expert-login-modern .expert-login-form .form-group input[type="password"]:focus { - background: rgba(255, 255, 255, 0.15) !important; - border-color: rgba(255, 255, 255, 0.4) !important; - outline: none; - color: white !important; -} - -.expert-login-modern .expert-login-form .form-check { - margin-bottom: 32px; -} - -.expert-login-modern .expert-login-form .form-check label { - color: rgba(255, 255, 255, 0.8); - display: flex; - align-items: center; - justify-content: flex-start; - font-size: 14px; - cursor: pointer; -} - -.expert-login-modern .expert-login-form .form-check label input[type="checkbox"] { - margin-right: 8px; - width: 18px; - height: 18px; - cursor: pointer; - accent-color: #667eea; -} - -.expert-login-modern .expert-login-form button[type="submit"] { - width: 100%; - background: #764ba2; - border: none !important; - border-radius: 8px; - padding: 14px; - font-weight: 600; - color: white; - font-size: 16px; - cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; -} - -.expert-login-modern .expert-login-form button[type="submit"]:hover { - transform: translateY(-2px); -} - -/* Login Link Section */ -.expert-login-modern .expert-login-link { - margin-top: 24px; - max-width: 450px; - width: 100%; - text-align: center; -} - -.expert-login-modern .expert-login-link p { - color: rgba(255, 255, 255, 0.7); - font-size: 14px; - margin: 0; -} - -.expert-login-modern .expert-login-link p a { - color: #667eea; - text-decoration: none; - font-weight: 500; -} - -.expert-login-modern .expert-login-link p a:hover { - text-decoration: underline; -} - -/* Right Column: Image Section */ -.expert-login-modern .expert-login-right { - padding: 0; - height: 100%; - overflow: hidden; - border-radius: 20px; -} - -.expert-login-modern .expert-login-right .expert-login-image { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; -} - -.expert-login-modern .expert-login-right .expert-login-image img { - width: 100% !important; - height: 100% !important; - object-fit: cover !important; -} - -/* Responsive adjustments */ -@media (max-width: 991.98px) { - .expert-login-modern .expert-login-left { - padding: 30px 20px; - } - - .expert-login-modern .expert-login-welcome h1 { - font-size: 28px; - } - - .expert-login-modern .expert-login-welcome h1 .welcome-emoji { - font-size: 28px; - } - - .expert-login-modern .expert-login-welcome p { - font-size: 14px; - } -} - diff --git a/odex30_base/expert_theme/static/src/css/expert_login.css b/odex30_base/expert_theme/static/src/scss/expert_login.scss similarity index 100% rename from odex30_base/expert_theme/static/src/css/expert_login.css rename to odex30_base/expert_theme/static/src/scss/expert_login.scss diff --git a/odex30_base/expert_theme/static/src/css/expert_theme.css b/odex30_base/expert_theme/static/src/scss/expert_theme.scss similarity index 98% rename from odex30_base/expert_theme/static/src/css/expert_theme.css rename to odex30_base/expert_theme/static/src/scss/expert_theme.scss index 6f4b521..13c2eb4 100644 --- a/odex30_base/expert_theme/static/src/css/expert_theme.css +++ b/odex30_base/expert_theme/static/src/scss/expert_theme.scss @@ -47,9 +47,9 @@ body { background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important; background: linear-gradient(135deg, var(--expert-bg-gradient-start, #f5f7fa) 0%, var(--expert-bg-gradient-end, #c3cfe2) 100%) !important; - min-height: 100vh !important; - margin: 0 !important; - padding: 0 !important; + // min-height: 100vh !important; + // margin: 0 !important; + // padding: 0 !important; } /* Ensure the gradient shows on the main content area */ @@ -58,7 +58,7 @@ body { .o_action_manager .o_view_controller .o_content { background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important; background: linear-gradient(135deg, var(--expert-bg-gradient-start, #f5f7fa) 0%, var(--expert-bg-gradient-end, #c3cfe2) 100%) !important; - min-height: 100vh !important; + // min-height: 100vh !important; } /* Override any Odoo background colors that might interfere */ diff --git a/odex30_base/expert_theme/static/src/css/expert_theme_config.css b/odex30_base/expert_theme/static/src/scss/expert_theme_config.scss similarity index 100% rename from odex30_base/expert_theme/static/src/css/expert_theme_config.css rename to odex30_base/expert_theme/static/src/scss/expert_theme_config.scss diff --git a/odex30_base/expert_theme/static/src/scss/login_minimal.scss b/odex30_base/expert_theme/static/src/scss/login_minimal.scss new file mode 100644 index 0000000..e0af721 --- /dev/null +++ b/odex30_base/expert_theme/static/src/scss/login_minimal.scss @@ -0,0 +1,280 @@ +/* Expert Theme - Minimal Login Template Styles */ +.expert-login-minimal { + background: #FFFFFF; + min-height: 100vh; + + .expert-login-left { + display: flex; + justify-content: center; + align-items: center; + text-align: center; + min-height: 100vh; + + .expert-login-form-container { + max-width: 450px; + + + .expert-login-logo { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 40px; + width: 100%; + + .expert-logo-icon { + width: 40px; + height: 40px; + background: #000000; + border-radius: 8px; + margin-right: 12px; + display: flex; + align-items: center; + justify-content: center; + + span { + color: white; + font-weight: bold; + font-size: 20px; + } + } + + .expert-logo-text { + color: #000000; + font-size: 20px; + font-weight: 600; + } + } + + .expert-login-welcome { + width: 100%; + text-align: center; + margin-bottom: 40px; + + h1 { + color: #000000; + font-size: 32px; + font-weight: 700; + margin-bottom: 12px; + line-height: 1.2; + text-align: center; + + .welcome-emoji { + font-size: 32px; + } + } + + p { + color: rgba(0, 0, 0, 0.7); + font-size: 16px; + margin-bottom: 0; + text-align: center; + } + } + + .expert-login-form { + max-width: 450px; + width: 100%; + margin: 0 auto; + background-color: transparent !important; + + .oe_login_form, + .oe_signup_form, + .oe_reset_password_form { + max-width: 450px; + background-color: transparent !important; + + label { + font-weight: 500; + color: #000000; + display: block; + margin-bottom: 8px; + font-size: 14px; + text-align: start; + } + + input { + + &[type="text"], + &[type="password"] { + background: #FFFFFF !important; + border: 1px solid #000000 !important; + border-radius: 8px; + padding: 12px 16px; + width: 100%; + box-sizing: border-box; + color: #000000 !important; + font-size: 14px; + } + + &[type="text"]::placeholder, + &[type="password"]::placeholder { + color: rgba(0, 0, 0, 0.5) !important; + } + + &[type="text"]:focus, + &[type="password"]:focus { + background: #FFFFFF !important; + border-color: #000000 !important; + outline: none; + color: #000000 !important; + } + } + } + + .form-check { + margin-bottom: 32px; + + label { + color: #000000; + display: flex; + align-items: center; + justify-content: flex-start; + flex-wrap: wrap; + gap: 5px; + font-size: 14px; + cursor: pointer; + + input[type="checkbox"] { + margin-right: 8px; + width: 18px; + height: 18px; + cursor: pointer; + accent-color: #000000; + } + } + } + + + .btn-link { + color: #5a5a5a; + } + + .btn-primary { + width: 100%; + background: #E5E5E5; + border: none; + border-radius: 8px; + padding: 14px; + font-weight: 600; + color: #000000; + font-size: 16px; + cursor: pointer; + transition: background 0.2s; + margin-bottom: 10px; + + &:hover { + background: #D5D5D5; + } + + &:active { + background: #CCCCCC; + } + } + } + + .expert-login-link { + margin-top: 24px; + max-width: 450px; + width: 100%; + text-align: center; + + p { + color: rgba(0, 0, 0, 0.7); + font-size: 14px; + margin: 0; + + a { + color: #000000; + text-decoration: underline; + font-weight: 500; + + &:hover { + text-decoration: none; + } + } + } + } + + } + + } + + .expert-login-right { + padding: 0; + height: 100%; + overflow: hidden; + min-height: 100vh; + + .expert-login-image { + width: 100%; + min-height: 100vh; + background: #FFFFFF; + display: flex; + align-items: center; + justify-content: center; + + } + } + + .expert-minimal-illustration { + width: 600px !important; + height: 600px !important; + object-fit: contain; + } + + .alert { + border-radius: 8px; + padding: 12px 16px; + margin-bottom: 20px; + text-align: start; + } + + .alert-danger { + background-color: #F8D7DA; + border: 1px solid #F5C6CB; + color: #721C24; + } + + .alert-success { + background-color: #D4EDDA; + border: 1px solid #C3E6CB; + color: #155724; + } +} + +/* Left Column: Login Form */ + +/* Logo Section */ + +/* Welcome Section */ + +/* Form Section */ + +/* Login Link Section */ + +/* Right Column: Image Section */ + +/* Alert Messages */ + +/* Responsive adjustments */ +@media (max-width: 991.98px) { + .expert-login-minimal { + .expert-login-left { + padding: 30px 20px; + } + + .expert-login-welcome { + h1 { + font-size: 28px; + + .welcome-emoji { + font-size: 28px; + } + } + + p { + font-size: 14px; + } + } + } +} \ No newline at end of file diff --git a/odex30_base/expert_theme/static/src/scss/login_modern.scss b/odex30_base/expert_theme/static/src/scss/login_modern.scss index 976f9fd..1fe5879 100644 --- a/odex30_base/expert_theme/static/src/scss/login_modern.scss +++ b/odex30_base/expert_theme/static/src/scss/login_modern.scss @@ -1,177 +1,180 @@ /* Expert Theme - Modern Login Template Styles */ - .expert-login-modern { background: #19181F; min-height: 100vh; padding: 20px; - .container-fluid { - height: calc(100vh - 40px); - } - - .row { - height: 100%; - margin: 0; - } - // Left Column: Login Form .expert-login-left { display: flex; - flex-direction: column; justify-content: center; - padding: 40px; - } - - // Logo Section - .expert-login-logo { - display: flex; align-items: center; - margin-bottom: 40px; + min-height: 100vh; - .expert-logo-icon { - width: 40px; - height: 40px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - border-radius: 8px; - margin-right: 12px; - display: flex; - align-items: center; - justify-content: center; + .expert-login-form-container { + max-width: 450px; - span { - color: white; - font-weight: bold; - font-size: 20px; - } - } - - .expert-logo-text { - color: white; - font-size: 20px; - font-weight: 600; - } - } - - // Welcome Section - .expert-login-welcome { - h1 { - color: white; - font-size: 36px; - font-weight: 700; - margin-bottom: 12px; - line-height: 1.2; - - .welcome-emoji { - font-size: 36px; - } - } - - p { - color: rgba(255, 255, 255, 0.7); - font-size: 16px; - margin-bottom: 40px; - } - } - - // Form Section - .expert-login-form { - max-width: 450px; - - .form-group { - margin-bottom: 24px; - - label { - font-weight: 500; - color: rgba(255, 255, 255, 0.9); - display: block; - margin-bottom: 8px; - font-size: 14px; - } - - input[type="text"], - input[type="password"] { - background: rgba(255, 255, 255, 0.1); - border: 1px solid rgba(255, 255, 255, 0.2); - border-radius: 8px; - padding: 12px 16px; - width: 100%; - box-sizing: border-box; - color: white; - font-size: 14px; - - &::placeholder { - color: rgba(255, 255, 255, 0.5); - } - - &:focus { - background: rgba(255, 255, 255, 0.15) !important; - border-color: rgba(255, 255, 255, 0.4) !important; - outline: none; - color: white; - } - } - } - - .form-check { - margin-bottom: 32px; - - label { - color: rgba(255, 255, 255, 0.8); + // Logo Section + .expert-login-logo { display: flex; align-items: center; - font-size: 14px; - cursor: pointer; + margin-bottom: 40px; - input[type="checkbox"] { - margin-right: 8px; - width: 18px; - height: 18px; - cursor: pointer; - accent-color: #667eea; + .expert-logo-icon { + width: 40px; + height: 40px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 8px; + margin-right: 12px; + display: flex; + align-items: center; + justify-content: center; + + span { + color: white; + font-weight: bold; + font-size: 20px; + } + } + + .expert-logo-text { + color: white; + font-size: 20px; + font-weight: 600; } } } - button[type="submit"] { - width: 100%; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - border: none; - border-radius: 8px; - padding: 14px; - font-weight: 600; - color: white; - font-size: 16px; - cursor: pointer; - transition: transform 0.2s, box-shadow 0.2s; + // Welcome Section + .expert-login-welcome { + h1 { + color: white; + font-size: 36px; + font-weight: 700; + margin-bottom: 12px; + line-height: 1.2; - &:hover { - transform: translateY(-2px); - box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4); + .welcome-emoji { + font-size: 36px; + } } - &:active { - transform: translateY(0); + p { + color: rgba(255, 255, 255, 0.7); + font-size: 16px; + margin-bottom: 40px; } } - } - // Login Link Section - .expert-login-link { - margin-top: 24px; - max-width: 450px; + // Form Section + .expert-login-form { - p { - color: rgba(255, 255, 255, 0.7); - font-size: 14px; - margin: 0; + .oe_login_form, + .oe_signup_form, + .oe_reset_password_form { + max-width: 450px; + background-color: transparent !important; - a { - color: #667eea; - text-decoration: none; - font-weight: 500; + .form-label, + label { + font-weight: 500; + color: rgba(255, 255, 255, 0.9); + display: block; + margin-bottom: 8px; + font-size: 14px; + } - &:hover { - text-decoration: underline; + .form-control { + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 8px; + padding: 12px 16px; + width: 100%; + box-sizing: border-box; + color: white; + font-size: 14px; + + &::placeholder { + color: rgba(255, 255, 255, 0.5); + } + + &:focus { + background: rgba(255, 255, 255, 0.15) !important; + border-color: rgba(255, 255, 255, 0.4) !important; + outline: none; + color: white; + } + } + + .form-check { + margin-bottom: 32px; + + label { + color: rgba(255, 255, 255, 0.8); + display: flex; + align-items: center; + font-size: 14px; + cursor: pointer; + + input[type="checkbox"] { + margin-right: 8px; + width: 18px; + height: 18px; + cursor: pointer; + accent-color: #667eea; + } + } + } + + .btn-link { + color: #939393; + } + + .btn-primary { + width: 100%; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border: none; + border-radius: 8px; + padding: 14px; + font-weight: 600; + color: white; + font-size: 16px; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + margin-bottom: 10px; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4); + } + + &:active { + transform: translateY(0); + } + } + } + + + } + + // Login Link Section + .expert-login-link { + margin-top: 24px; + max-width: 450px; + + p { + color: rgba(255, 255, 255, 0.7); + font-size: 14px; + margin: 0; + + a { + color: #667eea; + text-decoration: none; + font-weight: 500; + + &:hover { + text-decoration: underline; + } } } } @@ -183,15 +186,27 @@ height: 100%; overflow: hidden; border-radius: 20px 0 0 20px; - + min-height: 100vh; + .expert-login-image { width: 100%; height: 100%; - background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 25%, #667eea 75%, #764ba2 100%); + // background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 25%, #667eea 75%, #764ba2 100%); display: flex; align-items: center; justify-content: center; position: relative; + padding: 20px; + + .expert-login-image-cover { + height: 100%; + width: 100%; + background-color: #667eea; + background-position: center; + background-size: cover; + background-repeat: no-repeat; + border-radius: 16px; + } .expert-spiral-decoration { width: 400px; @@ -254,5 +269,4 @@ } } } -} - +} \ No newline at end of file diff --git a/odex30_base/expert_theme/views/expert_home_views.xml b/odex30_base/expert_theme/views/expert_home_views.xml index 71944e0..f827c10 100644 --- a/odex30_base/expert_theme/views/expert_home_views.xml +++ b/odex30_base/expert_theme/views/expert_home_views.xml @@ -14,7 +14,6 @@

Your installed modules are listed below

-
diff --git a/odex30_base/expert_theme/views/expert_menu_views.xml b/odex30_base/expert_theme/views/expert_menu_views.xml index 1728e82..c4158ff 100644 --- a/odex30_base/expert_theme/views/expert_menu_views.xml +++ b/odex30_base/expert_theme/views/expert_menu_views.xml @@ -3,31 +3,33 @@ - - - - - - - - - + name="Odex Theme" + web_icon="expert_theme,static/description/icon.png" + sequence="1000" /> + + + + + + + + + + - + \ No newline at end of file diff --git a/odex30_base/expert_theme/views/login_templates.xml b/odex30_base/expert_theme/views/login_templates.xml index 2ce16fb..ff6b42c 100644 --- a/odex30_base/expert_theme/views/login_templates.xml +++ b/odex30_base/expert_theme/views/login_templates.xml @@ -5,878 +5,275 @@ Standalone templates rendered by the /web/login override. Each template calls web.layout and defines its own login form. --> - + -