viberadar 0.3.216 → 0.3.218
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/server/index.d.ts.map +1 -1
- package/dist/server/index.js +42 -12
- package/dist/server/index.js.map +1 -1
- package/dist/ui/dashboard.html +195 -38
- package/package.json +1 -1
package/dist/ui/dashboard.html
CHANGED
|
@@ -1555,10 +1555,31 @@
|
|
|
1555
1555
|
background: transparent; color: var(--muted); font-size: 11px; cursor: pointer;
|
|
1556
1556
|
}
|
|
1557
1557
|
.load-script-del-btn:hover { border-color: var(--red); color: var(--red); }
|
|
1558
|
-
.load-
|
|
1559
|
-
.load-
|
|
1560
|
-
|
|
1561
|
-
|
|
1558
|
+
.load-live-shell { display: grid; grid-template-columns: minmax(180px, 240px) 1fr; gap: 14px; align-items: stretch; }
|
|
1559
|
+
.load-progress-card {
|
|
1560
|
+
background: linear-gradient(180deg, rgba(88,166,255,0.10), rgba(13,17,23,0));
|
|
1561
|
+
border: 1px solid rgba(88,166,255,0.28); border-radius: 8px; padding: 16px;
|
|
1562
|
+
display: flex; flex-direction: column; justify-content: space-between; min-height: 170px;
|
|
1563
|
+
}
|
|
1564
|
+
.load-progress-value { font-size: 52px; line-height: 1; font-weight: 800; color: var(--text); letter-spacing: 0; }
|
|
1565
|
+
.load-progress-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; margin-top: 6px; }
|
|
1566
|
+
.load-progress-bar { height: 8px; background: var(--bg); border: 1px solid var(--border); border-radius: 999px; overflow: hidden; margin-top: 14px; }
|
|
1567
|
+
.load-progress-fill { height: 100%; background: var(--blue); border-radius: inherit; transition: width 0.25s ease; }
|
|
1568
|
+
.load-live-kpis { display: grid; grid-template-columns: repeat(4, minmax(100px, 1fr)); gap: 8px; margin-bottom: 10px; }
|
|
1569
|
+
.load-live-kpi { background: var(--bg); border: 1px solid var(--border); border-radius: 7px; padding: 10px 12px; min-width: 0; }
|
|
1570
|
+
.load-live-kpi-val { font-size: 20px; font-weight: 750; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1571
|
+
.load-live-kpi-lbl { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.4px; margin-top: 2px; }
|
|
1572
|
+
.load-charts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
|
1573
|
+
.load-chart-box { background: var(--bg); border: 1px solid var(--border); border-radius: 7px; padding: 10px; min-width: 0; }
|
|
1574
|
+
.load-chart-label { display:flex; align-items:center; justify-content:space-between; gap:8px; font-size: 11px; color: var(--muted); margin-bottom: 6px; }
|
|
1575
|
+
.load-chart-value { color: var(--text); font-weight: 700; }
|
|
1576
|
+
.load-chart-box canvas { display: block; width: 100%; height: 128px; }
|
|
1577
|
+
.load-chart-empty { height:128px; display:flex; align-items:center; justify-content:center; color:var(--dim); font-size:12px; border:1px dashed var(--border); border-radius:6px; }
|
|
1578
|
+
@media (max-width: 760px) {
|
|
1579
|
+
.load-live-shell { grid-template-columns: 1fr; }
|
|
1580
|
+
.load-live-kpis { grid-template-columns: 1fr 1fr; }
|
|
1581
|
+
.load-charts { grid-template-columns: 1fr; }
|
|
1582
|
+
}
|
|
1562
1583
|
.load-summary-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 8px; }
|
|
1563
1584
|
.load-kpi { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 10px; text-align: center; }
|
|
1564
1585
|
.load-kpi-val { font-size: 20px; font-weight: 700; }
|
|
@@ -1794,6 +1815,7 @@ let loadDataDirDraft = '';
|
|
|
1794
1815
|
let loadResultDirDraft = '';
|
|
1795
1816
|
let loadAccountsJsonDraft = '';
|
|
1796
1817
|
let loadImportedEnvVarsDraft = {};
|
|
1818
|
+
let loadLiveUiTimer = null;
|
|
1797
1819
|
let loadView = 'library'; // 'library' | 'editor'
|
|
1798
1820
|
|
|
1799
1821
|
function toggleObsHint(id) {
|
|
@@ -7660,20 +7682,114 @@ function generateScriptFromFeature(featureKey) {
|
|
|
7660
7682
|
});
|
|
7661
7683
|
}
|
|
7662
7684
|
|
|
7663
|
-
function drawLoadCharts() {
|
|
7664
|
-
if (!loadBuckets || loadBuckets.length === 0) return;
|
|
7665
|
-
drawLoadChart('loadChartRps', loadBuckets, b => b.count / 2, 'var(--blue)', 'RPS');
|
|
7666
|
-
drawLoadChart('loadChartLatency', loadBuckets, b => b.count > 0 ? b.durSum / b.count : 0, 'var(--green)', 'Latency avg (ms)');
|
|
7667
|
-
drawLoadChart('loadChartErrors', loadBuckets, b => b.count > 0 ? (b.errors / b.count) * 100 : 0, 'var(--red)', 'Error %');
|
|
7668
|
-
drawLoadChart('loadChartVus', loadBuckets, b => b.vus, 'var(--yellow)', 'VUs');
|
|
7669
|
-
}
|
|
7670
|
-
|
|
7685
|
+
function drawLoadCharts() {
|
|
7686
|
+
if (!loadBuckets || loadBuckets.length === 0) return;
|
|
7687
|
+
drawLoadChart('loadChartRps', loadBuckets, b => b.count / 2, 'var(--blue)', 'RPS');
|
|
7688
|
+
drawLoadChart('loadChartLatency', loadBuckets, b => b.count > 0 ? b.durSum / b.count : 0, 'var(--green)', 'Latency avg (ms)');
|
|
7689
|
+
drawLoadChart('loadChartErrors', loadBuckets, b => b.count > 0 ? (b.errors / b.count) * 100 : 0, 'var(--red)', 'Error %');
|
|
7690
|
+
drawLoadChart('loadChartVus', loadBuckets, b => b.vus, 'var(--yellow)', 'VUs');
|
|
7691
|
+
}
|
|
7692
|
+
|
|
7693
|
+
function parseLoadDurationMs(value) {
|
|
7694
|
+
const text = String(value || '').trim();
|
|
7695
|
+
if (!text) return 0;
|
|
7696
|
+
let total = 0;
|
|
7697
|
+
const re = /(\d+(?:\.\d+)?)\s*(ms|s|m|h)/gi;
|
|
7698
|
+
let match;
|
|
7699
|
+
while ((match = re.exec(text))) {
|
|
7700
|
+
const n = Number(match[1]);
|
|
7701
|
+
const unit = match[2].toLowerCase();
|
|
7702
|
+
total += unit === 'h' ? n * 3600000 : unit === 'm' ? n * 60000 : unit === 's' ? n * 1000 : n;
|
|
7703
|
+
}
|
|
7704
|
+
if (total > 0) return total;
|
|
7705
|
+
const asNum = Number(text);
|
|
7706
|
+
return Number.isFinite(asNum) ? asNum * 1000 : 0;
|
|
7707
|
+
}
|
|
7708
|
+
|
|
7709
|
+
function estimateLoadDurationMs(state) {
|
|
7710
|
+
const cfg = state?.config || {};
|
|
7711
|
+
const base = parseLoadDurationMs(cfg.duration || loadDurationDraft);
|
|
7712
|
+
if (!base) return 0;
|
|
7713
|
+
return cfg.executionMode === 'script' ? base + 60000 : base;
|
|
7714
|
+
}
|
|
7715
|
+
|
|
7716
|
+
function formatLoadTime(ms) {
|
|
7717
|
+
if (!ms || ms < 0) return '0s';
|
|
7718
|
+
const sec = Math.floor(ms / 1000);
|
|
7719
|
+
const m = Math.floor(sec / 60);
|
|
7720
|
+
const s = sec % 60;
|
|
7721
|
+
return m > 0 ? `${m}m ${String(s).padStart(2, '0')}s` : `${s}s`;
|
|
7722
|
+
}
|
|
7723
|
+
|
|
7724
|
+
function getLoadLiveStats() {
|
|
7725
|
+
const state = loadState || {};
|
|
7726
|
+
const buckets = loadBuckets || [];
|
|
7727
|
+
const last = buckets[buckets.length - 1] || { count: 0, errors: 0, durSum: 0, vus: 0 };
|
|
7728
|
+
const total = state.totalRequests || buckets.reduce((sum, b) => sum + (b.count || 0), 0);
|
|
7729
|
+
const errors = state.totalErrors || buckets.reduce((sum, b) => sum + (b.errors || 0), 0);
|
|
7730
|
+
const recent = buckets.slice(-5);
|
|
7731
|
+
const recentReqs = recent.reduce((sum, b) => sum + (b.count || 0), 0);
|
|
7732
|
+
const recentErrors = recent.reduce((sum, b) => sum + (b.errors || 0), 0);
|
|
7733
|
+
const recentDur = recent.reduce((sum, b) => sum + (b.durSum || 0), 0);
|
|
7734
|
+
const currentRps = last.count ? last.count / 2 : 0;
|
|
7735
|
+
const avgMs = recentReqs > 0 ? recentDur / recentReqs : 0;
|
|
7736
|
+
const errorPct = recentReqs > 0 ? (recentErrors / recentReqs) * 100 : (total > 0 ? (errors / total) * 100 : 0);
|
|
7737
|
+
const start = state.startTime || Date.now();
|
|
7738
|
+
const end = state.endTime || Date.now();
|
|
7739
|
+
const elapsedMs = Math.max(0, end - start);
|
|
7740
|
+
const estimateMs = estimateLoadDurationMs(state);
|
|
7741
|
+
let progressPct = estimateMs > 0 ? Math.min(99, Math.round((elapsedMs / estimateMs) * 100)) : 0;
|
|
7742
|
+
if (state.status === 'done' || state.status === 'stopped' || state.status === 'error') progressPct = 100;
|
|
7743
|
+
return { total, errors, currentRps, avgMs, errorPct, vus: last.vus || 0, elapsedMs, estimateMs, progressPct, hasBuckets: buckets.length > 0 };
|
|
7744
|
+
}
|
|
7745
|
+
|
|
7746
|
+
function updateLoadLiveStats() {
|
|
7747
|
+
const stats = getLoadLiveStats();
|
|
7748
|
+
const setText = (id, text) => { const el = document.getElementById(id); if (el) el.textContent = text; };
|
|
7749
|
+
setText('loadProgressValue', `${stats.progressPct}%`);
|
|
7750
|
+
setText('loadElapsedValue', stats.estimateMs ? `${formatLoadTime(stats.elapsedMs)} / ${formatLoadTime(stats.estimateMs)}` : formatLoadTime(stats.elapsedMs));
|
|
7751
|
+
setText('loadTotalRequestsValue', String(Math.round(stats.total || 0)));
|
|
7752
|
+
setText('loadRpsValue', stats.currentRps.toFixed(1));
|
|
7753
|
+
setText('loadAvgValue', stats.avgMs ? `${Math.round(stats.avgMs)} ms` : '—');
|
|
7754
|
+
setText('loadErrorValue', `${stats.errorPct.toFixed(2)}%`);
|
|
7755
|
+
setText('loadVuValue', String(Math.round(stats.vus || 0)));
|
|
7756
|
+
const fill = document.getElementById('loadProgressFill');
|
|
7757
|
+
if (fill) fill.style.width = `${stats.progressPct}%`;
|
|
7758
|
+
}
|
|
7759
|
+
|
|
7760
|
+
async function copyLoadLog(btn) {
|
|
7761
|
+
const text = (loadLogLines || []).join('\n');
|
|
7762
|
+
if (!text.trim()) return;
|
|
7763
|
+
const original = btn ? btn.textContent : '';
|
|
7764
|
+
try {
|
|
7765
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
7766
|
+
await navigator.clipboard.writeText(text);
|
|
7767
|
+
} else {
|
|
7768
|
+
const ta = document.createElement('textarea');
|
|
7769
|
+
ta.value = text;
|
|
7770
|
+
ta.style.position = 'fixed';
|
|
7771
|
+
ta.style.left = '-9999px';
|
|
7772
|
+
document.body.appendChild(ta);
|
|
7773
|
+
ta.focus();
|
|
7774
|
+
ta.select();
|
|
7775
|
+
document.execCommand('copy');
|
|
7776
|
+
ta.remove();
|
|
7777
|
+
}
|
|
7778
|
+
if (btn) {
|
|
7779
|
+
btn.textContent = 'Скопировано';
|
|
7780
|
+
setTimeout(() => { btn.textContent = original || 'Копировать лог'; }, 1400);
|
|
7781
|
+
}
|
|
7782
|
+
} catch (e) {
|
|
7783
|
+
alert('Не удалось скопировать лог: ' + e.message);
|
|
7784
|
+
}
|
|
7785
|
+
}
|
|
7786
|
+
|
|
7671
7787
|
function drawLoadChart(id, buckets, valFn, color, label) {
|
|
7672
|
-
const canvas = document.getElementById(id);
|
|
7673
|
-
if (!canvas) return;
|
|
7674
|
-
const dpr = window.devicePixelRatio || 1;
|
|
7675
|
-
const W = canvas.offsetWidth || 380;
|
|
7676
|
-
const H =
|
|
7788
|
+
const canvas = document.getElementById(id);
|
|
7789
|
+
if (!canvas) return;
|
|
7790
|
+
const dpr = window.devicePixelRatio || 1;
|
|
7791
|
+
const W = canvas.offsetWidth || 380;
|
|
7792
|
+
const H = 128;
|
|
7677
7793
|
canvas.width = W * dpr;
|
|
7678
7794
|
canvas.height = H * dpr;
|
|
7679
7795
|
const ctx = canvas.getContext('2d');
|
|
@@ -8055,10 +8171,13 @@ function renderLoad(c) {
|
|
|
8055
8171
|
loadState.status === 'stopped' ? '<span class="load-status-badge load-status-stopped">■ Остановлено</span>' :
|
|
8056
8172
|
'<span class="load-status-badge load-status-error">✗ Ошибка</span>';
|
|
8057
8173
|
|
|
8058
|
-
const summary = (loadState && loadState.summary) || {};
|
|
8059
|
-
const hasSummary = isDone && summary && Object.keys(summary).length > 0;
|
|
8060
|
-
|
|
8061
|
-
|
|
8174
|
+
const summary = (loadState && loadState.summary) || {};
|
|
8175
|
+
const hasSummary = isDone && summary && Object.keys(summary).length > 0;
|
|
8176
|
+
const liveStats = getLoadLiveStats();
|
|
8177
|
+
const elapsedText = liveStats.estimateMs ? `${formatLoadTime(liveStats.elapsedMs)} / ${formatLoadTime(liveStats.estimateMs)}` : formatLoadTime(liveStats.elapsedMs);
|
|
8178
|
+
const chartEmpty = '<div class="load-chart-empty">Жду первые точки k6 metrics.ndjson</div>';
|
|
8179
|
+
|
|
8180
|
+
c.innerHTML = `<div class="load-screen">
|
|
8062
8181
|
|
|
8063
8182
|
<div class="load-editor-topbar">
|
|
8064
8183
|
${!isRunning ? `<button class="load-back-btn" onclick="loadView='library';renderContent()">← Все тесты</button>` : ''}
|
|
@@ -8115,15 +8234,40 @@ function renderLoad(c) {
|
|
|
8115
8234
|
</div>
|
|
8116
8235
|
</div>
|
|
8117
8236
|
|
|
8118
|
-
${(isRunning || isDone || hasErr) ? `<div class="load-section">
|
|
8119
|
-
<div class="load-section-title">Живые метрики</div>
|
|
8120
|
-
<div class="load-
|
|
8121
|
-
<div class="load-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8237
|
+
${(isRunning || isDone || hasErr) ? `<div class="load-section">
|
|
8238
|
+
<div class="load-section-title">Живые метрики</div>
|
|
8239
|
+
<div class="load-live-shell">
|
|
8240
|
+
<div class="load-progress-card">
|
|
8241
|
+
<div>
|
|
8242
|
+
<div class="load-progress-value" id="loadProgressValue">${liveStats.progressPct}%</div>
|
|
8243
|
+
<div class="load-progress-label">Выполнение прогона</div>
|
|
8244
|
+
<div class="load-progress-bar"><div class="load-progress-fill" id="loadProgressFill" style="width:${liveStats.progressPct}%"></div></div>
|
|
8245
|
+
</div>
|
|
8246
|
+
<div style="margin-top:14px">
|
|
8247
|
+
<div class="load-live-kpi-lbl">Время</div>
|
|
8248
|
+
<div class="load-live-kpi-val" id="loadElapsedValue" style="font-size:18px">${escapeHtml(elapsedText)}</div>
|
|
8249
|
+
</div>
|
|
8250
|
+
</div>
|
|
8251
|
+
<div>
|
|
8252
|
+
<div class="load-live-kpis">
|
|
8253
|
+
<div class="load-live-kpi"><div class="load-live-kpi-val" id="loadTotalRequestsValue">${Math.round(liveStats.total || 0)}</div><div class="load-live-kpi-lbl">Запросов</div></div>
|
|
8254
|
+
<div class="load-live-kpi"><div class="load-live-kpi-val" id="loadRpsValue">${liveStats.currentRps.toFixed(1)}</div><div class="load-live-kpi-lbl">RPS сейчас</div></div>
|
|
8255
|
+
<div class="load-live-kpi"><div class="load-live-kpi-val" id="loadAvgValue">${liveStats.avgMs ? `${Math.round(liveStats.avgMs)} ms` : '—'}</div><div class="load-live-kpi-lbl">Avg latency</div></div>
|
|
8256
|
+
<div class="load-live-kpi"><div class="load-live-kpi-val" id="loadErrorValue" style="color:${liveStats.errorPct > 2 ? 'var(--red)' : 'var(--text)'}">${liveStats.errorPct.toFixed(2)}%</div><div class="load-live-kpi-lbl">Ошибок</div></div>
|
|
8257
|
+
</div>
|
|
8258
|
+
<div class="load-live-kpi" style="margin-bottom:10px;display:flex;align-items:center;justify-content:space-between">
|
|
8259
|
+
<div><div class="load-live-kpi-lbl">Активные VUs</div><div class="load-live-kpi-val" id="loadVuValue">${Math.round(liveStats.vus || 0)}</div></div>
|
|
8260
|
+
<div style="font-size:12px;color:var(--muted);text-align:right">Данные обновляются из <code>metrics.ndjson</code></div>
|
|
8261
|
+
</div>
|
|
8262
|
+
</div>
|
|
8263
|
+
</div>
|
|
8264
|
+
<div class="load-charts" style="margin-top:12px">
|
|
8265
|
+
<div class="load-chart-box"><div class="load-chart-label"><span>Запросов/сек</span><span class="load-chart-value">${liveStats.currentRps.toFixed(1)}</span></div>${liveStats.hasBuckets ? '<canvas id="loadChartRps"></canvas>' : chartEmpty}</div>
|
|
8266
|
+
<div class="load-chart-box"><div class="load-chart-label"><span>Среднее время ответа</span><span class="load-chart-value">${liveStats.avgMs ? `${Math.round(liveStats.avgMs)} ms` : '—'}</span></div>${liveStats.hasBuckets ? '<canvas id="loadChartLatency"></canvas>' : chartEmpty}</div>
|
|
8267
|
+
<div class="load-chart-box"><div class="load-chart-label"><span>Ошибки</span><span class="load-chart-value">${liveStats.errorPct.toFixed(2)}%</span></div>${liveStats.hasBuckets ? '<canvas id="loadChartErrors"></canvas>' : chartEmpty}</div>
|
|
8268
|
+
<div class="load-chart-box"><div class="load-chart-label"><span>Активные VUs</span><span class="load-chart-value">${Math.round(liveStats.vus || 0)}</span></div>${liveStats.hasBuckets ? '<canvas id="loadChartVus"></canvas>' : chartEmpty}</div>
|
|
8269
|
+
</div>
|
|
8270
|
+
</div>` : ''}
|
|
8127
8271
|
|
|
8128
8272
|
${hasSummary ? `<div class="load-section">
|
|
8129
8273
|
<div class="load-section-title">Итоги</div>
|
|
@@ -8140,13 +8284,16 @@ function renderLoad(c) {
|
|
|
8140
8284
|
<div class="load-btns" style="margin-top:12px">
|
|
8141
8285
|
<button class="load-btn" style="background:#1a2a3a;border-color:var(--blue);color:var(--blue)" onclick="loadAiAnalysis()">🤖 AI-анализ результатов</button>
|
|
8142
8286
|
</div>
|
|
8143
|
-
</div>` : ''}
|
|
8144
|
-
|
|
8145
|
-
<div class="load-section">
|
|
8146
|
-
<div class="load-section-title"
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
</div>
|
|
8287
|
+
</div>` : ''}
|
|
8288
|
+
|
|
8289
|
+
<div class="load-section">
|
|
8290
|
+
<div class="load-section-title" style="display:flex;align-items:center;justify-content:space-between;gap:10px">
|
|
8291
|
+
<span>Лог k6</span>
|
|
8292
|
+
<button class="load-btn" style="padding:4px 10px;text-transform:none;letter-spacing:0;font-weight:500" onclick="copyLoadLog(this)" ${loadLogLines.length ? '' : 'disabled'}>Копировать лог</button>
|
|
8293
|
+
</div>
|
|
8294
|
+
<div class="load-log" id="loadLogContent">
|
|
8295
|
+
${loadLogLines.map(l => `<div class="load-log-line">${escapeHtml(l)}</div>`).join('')}
|
|
8296
|
+
</div>
|
|
8150
8297
|
</div>
|
|
8151
8298
|
|
|
8152
8299
|
</div>`;
|
|
@@ -8817,6 +8964,15 @@ function connectSSE() {
|
|
|
8817
8964
|
loadState = { runId, status: 'running', startTime: Date.now(), buckets: [], totalRequests: 0, totalErrors: 0, logs: [], script: loadScriptDraft || '', config, summary: null };
|
|
8818
8965
|
loadBuckets = [];
|
|
8819
8966
|
loadLogLines = [];
|
|
8967
|
+
if (loadLiveUiTimer) clearInterval(loadLiveUiTimer);
|
|
8968
|
+
loadLiveUiTimer = setInterval(() => {
|
|
8969
|
+
if (!loadState || loadState.status !== 'running') {
|
|
8970
|
+
clearInterval(loadLiveUiTimer);
|
|
8971
|
+
loadLiveUiTimer = null;
|
|
8972
|
+
return;
|
|
8973
|
+
}
|
|
8974
|
+
if (contextMode === 'load') updateLoadLiveStats();
|
|
8975
|
+
}, 1000);
|
|
8820
8976
|
if (config) applyLoadConfigToFields(config);
|
|
8821
8977
|
if (contextMode === 'load') { renderSidebar(); renderContent(); }
|
|
8822
8978
|
});
|
|
@@ -8842,12 +8998,13 @@ function connectSSE() {
|
|
|
8842
8998
|
loadBuckets = buckets || [];
|
|
8843
8999
|
if (loadState) loadState.buckets = loadBuckets;
|
|
8844
9000
|
if (loadState) { loadState.totalRequests = total || 0; loadState.totalErrors = errors || 0; }
|
|
8845
|
-
if (contextMode === 'load') { drawLoadCharts(); renderSidebar(); }
|
|
9001
|
+
if (contextMode === 'load') { updateLoadLiveStats(); drawLoadCharts(); renderSidebar(); }
|
|
8846
9002
|
});
|
|
8847
9003
|
|
|
8848
9004
|
es.addEventListener('load-done', (e) => {
|
|
8849
9005
|
const { status, summary } = JSON.parse(e.data);
|
|
8850
9006
|
if (loadState) { loadState.status = status; loadState.summary = summary || null; loadState.endTime = Date.now(); }
|
|
9007
|
+
if (loadLiveUiTimer) { clearInterval(loadLiveUiTimer); loadLiveUiTimer = null; }
|
|
8851
9008
|
loadRefreshRuns();
|
|
8852
9009
|
if (contextMode === 'load') { renderSidebar(); renderContent(); }
|
|
8853
9010
|
});
|