UI: фиксы сайдбара (обрезка container-name), стабильное обновление Tail Lines в SingleView без переподключения; улучшен UX и счетчики
This commit is contained in:
parent
6e764533d9
commit
705bc17097
@ -1947,6 +1947,7 @@ a{color:var(--link)}
|
||||
.container-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden; /* запрещаем горизонтальный скролл и обрезаем переполнение */
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
@ -1959,6 +1960,10 @@ a{color:var(--link)}
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container-item:hover {
|
||||
@ -1990,12 +1995,33 @@ a{color:var(--link)}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container-name i {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.container-name-text {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.container-service {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
margin-bottom: 4px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.container-status {
|
||||
|
@ -143,6 +143,9 @@ function determineWsState() {
|
||||
} else if (obj.ws.readyState === WebSocket.CLOSED || obj.ws.readyState === WebSocket.CLOSING) {
|
||||
closedConnections.push(id);
|
||||
}
|
||||
} else if (obj && obj.ajaxOnly) {
|
||||
// Не удаляем ajax-only объекты из state.open, они используются для AJAX обновлений
|
||||
continue;
|
||||
} else {
|
||||
closedConnections.push(id);
|
||||
}
|
||||
@ -150,6 +153,8 @@ function determineWsState() {
|
||||
|
||||
// Удаляем закрытые соединения
|
||||
closedConnections.forEach(id => {
|
||||
const obj = state.open[id];
|
||||
if (obj && obj.ajaxOnly) return; // сохраняем ajax-only объекты
|
||||
delete state.open[id];
|
||||
});
|
||||
|
||||
@ -851,9 +856,9 @@ function buildTabs(){
|
||||
svc.status === 'stopped' ? 'stopped' : 'paused';
|
||||
|
||||
item.innerHTML = `
|
||||
<div class="container-name">
|
||||
<div class="container-name" title="${escapeHtml(svc.name)}">
|
||||
<i class="fas fa-cube"></i>
|
||||
${escapeHtml(svc.name)}
|
||||
<span class="container-name-text">${escapeHtml(svc.name)}</span>
|
||||
</div>
|
||||
<div class="container-service">
|
||||
${escapeHtml(svc.service || svc.name)}
|
||||
@ -2395,8 +2400,9 @@ function openWs(svc, panel){
|
||||
els.logContent.innerHTML = '';
|
||||
}
|
||||
// Также очищаем legacy элемент лога
|
||||
if (obj.logEl) {
|
||||
obj.logEl.innerHTML = '';
|
||||
const current = state.open[id];
|
||||
if (current && current.logEl) {
|
||||
current.logEl.innerHTML = '';
|
||||
}
|
||||
|
||||
// Принудительно проверяем состояние через AJAX через 500мс и 1 секунду
|
||||
@ -4531,10 +4537,24 @@ if (els.snapshotBtn) {
|
||||
};
|
||||
}
|
||||
if (els.tail) {
|
||||
els.tail.onchange = ()=> {
|
||||
Object.keys(state.open).forEach(id=>{
|
||||
els.tail.onchange = async ()=> {
|
||||
// Single View: не переподключаем WS, просто пересчитываем отображение и счетчики
|
||||
if (!state.multiViewMode) {
|
||||
if (els.logContent) {
|
||||
updateLogVisibility(els.logContent);
|
||||
} else {
|
||||
refreshAllLogs();
|
||||
}
|
||||
// Обновляем счетчики и прокрутку
|
||||
setTimeout(() => {
|
||||
recalculateCounters();
|
||||
scrollToBottom();
|
||||
}, 50);
|
||||
return;
|
||||
}
|
||||
for (const id of Object.keys(state.open)){
|
||||
const svc = state.services.find(s=> s.id===id);
|
||||
if (!svc) return;
|
||||
if (!svc) continue;
|
||||
|
||||
// В multi view режиме используем openMultiViewWs
|
||||
if (state.multiViewMode && state.selectedContainers.includes(id)) {
|
||||
@ -4543,17 +4563,23 @@ if (els.tail) {
|
||||
} else {
|
||||
// В обычном режиме используем openWs
|
||||
const panel = els.grid.querySelector(`.panel[data-cid="${id}"]`);
|
||||
if (!panel) return;
|
||||
state.open[id].logEl.textContent='';
|
||||
closeWs(id);
|
||||
if (!panel) {
|
||||
// В современном интерфейсе панели может не быть — переподключаем через switchToSingle только для текущего контейнера
|
||||
if (state.current && state.current.id === id) {
|
||||
closeWs(id);
|
||||
// Переключаемся на тот же контейнер, чтобы пересоздать WS с новым tail
|
||||
await switchToSingle(svc);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (state.open[id] && state.open[id].logEl) {
|
||||
state.open[id].logEl.textContent='';
|
||||
}
|
||||
closeWs(id);
|
||||
openWs(svc, panel);
|
||||
}
|
||||
});
|
||||
|
||||
// Обновляем современный интерфейс
|
||||
if (state.current && els.logContent) {
|
||||
els.logContent.textContent = 'Reconnecting...';
|
||||
}
|
||||
// MultiView: не трогаем здесь UI — trimming делается ниже в делегированном обработчике
|
||||
|
||||
// Пересчитываем счетчики после изменения Tail Lines
|
||||
setTimeout(() => {
|
||||
@ -5437,11 +5463,24 @@ function reinitializeElements() {
|
||||
* @param {Array} newLogs - Массив новых логов
|
||||
*/
|
||||
function appendNewLogsForContainer(containerId, newLogs) {
|
||||
const obj = state.open[containerId];
|
||||
let obj = state.open[containerId];
|
||||
|
||||
if (!obj) {
|
||||
console.warn(`AJAX Update: Object not found for container ${containerId}`);
|
||||
return;
|
||||
// Лениво инициализируем объект для AJAX-обновлений, когда WS ещё не открыт
|
||||
const multiViewLog = document.querySelector(`.multi-view-log[data-container-id="${containerId}"]`);
|
||||
const logEl = els.logContent || multiViewLog || null;
|
||||
state.open[containerId] = {
|
||||
ws: null,
|
||||
logEl: logEl,
|
||||
wrapEl: logEl ? logEl.parentElement : null,
|
||||
counters: {dbg:0, info:0, warn:0, err:0, other:0},
|
||||
pausedBuffer: [],
|
||||
serviceName: containerId,
|
||||
allLogs: [],
|
||||
ajaxOnly: true
|
||||
};
|
||||
obj = state.open[containerId];
|
||||
console.warn(`AJAX Update: Created ajaxOnly state for container ${containerId}`);
|
||||
}
|
||||
|
||||
// Обрабатываем каждую новую строку лога через handleLine
|
||||
|
@ -309,7 +309,7 @@
|
||||
Автор: <a href="https://devops.org.ru" target="_blank">Сергей Антропов</a>
|
||||
</div>
|
||||
<div class="help-tooltip-version">
|
||||
Версия 2.0
|
||||
Версия 1.0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user