feat: добавить поддержку множественных проектов Docker Compose
- Добавлен API эндпоинт /api/projects для получения списка проектов - Обновлен API /api/services для поддержки фильтрации по множественным проектам - Добавлен селектор проектов в веб-интерфейс - Добавлена переменная окружения LOGBOARD_PROJECTS - Обновлен HTML шаблон с JavaScript функциональностью - Добавлена функция fetchProjects() для загрузки списка проектов - Обновлена функция fetchServices() для работы с выбранными проектами Автор: Сергей Антропов Сайт: https://devops.org.ru
This commit is contained in:
@@ -73,6 +73,11 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}
|
||||
<h1>LogBoard+</h1>
|
||||
<span id="projectBadge" class="badge">project: <em>all</em></span>
|
||||
<div class="controls">
|
||||
<label>Projects:
|
||||
<select id="projectSelect">
|
||||
<option value="all">All Projects</option>
|
||||
</select>
|
||||
</label>
|
||||
<span class="filterlvl">
|
||||
<label><input type="checkbox" id="lvlDebug" checked>DEBUG</label>
|
||||
<label><input type="checkbox" id="lvlInfo" checked>INFO</label>
|
||||
@@ -132,6 +137,7 @@ const els = {
|
||||
filter: document.getElementById('filter'),
|
||||
wsstate: document.getElementById('wsstate'),
|
||||
projectBadge: document.getElementById('projectBadge'),
|
||||
projectSelect: document.getElementById('projectSelect'),
|
||||
clearBtn: document.getElementById('clear'),
|
||||
refreshBtn: document.getElementById('refresh'),
|
||||
snapshotBtn: document.getElementById('snapshot'),
|
||||
@@ -144,9 +150,6 @@ const els = {
|
||||
themeSwitch: document.getElementById('themeSwitch'),
|
||||
copyFab: document.getElementById('copyFab'),
|
||||
groupBtn: document.getElementById('groupBtn'),
|
||||
aggregate: document.getElementById('aggregate'),
|
||||
themeSwitch: document.getElementById('themeSwitch'),
|
||||
copyFab: document.getElementById('copyFab'),
|
||||
};
|
||||
|
||||
// ----- Theme toggle -----
|
||||
@@ -298,14 +301,44 @@ function setLayout(cls){
|
||||
els.grid.className = cls==='tabs' ? 'grid-1' : (cls==='grid2'?'grid-2':cls==='grid3'?'grid-3':'grid-4');
|
||||
}
|
||||
|
||||
async function fetchProjects(){
|
||||
const url = new URL(location.origin + '/api/projects');
|
||||
const res = await fetch(url);
|
||||
if (!res.ok){ console.error('Failed to fetch projects'); return; }
|
||||
const projects = await res.json();
|
||||
|
||||
// Обновляем селектор проектов
|
||||
const select = els.projectSelect;
|
||||
select.innerHTML = '<option value="all">All Projects</option>';
|
||||
projects.forEach(project => {
|
||||
const option = document.createElement('option');
|
||||
option.value = project;
|
||||
option.textContent = project;
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
// Устанавливаем сохраненный проект
|
||||
if (localStorage.lb_project && projects.includes(localStorage.lb_project)) {
|
||||
select.value = localStorage.lb_project;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchServices(){
|
||||
const url = new URL(location.origin + '/api/services');
|
||||
if (localStorage.lb_project) url.searchParams.set('project', localStorage.lb_project);
|
||||
const selectedProject = els.projectSelect.value;
|
||||
|
||||
if (selectedProject && selectedProject !== 'all') {
|
||||
url.searchParams.set('projects', selectedProject);
|
||||
localStorage.lb_project = selectedProject;
|
||||
} else {
|
||||
localStorage.removeItem('lb_project');
|
||||
}
|
||||
|
||||
const res = await fetch(url);
|
||||
if (!res.ok){ alert('Auth failed (HTTP)'); return; }
|
||||
const data = await res.json();
|
||||
state.services = data;
|
||||
const pj = localStorage.lb_project || 'all';
|
||||
const pj = selectedProject === 'all' ? 'all' : selectedProject;
|
||||
els.projectBadge.innerHTML = 'project: <em>'+escapeHtml(pj)+'</em>';
|
||||
buildTabs();
|
||||
if (!state.current && state.services.length) switchToSingle(state.services[0]);
|
||||
@@ -551,6 +584,7 @@ els.groupBtn.onclick = ()=>{
|
||||
// Controls
|
||||
els.clearBtn.onclick = ()=> Object.values(state.open).forEach(o=> o.logEl.textContent='');
|
||||
els.refreshBtn.onclick = fetchServices;
|
||||
els.projectSelect.onchange = fetchServices;
|
||||
els.snapshotBtn.onclick = ()=>{ if (state.current) sendSnapshot(state.current.id); };
|
||||
els.tail.onchange = ()=> {
|
||||
Object.keys(state.open).forEach(id=>{
|
||||
@@ -588,7 +622,11 @@ window.addEventListener('keydown', (e)=>{
|
||||
}
|
||||
});
|
||||
|
||||
fetchServices();
|
||||
// Инициализация
|
||||
(async function init() {
|
||||
await fetchProjects();
|
||||
await fetchServices();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user