diff --git a/app/static/style.css b/app/static/style.css index e856b0a..7c66a7b 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -410,18 +410,60 @@ button { position: relative; height: 100%; } +.svc-cred-toggle { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + background: rgba(42,140,214,0.1); + border: 1px solid rgba(42,140,214,0.22); + border-radius: 8px; + padding: 0.32rem 0.65rem; + margin: 0 0 0rem; + cursor: pointer; + font-size: 0.76rem; + font-weight: 700; + color: #1a5a8a; + letter-spacing: 0.03em; + text-transform: uppercase; + pointer-events: auto; + transition: background 0.15s ease, border-color 0.15s ease; + flex-shrink: 0; +} +.svc-cred-toggle:hover { + background: rgba(42,140,214,0.18); + border-color: rgba(42,140,214,0.38); +} +.svc-cred-chevron { + width: 14px; height: 14px; + flex-shrink: 0; + transition: transform 0.2s ease; + color: #2a8cd6; +} +.svc-credentials-wrap.open .svc-cred-chevron { + transform: rotate(180deg); +} +.svc-credentials-wrap.open .svc-cred-toggle { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-color: transparent; +} .svc-credentials { background: linear-gradient(135deg, #edf5fc 0%, #e2eff8 100%); border: 1px solid #c7d9ea; - border-radius: 8px; + border-top: none; + border-radius: 0 0 8px 8px; padding: 0.5rem 0.75rem 0.55rem; margin: 0 0 0.5rem; - display: flex; + display: none; flex-direction: column; gap: 0.3rem; flex-shrink: 0; pointer-events: auto; } +.svc-credentials-wrap.open .svc-credentials { + display: flex; +} .svc-cred-row { display: flex; align-items: center; @@ -881,8 +923,16 @@ button { /* Credentials block */ .dashboard-page .svc-credentials { - background: linear-gradient(135deg, #edf6ff 0%, #e2f0fb 100%) !important; - border-color: rgba(180, 215, 240, 0.8) !important; + background: linear-gradient(135deg, rgba(220,238,255,0.55) 0%, rgba(200,225,248,0.5) 100%) !important; + border-color: rgba(180, 215, 240, 0.6) !important; +} +.dashboard-page .svc-cred-toggle { + background: rgba(42,140,214,0.12) !important; + border-color: rgba(42,140,214,0.25) !important; + color: #0c2e4a !important; +} +.dashboard-page .svc-cred-toggle:hover { + background: rgba(42,140,214,0.2) !important; } /* Category badges on tile */ diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 6a96ab4..0668073 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -104,22 +104,28 @@

{{ service.name }}

{% if service.svc_login or service.svc_password %} -
- {% if service.svc_login %} -
- Логин - {{ service.svc_login }} +
+ +
+ {% if service.svc_login %} +
+ Логин + {{ service.svc_login }} +
+ {% endif %} + {% if service.svc_password %} +
+ Пароль + {{ service.svc_password }} +
+ {% endif %} + {% if service.svc_cred_hint %} +

{{ service.svc_cred_hint }}

+ {% endif %}
- {% endif %} - {% if service.svc_password %} -
- Пароль - {{ service.svc_password }} -
- {% endif %} - {% if service.svc_cred_hint %} -

{{ service.svc_cred_hint }}

- {% endif %}
{% endif %} {% if service.comment %} diff --git a/universal-runtime/manager.py b/universal-runtime/manager.py index e795668..fc0de6e 100644 --- a/universal-runtime/manager.py +++ b/universal-runtime/manager.py @@ -49,7 +49,8 @@ _AUTOFILL_CONTENT_JS = r""" 'input[name*="email" i]:not([type="password"]):not([type="hidden"]), ' + 'input[id*="user" i]:not([type="password"]):not([type="hidden"]), ' + 'input[id*="login" i]:not([type="password"]):not([type="hidden"]), ' + - 'input[id*="email" i]:not([type="password"]):not([type="hidden"])' + 'input[id*="email" i]:not([type="password"]):not([type="hidden"]), ' + + 'input[autofocus]:not([type="password"]):not([type="hidden"]):not([type="checkbox"]):not([type="radio"])' ); for (const el of candidates) { if (isVisible(el)) return el; @@ -126,6 +127,11 @@ _AUTOFILL_CONTENT_JS = r""" console.log('[PortalAutofill] password filled'); } } + // Some apps (e.g. Zabbix) clear username after password events — re-fill if needed + if (CREDS.login && u && u.value !== CREDS.login) { + setNativeValue(u, CREDS.login); + console.log('[PortalAutofill] user re-filled after password'); + } } // Watch for SPA re-renders clearing the fields and re-fill continuously