feat(keenetic): edit KeenDNS address from dashboard

Add PATCH endpoint and inline card editor to update web_url and host,
with URL validation and automatic refresh after save.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Андрей Бобырев
2026-05-22 01:02:01 +03:00
parent 746ecfc343
commit 8f8e9a3234
4 changed files with 228 additions and 0 deletions

View File

@@ -433,10 +433,21 @@ main {
.progress-bar .fill.warn { background: var(--warning); }
.progress-bar .fill.crit { background: var(--danger); }
.keenetic-url-edit {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid var(--border);
}
.keenetic-url-edit .form-group input {
font-size: 12px;
}
.server-card-actions {
display: flex;
gap: 8px;
margin-top: 14px;
flex-wrap: wrap;
padding-top: 14px;
border-top: 1px solid var(--border);
}
@@ -722,6 +733,114 @@ main {
text-decoration: underline;
}
/* Loading state */
.server-card.loading {
opacity: 0.5;
pointer-events: none;
position: relative;
}
.server-card.loading::after {
content: "⏳";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 32px;
animation: pulse 1s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
/* Card bottom buttons */
.card-buttons {
display: flex;
gap: 6px;
padding: 8px 0 0;
margin-top: 8px;
border-top: 1px solid rgba(255,255,255,0.06);
flex-wrap: wrap;
}
.btn-card {
flex: 1;
padding: 6px 10px;
border: 1px solid rgba(255,255,255,0.1);
background: rgba(255,255,255,0.04);
color: var(--text);
border-radius: 6px;
font-size: 12px;
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
min-width: 0;
}
.btn-card:hover { background: rgba(255,255,255,0.1); }
.btn-card.btn-warn {
border-color: rgba(251,191,36,0.3);
color: #fbbf24;
}
.btn-card.btn-warn:hover { background: rgba(251,191,36,0.15); }
.btn-card.btn-danger-sm {
flex: 0;
border-color: rgba(239,68,68,0.3);
color: #ef4444;
padding: 6px 10px;
}
.btn-card.btn-danger-sm:hover { background: rgba(239,68,68,0.15); }
/* VPN badges */
.badge-vpn-up {
display: inline-block;
background: rgba(34,197,94,0.15);
color: #22c55e;
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
border: 1px solid rgba(34,197,94,0.3);
}
.badge-vpn-down {
display: inline-block;
background: rgba(239,68,68,0.15);
color: #ef4444;
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
border: 1px solid rgba(239,68,68,0.3);
}
/* Mute bell icon */
.mute-bell {
position: absolute;
top: 10px;
right: 10px;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
border: 1px solid transparent;
background: rgba(255,255,255,0.04);
cursor: pointer;
font-size: 15px;
opacity: 0.35;
transition: all 0.2s;
z-index: 5;
padding: 0;
line-height: 1;
}
.mute-bell:hover {
opacity: 1;
background: rgba(255,255,255,0.1);
border-color: rgba(255,255,255,0.15);
}
.mute-bell.muted {
opacity: 1;
background: rgba(239,68,68,0.15);
border-color: rgba(239,68,68,0.4);
}
/* Responsive */
@media (max-width: 768px) {
main { padding: 16px; }