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 0000000..d3b8d45 Binary files /dev/null and b/odex30_base/expert_theme/static/description/icon.png differ 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. --> - + -