viberadar 0.3.43 → 0.3.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ui/dashboard.html +74 -41
- package/package.json +1 -1
package/dist/ui/dashboard.html
CHANGED
|
@@ -482,56 +482,49 @@
|
|
|
482
482
|
|
|
483
483
|
/* ── Test-type cards inside feature detail ───────────────────────────────── */
|
|
484
484
|
.test-type-grid {
|
|
485
|
-
display:
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
align-items: center;
|
|
485
|
+
display: grid;
|
|
486
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
487
|
+
gap: 10px;
|
|
488
|
+
margin-bottom: 18px;
|
|
490
489
|
}
|
|
491
490
|
.test-type-card {
|
|
492
491
|
display: flex;
|
|
493
|
-
|
|
494
|
-
gap: 8px;
|
|
492
|
+
flex-direction: column;
|
|
495
493
|
background: var(--bg-card);
|
|
496
494
|
border: 1px solid var(--border);
|
|
497
|
-
border-
|
|
495
|
+
border-top: 3px solid transparent;
|
|
498
496
|
border-radius: 8px;
|
|
499
|
-
padding:
|
|
497
|
+
padding: 12px 14px 10px;
|
|
500
498
|
cursor: pointer;
|
|
501
499
|
transition: background 0.15s, border-color 0.15s;
|
|
502
|
-
|
|
500
|
+
min-width: 0;
|
|
503
501
|
}
|
|
504
502
|
.test-type-card:hover { background: var(--bg-hover); }
|
|
505
|
-
.test-type-card
|
|
506
|
-
.test-type-card
|
|
507
|
-
font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;
|
|
508
|
-
color: var(--muted); white-space: nowrap;
|
|
509
|
-
}
|
|
510
|
-
.test-type-card .tt-count {
|
|
511
|
-
font-size: 18px; font-weight: 700; line-height: 1;
|
|
512
|
-
}
|
|
513
|
-
.test-type-card .tt-sub {
|
|
514
|
-
font-size: 11px; color: var(--dim); white-space: nowrap;
|
|
515
|
-
}
|
|
516
|
-
.test-type-card.tt-empty { opacity: 0.65; }
|
|
517
|
-
.test-type-card.tt-active { background: var(--bg-hover); }
|
|
503
|
+
.test-type-card.tt-active { background: var(--bg-hover); border-color: var(--border); }
|
|
504
|
+
.test-type-card.tt-empty { opacity: 0.6; }
|
|
518
505
|
.test-type-card.tt-failed {
|
|
519
506
|
border-color: var(--red) !important;
|
|
520
|
-
background: rgba(248, 81, 73, 0.
|
|
521
|
-
}
|
|
522
|
-
.tt-
|
|
507
|
+
background: rgba(248, 81, 73, 0.05);
|
|
508
|
+
}
|
|
509
|
+
.tt-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
|
|
510
|
+
.tt-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted); }
|
|
511
|
+
.tt-failed-badge { font-size: 10px; color: var(--red); font-weight: 700; }
|
|
512
|
+
.tt-count { font-size: 28px; font-weight: 700; line-height: 1; margin-bottom: 2px; }
|
|
513
|
+
.tt-sub { font-size: 11px; color: var(--dim); }
|
|
514
|
+
.tt-card-actions { display: flex; flex-direction: column; gap: 5px; margin-top: 10px; }
|
|
523
515
|
.tt-run-btn {
|
|
524
|
-
|
|
525
|
-
padding: 3px 9px;
|
|
516
|
+
width: 100%; padding: 5px 10px;
|
|
526
517
|
background: transparent; border: 1px solid var(--border);
|
|
527
|
-
border-radius:
|
|
528
|
-
cursor: pointer;
|
|
518
|
+
border-radius: 5px; color: var(--muted); font-size: 11px;
|
|
519
|
+
cursor: pointer; text-align: center;
|
|
529
520
|
transition: background 0.1s, color 0.1s, border-color 0.1s;
|
|
530
521
|
}
|
|
531
522
|
.tt-run-btn:hover { background: var(--bg-hover); color: var(--text); border-color: var(--dim); }
|
|
532
523
|
.tt-run-btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
533
524
|
.tt-fix-btn { border-color: var(--yellow); color: var(--yellow); font-weight: 600; }
|
|
534
525
|
.tt-fix-btn:hover { background: rgba(255,200,0,0.1); color: var(--yellow); border-color: var(--yellow); }
|
|
526
|
+
.tt-write-btn { border-color: var(--accent); color: var(--accent); }
|
|
527
|
+
.tt-write-btn:hover { background: rgba(88,166,255,0.1); color: var(--accent); border-color: var(--accent); }
|
|
535
528
|
.file-rows { display: flex; flex-direction: column; gap: 2px; }
|
|
536
529
|
.file-row {
|
|
537
530
|
display: flex;
|
|
@@ -668,6 +661,12 @@
|
|
|
668
661
|
font-size: 14px; padding: 3px 6px; border-radius: 4px; line-height: 1;
|
|
669
662
|
}
|
|
670
663
|
.agent-panel-close:hover { background: var(--border); color: var(--text); }
|
|
664
|
+
.agent-panel-copy {
|
|
665
|
+
background: none; border: none; color: var(--dim); cursor: pointer;
|
|
666
|
+
font-size: 13px; padding: 3px 7px; border-radius: 4px; line-height: 1;
|
|
667
|
+
}
|
|
668
|
+
.agent-panel-copy:hover { background: var(--border); color: var(--text); }
|
|
669
|
+
.agent-panel-copy.copied { color: var(--green); }
|
|
671
670
|
.agent-panel-cancel {
|
|
672
671
|
background: none; border: 1px solid var(--yellow); color: var(--yellow);
|
|
673
672
|
cursor: pointer; font-size: 11px; padding: 2px 8px; border-radius: 4px;
|
|
@@ -818,6 +817,7 @@
|
|
|
818
817
|
<span class="agent-queue-badge" id="agentQueueBadge" style="display:none">📋 <span id="agentQueueCount">0</span> в очереди</span>
|
|
819
818
|
<button class="agent-panel-cancel" id="agentQueueClearBtn" onclick="clearAgentQueue()" title="Очистить очередь" style="display:none">🗑 очередь</button>
|
|
820
819
|
<button class="agent-panel-cancel" id="agentCancelBtn" onclick="cancelAgent()" title="Сбросить состояние агента" style="display:none">⏹ сброс</button>
|
|
820
|
+
<button class="agent-panel-copy" id="agentCopyBtn" onclick="copyTerminalContent()" title="Скопировать содержимое вкладки в буфер обмена">⎘</button>
|
|
821
821
|
<button class="agent-panel-close" onclick="closeAgentPanel()">✕</button>
|
|
822
822
|
</div>
|
|
823
823
|
<div class="agent-tabs-bar" id="agentTabsBar"></div>
|
|
@@ -984,7 +984,9 @@ function renderTabs() {
|
|
|
984
984
|
bar.innerHTML = consoleSessions.map(s => {
|
|
985
985
|
const isActive = s.id === activeSessionId;
|
|
986
986
|
const safe = s.title.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
987
|
-
return `<div class="agent-tab${isActive ? ' active' : ''}"
|
|
987
|
+
return `<div class="agent-tab${isActive ? ' active' : ''}"
|
|
988
|
+
onclick="switchSession('${s.id}')"
|
|
989
|
+
onmousedown="if(event.button===1){event.preventDefault();event.stopPropagation();closeSession('${s.id}')}">
|
|
988
990
|
<span class="tab-dot tab-dot-${s.status}"></span>
|
|
989
991
|
<span class="agent-tab-title" title="${safe}">${safe}</span>
|
|
990
992
|
<button class="agent-tab-close" onclick="event.stopPropagation();closeSession('${s.id}')" title="Закрыть вкладку">×</button>
|
|
@@ -994,6 +996,29 @@ function renderTabs() {
|
|
|
994
996
|
if (active) active.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
995
997
|
}
|
|
996
998
|
|
|
999
|
+
function copyTerminalContent() {
|
|
1000
|
+
const s = consoleSessions.find(s => s.id === activeSessionId);
|
|
1001
|
+
if (!s || s.lines.length === 0) return;
|
|
1002
|
+
// Extract plain text from each line (strip HTML for rich nodes)
|
|
1003
|
+
const text = s.lines.map(l => {
|
|
1004
|
+
if (l.text !== undefined) return l.text;
|
|
1005
|
+
if (l.html) {
|
|
1006
|
+
const tmp = document.createElement('div');
|
|
1007
|
+
tmp.innerHTML = l.html;
|
|
1008
|
+
return tmp.innerText;
|
|
1009
|
+
}
|
|
1010
|
+
return '';
|
|
1011
|
+
}).filter(Boolean).join('\n');
|
|
1012
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
1013
|
+
const btn = document.getElementById('agentCopyBtn');
|
|
1014
|
+
if (!btn) return;
|
|
1015
|
+
const prev = btn.textContent;
|
|
1016
|
+
btn.textContent = '✓';
|
|
1017
|
+
btn.classList.add('copied');
|
|
1018
|
+
setTimeout(() => { btn.textContent = prev; btn.classList.remove('copied'); }, 1500);
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
|
|
997
1022
|
function renderActiveSession() {
|
|
998
1023
|
const term = document.getElementById('agentTerminal');
|
|
999
1024
|
if (!term) return;
|
|
@@ -1533,30 +1558,38 @@ function renderFeatureCards(c) {
|
|
|
1533
1558
|
}
|
|
1534
1559
|
|
|
1535
1560
|
function testTypeCard(type, label, icon, color, count, active, featureKey, failedCount = 0) {
|
|
1536
|
-
const empty
|
|
1561
|
+
const empty = count === 0 && type !== 'source';
|
|
1537
1562
|
const hasFailed = failedCount > 0 && type !== 'source';
|
|
1538
|
-
const subLabel
|
|
1563
|
+
const subLabel = type === 'source' ? 'файлов' : (empty ? 'нет тестов' : pluralFiles(count));
|
|
1539
1564
|
const accentColor = hasFailed ? 'var(--red)' : color;
|
|
1540
1565
|
const countColor = hasFailed ? 'var(--red)' : (active || !empty ? color : 'var(--dim)');
|
|
1541
1566
|
|
|
1567
|
+
const failedBadge = hasFailed
|
|
1568
|
+
? `<span class="tt-failed-badge">❌ ${failedCount}</span>`
|
|
1569
|
+
: '';
|
|
1570
|
+
|
|
1542
1571
|
const runBtn = !empty && type !== 'source' && featureKey
|
|
1543
|
-
? `<button class="tt-run-btn" onclick="event.stopPropagation();runTests('${featureKey}','${type}')">▶
|
|
1572
|
+
? `<button class="tt-run-btn" onclick="event.stopPropagation();runTests('${featureKey}','${type}')">▶ запустить тесты</button>`
|
|
1544
1573
|
: '';
|
|
1545
1574
|
const fixAllBtn = hasFailed && D.agent && featureKey
|
|
1546
|
-
? `<button class="tt-run-btn tt-fix-btn" onclick="event.stopPropagation();runAgentTask('fix-tests-all','${featureKey}','${type}')">🔧
|
|
1575
|
+
? `<button class="tt-run-btn tt-fix-btn" onclick="event.stopPropagation();runAgentTask('fix-tests-all','${featureKey}','${type}')">🔧 починить все</button>`
|
|
1547
1576
|
: '';
|
|
1548
|
-
const
|
|
1549
|
-
? `<
|
|
1577
|
+
const writeBtn = type !== 'source' && D.agent && featureKey
|
|
1578
|
+
? `<button class="tt-run-btn tt-write-btn" onclick="event.stopPropagation();runAgentTask('write-tests','${featureKey}')">✍ написать тесты</button>`
|
|
1579
|
+
: '';
|
|
1580
|
+
const actions = (runBtn || fixAllBtn || writeBtn)
|
|
1581
|
+
? `<div class="tt-card-actions">${runBtn}${fixAllBtn}${writeBtn}</div>`
|
|
1550
1582
|
: '';
|
|
1551
|
-
const actions = (runBtn || fixAllBtn) ? `<div class="tt-chip-actions">${runBtn}${fixAllBtn}</div>` : '';
|
|
1552
1583
|
|
|
1553
1584
|
return `
|
|
1554
1585
|
<div class="test-type-card${empty ? ' tt-empty' : ''}${active ? ' tt-active' : ''}${hasFailed ? ' tt-failed' : ''}"
|
|
1555
|
-
data-testtype="${type}" style="border-
|
|
1556
|
-
<
|
|
1586
|
+
data-testtype="${type}" style="border-top-color:${accentColor}">
|
|
1587
|
+
<div class="tt-card-header">
|
|
1588
|
+
<span class="tt-label">${icon} ${label}</span>
|
|
1589
|
+
${failedBadge}
|
|
1590
|
+
</div>
|
|
1557
1591
|
<span class="tt-count" style="color:${countColor}">${count}</span>
|
|
1558
1592
|
<span class="tt-sub">${subLabel}</span>
|
|
1559
|
-
${failedBadge}
|
|
1560
1593
|
${actions}
|
|
1561
1594
|
</div>`;
|
|
1562
1595
|
}
|