@@ -4915,10 +4915,10 @@ async def admin_get_user_edit(
49154915 <span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span>
49164916 <span>At least {settings.password_min_length} characters long</span>
49174917 </div>
4918- {' <div class="flex items-center" id="req-uppercase"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains uppercase letters (A-Z)</span></div>' if settings.password_require_uppercase else ''}
4919- {' <div class="flex items-center" id="req-lowercase"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains lowercase letters (a-z)</span></div>' if settings.password_require_lowercase else ''}
4918+ <div class="flex items-center" id="req-uppercase"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains uppercase letters (A-Z)</span></div>
4919+ <div class="flex items-center" id="req-lowercase"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains lowercase letters (a-z)</span></div>
49204920 {'<div class="flex items-center" id="req-numbers"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains numbers (0-9)</span></div>' if settings.password_require_numbers else ''}
4921- {' <div class="flex items-center" id="req-special"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains special characters (!@#$%^&*(),.?":{{}}|<>)</span></div>' if settings.password_require_special else ''}
4921+ <div class="flex items-center" id="req-special"><span class="inline-flex items-center justify-center w-4 h-4 bg-gray-400 text-white rounded-full text-xs mr-2">✗</span><span>Contains special characters (!@#$%^&*(),.?":{{}}|<>)</span></div>
49224922 </div>
49234923 </div>
49244924 </div>
@@ -4934,6 +4934,8 @@ async def admin_get_user_edit(
49344934 requireSpecial: {'true' if settings.password_require_special else 'false'}
49354935 }};
49364936
4937+ // (No debug output) passwordPolicy available in JS for logic below
4938+
49374939 function updateRequirementIcon(elementId, isValid) {{
49384940 const req = document.getElementById(elementId);
49394941 if (req) {{
@@ -4957,19 +4959,19 @@ async def admin_get_user_edit(
49574959
49584960 // Check uppercase requirement (if enabled)
49594961 const uppercaseCheck = !passwordPolicy.requireUppercase || /[A-Z]/.test(password);
4960- updateRequirementIcon('req-uppercase', /[A-Z]/.test(password) );
4962+ updateRequirementIcon('req-uppercase', uppercaseCheck );
49614963
49624964 // Check lowercase requirement (if enabled)
49634965 const lowercaseCheck = !passwordPolicy.requireLowercase || /[a-z]/.test(password);
4964- updateRequirementIcon('req-lowercase', /[a-z]/.test(password) );
4966+ updateRequirementIcon('req-lowercase', lowercaseCheck );
49654967
49664968 // Check numbers requirement (if enabled)
49674969 const numbersCheck = !passwordPolicy.requireNumbers || /[0-9]/.test(password);
4968- updateRequirementIcon('req-numbers', /[0-9]/.test(password) );
4970+ updateRequirementIcon('req-numbers', numbersCheck );
49694971
49704972 // Check special character requirement (if enabled) - matches backend set
49714973 const specialCheck = !passwordPolicy.requireSpecial || /[!@#$%^&*(),.?":{{}}|<>]/.test(password);
4972- updateRequirementIcon('req-special', /[!@#$%^&*(),.?":{{}}|<>]/.test(password) );
4974+ updateRequirementIcon('req-special', specialCheck );
49734975
49744976 // Enable/disable submit button based on active requirements
49754977 const submitButton = document.querySelector('#user-edit-modal-content button[type="submit"]');
@@ -5000,9 +5002,25 @@ async def admin_get_user_edit(
50005002 }}
50015003 }}
50025004
5003- // Initialize validation on page load
5004- document.addEventListener('DOMContentLoaded', function() {{
5005- validatePasswordRequirements();
5005+ // Initialize validation when the form is present (supports HTMX-injected content)
5006+ (function initPasswordValidation() {{
5007+ if (document.getElementById('password-field')) {{
5008+ validatePasswordRequirements();
5009+ validatePasswordMatch();
5010+ }}
5011+ }})();
5012+
5013+ // Re-run validation after HTMX swaps content into the DOM (modal loaded via HTMX)
5014+ document.addEventListener('htmx:afterSwap', function(event) {{
5015+ try {{
5016+ const target = event.detail && event.detail.target ? event.detail.target : null;
5017+ if (target && (target.querySelector('#password-field') || target.id === 'user-edit-modal-content')) {{
5018+ validatePasswordRequirements();
5019+ validatePasswordMatch();
5020+ }}
5021+ }} catch (e) {{
5022+ // Ignore errors from HTMX event handling
5023+ }}
50065024 }});
50075025 </script>
50085026 <div class="flex justify-end space-x-3">
0 commit comments