fix: исправить ошибки JavaScript в современном интерфейсе
- Добавлены проверки на null для отсутствующих элементов - Исправлена ошибка 'Cannot set properties of null' - Добавлено логирование для отладки загрузки проектов и сервисов - Улучшена обработка ошибок в fetchProjects и fetchServices - Исправлена работа с layoutBadge, aggregate и groupBtn - Добавлены проверки существования элементов перед их использованием Автор: Сергей Антропов Сайт: https://devops.org.ru
This commit is contained in:
parent
43f19d32e1
commit
c647c2eb71
@ -601,11 +601,11 @@ const els = {
|
||||
lvlInfo: document.getElementById('lvlInfo'),
|
||||
lvlWarn: document.getElementById('lvlWarn'),
|
||||
lvlErr: document.getElementById('lvlErr'),
|
||||
layoutBadge: document.getElementById('layoutBadge'),
|
||||
aggregate: document.getElementById('aggregate'),
|
||||
layoutBadge: document.getElementById('layoutBadge') || { textContent: '' },
|
||||
aggregate: document.getElementById('aggregate') || { checked: false },
|
||||
themeSwitch: document.getElementById('themeSwitch'),
|
||||
copyFab: document.getElementById('copyFab'),
|
||||
groupBtn: document.getElementById('groupBtn'),
|
||||
groupBtn: document.getElementById('groupBtn') || { onclick: null },
|
||||
|
||||
// New modern elements
|
||||
containerList: document.getElementById('containerList'),
|
||||
@ -792,18 +792,27 @@ function buildTabs(){
|
||||
|
||||
function setLayout(cls){
|
||||
state.layout = cls;
|
||||
if (els.layoutBadge) {
|
||||
els.layoutBadge.textContent = 'view: ' + (cls==='tabs'?'tabs':cls);
|
||||
}
|
||||
els.grid.className = cls==='tabs' ? 'grid-1' : (cls==='grid2'?'grid-2':cls==='grid3'?'grid-3':'grid-4');
|
||||
}
|
||||
|
||||
async function fetchProjects(){
|
||||
try {
|
||||
console.log('Fetching projects...');
|
||||
const url = new URL(location.origin + '/api/projects');
|
||||
const res = await fetch(url);
|
||||
if (!res.ok){ console.error('Failed to fetch projects'); return; }
|
||||
if (!res.ok){
|
||||
console.error('Failed to fetch projects:', res.status, res.statusText);
|
||||
return;
|
||||
}
|
||||
const projects = await res.json();
|
||||
console.log('Projects loaded:', projects);
|
||||
|
||||
// Обновляем селектор проектов
|
||||
const select = els.projectSelect;
|
||||
if (select) {
|
||||
select.innerHTML = '<option value="all">All Projects</option>';
|
||||
projects.forEach(project => {
|
||||
const option = document.createElement('option');
|
||||
@ -816,11 +825,17 @@ async function fetchProjects(){
|
||||
if (localStorage.lb_project && projects.includes(localStorage.lb_project)) {
|
||||
select.value = localStorage.lb_project;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching projects:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchServices(){
|
||||
try {
|
||||
console.log('Fetching services...');
|
||||
const url = new URL(location.origin + '/api/services');
|
||||
const selectedProject = els.projectSelect.value;
|
||||
const selectedProject = els.projectSelect ? els.projectSelect.value : 'all';
|
||||
|
||||
if (selectedProject && selectedProject !== 'all') {
|
||||
url.searchParams.set('projects', selectedProject);
|
||||
@ -830,13 +845,25 @@ async function fetchServices(){
|
||||
}
|
||||
|
||||
const res = await fetch(url);
|
||||
if (!res.ok){ alert('Auth failed (HTTP)'); return; }
|
||||
if (!res.ok){
|
||||
console.error('Auth failed (HTTP):', res.status, res.statusText);
|
||||
alert('Auth failed (HTTP)');
|
||||
return;
|
||||
}
|
||||
const data = await res.json();
|
||||
console.log('Services loaded:', data);
|
||||
state.services = data;
|
||||
const pj = selectedProject === 'all' ? 'all' : selectedProject;
|
||||
|
||||
if (els.projectBadge) {
|
||||
els.projectBadge.innerHTML = 'project: <em>'+escapeHtml(pj)+'</em>';
|
||||
}
|
||||
|
||||
buildTabs();
|
||||
if (!state.current && state.services.length) switchToSingle(state.services[0]);
|
||||
} catch (error) {
|
||||
console.error('Error fetching services:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function wsUrl(containerId, service, project){
|
||||
@ -966,8 +993,12 @@ function switchToSingle(svc){
|
||||
for (const p of [...els.grid.children]) if (p!==panel) p.remove();
|
||||
|
||||
// Modern interface updates
|
||||
if (els.logTitle) {
|
||||
els.logTitle.textContent = `${svc.name} (${svc.service || svc.name})`;
|
||||
}
|
||||
if (els.logContent) {
|
||||
els.logContent.textContent = 'Connecting...';
|
||||
}
|
||||
|
||||
// Update active state in container list
|
||||
document.querySelectorAll('.container-item').forEach(item => {
|
||||
@ -1090,14 +1121,16 @@ function openFanGroup(services){
|
||||
updateIdFiltersBar();
|
||||
}
|
||||
|
||||
els.groupBtn.onclick = ()=>{
|
||||
if (els.groupBtn && els.groupBtn.onclick !== null) {
|
||||
els.groupBtn.onclick = ()=>{
|
||||
const list = state.services.map(s=> `${s.service}`).filter((v,i,a)=> a.indexOf(v)===i).join(', ');
|
||||
const ans = prompt('Введите имена сервисов через запятую:\n'+list);
|
||||
if (ans){
|
||||
const services = ans.split(',').map(x=>x.trim()).filter(Boolean);
|
||||
if (services.length) openFanGroup(services);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Controls
|
||||
els.clearBtn.onclick = ()=> Object.values(state.open).forEach(o=> o.logEl.textContent='');
|
||||
@ -1156,6 +1189,16 @@ window.addEventListener('keydown', (e)=>{
|
||||
|
||||
// Инициализация
|
||||
(async function init() {
|
||||
console.log('Initializing LogBoard+...');
|
||||
console.log('Elements found:', {
|
||||
projectSelect: !!els.projectSelect,
|
||||
containerList: !!els.containerList,
|
||||
logTitle: !!els.logTitle,
|
||||
logContent: !!els.logContent,
|
||||
mobileToggle: !!els.mobileToggle,
|
||||
themeSwitch: !!els.themeSwitch
|
||||
});
|
||||
|
||||
await fetchProjects();
|
||||
await fetchServices();
|
||||
})();
|
||||
|
Loading…
x
Reference in New Issue
Block a user