Move excluded containers to separate sidebar section and improve UI
This commit is contained in:
@@ -328,6 +328,93 @@ a{color:var(--link)}
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Секция исключенных контейнеров */
|
||||
.excluded-containers-list {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.excluded-container-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.excluded-container-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.excluded-container-item:first-child {
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
.excluded-container-item:last-child {
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
}
|
||||
|
||||
.excluded-container-name {
|
||||
color: var(--fg);
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.remove-excluded-btn {
|
||||
background: var(--err);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
margin-left: 8px;
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.remove-excluded-btn:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.excluded-containers-controls {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.excluded-input {
|
||||
flex: 1;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
font-size: 12px;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.excluded-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.excluded-input::placeholder {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
background: var(--chip);
|
||||
@@ -550,6 +637,82 @@ a{color:var(--link)}
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
/* Мультивыбор проектов */
|
||||
.multi-select-container {
|
||||
position: relative;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.multi-select-display {
|
||||
background: var(--chip);
|
||||
color: var(--fg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.multi-select-display:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.multi-select-display.active {
|
||||
border-color: var(--accent);
|
||||
background: var(--tab-active);
|
||||
}
|
||||
|
||||
.multi-select-text {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.multi-select-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
z-index: 1000;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.multi-select-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.multi-select-option:hover {
|
||||
background: var(--chip);
|
||||
}
|
||||
|
||||
.multi-select-option input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.multi-select-option label {
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
color: var(--fg);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.header-controls {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
@@ -716,6 +879,19 @@ a{color:var(--link)}
|
||||
.status-indicator.stopped { background: var(--err); }
|
||||
.status-indicator.paused { background: var(--warn); }
|
||||
|
||||
.container-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s ease;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.container-link:hover {
|
||||
opacity: 1;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* Log Area */
|
||||
.log-area {
|
||||
flex: 1;
|
||||
@@ -900,6 +1076,8 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}
|
||||
<label for="wrap">Wrap text</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -920,6 +1098,24 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group collapsible" data-section="excluded">
|
||||
<div class="control-header">
|
||||
<label>Excluded</label>
|
||||
<button class="collapse-btn" data-target="excluded">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control-content" id="excluded-content">
|
||||
<div class="excluded-containers-list" id="excludedContainersList">
|
||||
<!-- Список будет загружен динамически -->
|
||||
</div>
|
||||
<div class="excluded-containers-controls">
|
||||
<input type="text" id="newExcludedContainer" placeholder="Имя контейнера" class="excluded-input">
|
||||
<button id="addExcludedContainer" class="btn btn-small">Добавить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Container List -->
|
||||
@@ -942,9 +1138,18 @@ footer{position:fixed;right:10px;bottom:10px;opacity:.6;font-size:11px}
|
||||
</button>
|
||||
<h2 class="header-title">Logs</h2>
|
||||
<span class="header-badge" id="projectBadge">
|
||||
<select id="projectSelectHeader">
|
||||
<option value="all">All Projects</option>
|
||||
</select>
|
||||
<div class="multi-select-container">
|
||||
<div class="multi-select-display" id="projectSelectDisplay">
|
||||
<span class="multi-select-text">All Projects</span>
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</div>
|
||||
<div class="multi-select-dropdown" id="projectSelectDropdown" style="display: none;">
|
||||
<div class="multi-select-option" data-value="all">
|
||||
<input type="checkbox" id="project-all" checked>
|
||||
<label for="project-all">All Projects</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<input id="filter" type="text" placeholder="Filter logs (regex)…" class="header-filter"/>
|
||||
<div class="header-controls">
|
||||
@@ -1277,10 +1482,18 @@ function buildTabs(){
|
||||
<div class="container-status">
|
||||
<span class="status-indicator ${statusClass}"></span>
|
||||
${escapeHtml(svc.status)}
|
||||
${svc.url ? `<a href="${svc.url}" target="_blank" class="container-link" title="Открыть сайт"><i class="fas fa-external-link-alt"></i></a>` : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
item.onclick = () => switchToSingle(svc);
|
||||
item.onclick = (e) => {
|
||||
// Не переключаем контейнер, если кликнули на ссылку
|
||||
if (e.target.closest('.container-link')) {
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
switchToSingle(svc);
|
||||
};
|
||||
els.containerList.appendChild(item);
|
||||
});
|
||||
}
|
||||
@@ -1307,44 +1520,230 @@ async function fetchProjects(){
|
||||
|
||||
|
||||
|
||||
// Обновляем селектор проектов в заголовке
|
||||
const headerSelect = document.getElementById('projectSelectHeader');
|
||||
console.log('Header select element found:', !!headerSelect);
|
||||
if (headerSelect) {
|
||||
headerSelect.innerHTML = '<option value="all">All Projects</option>';
|
||||
console.log('Adding projects to header select:', projects);
|
||||
// Обновляем мультивыбор проектов в заголовке
|
||||
const dropdown = document.getElementById('projectSelectDropdown');
|
||||
const display = document.getElementById('projectSelectDisplay');
|
||||
const displayText = display?.querySelector('.multi-select-text');
|
||||
|
||||
console.log('Multi-select elements found:', {dropdown: !!dropdown, display: !!display, displayText: !!displayText});
|
||||
|
||||
if (dropdown && displayText) {
|
||||
// Очищаем dropdown
|
||||
dropdown.innerHTML = '';
|
||||
|
||||
// Добавляем опцию "All Projects"
|
||||
const allOption = document.createElement('div');
|
||||
allOption.className = 'multi-select-option';
|
||||
allOption.setAttribute('data-value', 'all');
|
||||
allOption.innerHTML = `
|
||||
<input type="checkbox" id="project-all" checked>
|
||||
<label for="project-all">All Projects</label>
|
||||
`;
|
||||
dropdown.appendChild(allOption);
|
||||
|
||||
// Добавляем проекты
|
||||
console.log('Adding projects to multi-select:', projects);
|
||||
projects.forEach(project => {
|
||||
const option = document.createElement('option');
|
||||
option.value = project;
|
||||
option.textContent = project;
|
||||
headerSelect.appendChild(option);
|
||||
const option = document.createElement('div');
|
||||
option.className = 'multi-select-option';
|
||||
option.setAttribute('data-value', project);
|
||||
option.innerHTML = `
|
||||
<input type="checkbox" id="project-${project}">
|
||||
<label for="project-${project}">${escapeHtml(project)}</label>
|
||||
`;
|
||||
dropdown.appendChild(option);
|
||||
});
|
||||
|
||||
// Устанавливаем сохраненный проект
|
||||
if (localStorage.lb_project && projects.includes(localStorage.lb_project)) {
|
||||
headerSelect.value = localStorage.lb_project;
|
||||
}
|
||||
console.log('Header select updated, current value:', headerSelect.value);
|
||||
// Восстанавливаем сохраненные выбранные проекты
|
||||
const savedProjects = JSON.parse(localStorage.getItem('lb_selected_projects') || '["all"]');
|
||||
updateMultiSelect(savedProjects);
|
||||
|
||||
console.log('Multi-select updated, current selection:', savedProjects);
|
||||
} else {
|
||||
console.error('Header select element not found!');
|
||||
console.error('Multi-select elements not found!');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching projects:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для обновления мультивыбора проектов
|
||||
function updateMultiSelect(selectedProjects) {
|
||||
const dropdown = document.getElementById('projectSelectDropdown');
|
||||
const displayText = document.querySelector('.multi-select-text');
|
||||
|
||||
if (!dropdown || !displayText) return;
|
||||
|
||||
// Фильтруем выбранные проекты, оставляя только те, которые есть в dropdown
|
||||
const availableProjects = [];
|
||||
dropdown.querySelectorAll('.multi-select-option').forEach(option => {
|
||||
const value = option.getAttribute('data-value');
|
||||
availableProjects.push(value);
|
||||
});
|
||||
|
||||
const filteredProjects = selectedProjects.filter(project =>
|
||||
project === 'all' || availableProjects.includes(project)
|
||||
);
|
||||
|
||||
// Если все выбранные проекты исчезли, выбираем "All Projects"
|
||||
if (filteredProjects.length === 0 || (filteredProjects.length === 1 && filteredProjects[0] === 'all')) {
|
||||
filteredProjects.length = 0;
|
||||
filteredProjects.push('all');
|
||||
}
|
||||
|
||||
// Обновляем чекбоксы
|
||||
dropdown.querySelectorAll('.multi-select-option').forEach(option => {
|
||||
const value = option.getAttribute('data-value');
|
||||
const checkbox = option.querySelector('input[type="checkbox"]');
|
||||
if (checkbox) {
|
||||
checkbox.checked = filteredProjects.includes(value);
|
||||
}
|
||||
});
|
||||
|
||||
// Обновляем текст отображения
|
||||
if (filteredProjects.includes('all') || filteredProjects.length === 0) {
|
||||
displayText.textContent = 'All Projects';
|
||||
} else if (filteredProjects.length === 1) {
|
||||
displayText.textContent = filteredProjects[0];
|
||||
} else {
|
||||
displayText.textContent = `${filteredProjects.length} Projects`;
|
||||
}
|
||||
|
||||
// Сохраняем в localStorage
|
||||
localStorage.setItem('lb_selected_projects', JSON.stringify(filteredProjects));
|
||||
}
|
||||
|
||||
// Функция для получения выбранных проектов
|
||||
function getSelectedProjects() {
|
||||
const dropdown = document.getElementById('projectSelectDropdown');
|
||||
if (!dropdown) return ['all'];
|
||||
|
||||
const selectedProjects = [];
|
||||
dropdown.querySelectorAll('.multi-select-option input[type="checkbox"]:checked').forEach(checkbox => {
|
||||
const option = checkbox.closest('.multi-select-option');
|
||||
const value = option.getAttribute('data-value');
|
||||
selectedProjects.push(value);
|
||||
});
|
||||
|
||||
return selectedProjects.length > 0 ? selectedProjects : ['all'];
|
||||
}
|
||||
|
||||
// Функции для работы с исключенными контейнерами
|
||||
async function loadExcludedContainers() {
|
||||
try {
|
||||
const response = await fetch('/api/excluded-containers');
|
||||
if (!response.ok) {
|
||||
console.error('Ошибка загрузки исключенных контейнеров:', response.status);
|
||||
return [];
|
||||
}
|
||||
const data = await response.json();
|
||||
return data.excluded_containers || [];
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки исключенных контейнеров:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function saveExcludedContainers(containers) {
|
||||
try {
|
||||
const response = await fetch('/api/excluded-containers', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(containers)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('Ошибка сохранения исключенных контейнеров:', response.status);
|
||||
return false;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Исключенные контейнеры сохранены:', data);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Ошибка сохранения исключенных контейнеров:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function renderExcludedContainers(containers) {
|
||||
const list = document.getElementById('excludedContainersList');
|
||||
if (!list) return;
|
||||
|
||||
list.innerHTML = '';
|
||||
|
||||
if (containers.length === 0) {
|
||||
list.innerHTML = '<div class="excluded-container-item"><span class="excluded-container-name">Нет исключенных контейнеров</span></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
containers.forEach(container => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'excluded-container-item';
|
||||
item.innerHTML = `
|
||||
<span class="excluded-container-name">${escapeHtml(container)}</span>
|
||||
<button class="remove-excluded-btn" onclick="removeExcludedContainer('${escapeHtml(container)}')">×</button>
|
||||
`;
|
||||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
async function addExcludedContainer() {
|
||||
const input = document.getElementById('newExcludedContainer');
|
||||
const containerName = input.value.trim();
|
||||
|
||||
if (!containerName) {
|
||||
alert('Введите имя контейнера');
|
||||
return;
|
||||
}
|
||||
|
||||
const currentContainers = await loadExcludedContainers();
|
||||
if (currentContainers.includes(containerName)) {
|
||||
alert('Контейнер уже в списке исключенных');
|
||||
return;
|
||||
}
|
||||
|
||||
currentContainers.push(containerName);
|
||||
const success = await saveExcludedContainers(currentContainers);
|
||||
|
||||
if (success) {
|
||||
renderExcludedContainers(currentContainers);
|
||||
input.value = '';
|
||||
// Обновляем список проектов и контейнеров
|
||||
await fetchProjects();
|
||||
await fetchServices();
|
||||
} else {
|
||||
alert('Ошибка сохранения');
|
||||
}
|
||||
}
|
||||
|
||||
async function removeExcludedContainer(containerName) {
|
||||
const currentContainers = await loadExcludedContainers();
|
||||
const updatedContainers = currentContainers.filter(name => name !== containerName);
|
||||
|
||||
const success = await saveExcludedContainers(updatedContainers);
|
||||
|
||||
if (success) {
|
||||
renderExcludedContainers(updatedContainers);
|
||||
// Обновляем список проектов и контейнеров
|
||||
await fetchProjects();
|
||||
await fetchServices();
|
||||
} else {
|
||||
alert('Ошибка удаления');
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchServices(){
|
||||
try {
|
||||
console.log('Fetching services...');
|
||||
const url = new URL(location.origin + '/api/services');
|
||||
const projectSelectHeader = document.getElementById('projectSelectHeader');
|
||||
const selectedProject = projectSelectHeader ? projectSelectHeader.value : 'all';
|
||||
const selectedProjects = getSelectedProjects();
|
||||
|
||||
if (selectedProject && selectedProject !== 'all') {
|
||||
url.searchParams.set('projects', selectedProject);
|
||||
localStorage.lb_project = selectedProject;
|
||||
} else {
|
||||
localStorage.removeItem('lb_project');
|
||||
// Если выбраны конкретные проекты (не "all"), добавляем их в URL как строку через запятую
|
||||
if (selectedProjects.length > 0 && !selectedProjects.includes('all')) {
|
||||
url.searchParams.set('projects', selectedProjects.join(','));
|
||||
}
|
||||
|
||||
const res = await fetch(url);
|
||||
@@ -1356,13 +1755,6 @@ async function fetchServices(){
|
||||
const data = await res.json();
|
||||
console.log('Services loaded:', data);
|
||||
state.services = data;
|
||||
const pj = selectedProject === 'all' ? 'all' : selectedProject;
|
||||
|
||||
// Обновляем селектор в заголовке
|
||||
const headerSelect = document.getElementById('projectSelectHeader');
|
||||
if (headerSelect) {
|
||||
headerSelect.value = selectedProject;
|
||||
}
|
||||
|
||||
buildTabs();
|
||||
if (!state.current && state.services.length) switchToSingle(state.services[0]);
|
||||
@@ -1874,15 +2266,67 @@ function addCounterClickHandlers() {
|
||||
}
|
||||
|
||||
|
||||
// Функция для добавления обработчика выпадающего списка проектов в заголовке
|
||||
function addHeaderProjectSelectHandler() {
|
||||
const headerProjectSelect = document.getElementById('projectSelectHeader');
|
||||
console.log('Adding handler for header project select, element found:', !!headerProjectSelect);
|
||||
if (headerProjectSelect) {
|
||||
headerProjectSelect.onchange = () => {
|
||||
console.log('Header project select changed to:', headerProjectSelect.value);
|
||||
// Функция для добавления обработчиков мультивыбора проектов
|
||||
function addMultiSelectHandlers() {
|
||||
const display = document.getElementById('projectSelectDisplay');
|
||||
const dropdown = document.getElementById('projectSelectDropdown');
|
||||
|
||||
console.log('Adding multi-select handlers, elements found:', {display: !!display, dropdown: !!dropdown});
|
||||
|
||||
if (display && dropdown) {
|
||||
// Обработчик клика по дисплею
|
||||
display.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const isOpen = dropdown.style.display !== 'none';
|
||||
|
||||
if (isOpen) {
|
||||
dropdown.style.display = 'none';
|
||||
display.classList.remove('active');
|
||||
} else {
|
||||
dropdown.style.display = 'block';
|
||||
display.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Обработчики кликов по опциям
|
||||
dropdown.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
const option = e.target.closest('.multi-select-option');
|
||||
if (!option) return;
|
||||
|
||||
const checkbox = option.querySelector('input[type="checkbox"]');
|
||||
if (!checkbox) return;
|
||||
|
||||
const value = option.getAttribute('data-value');
|
||||
|
||||
// Специальная логика для "All Projects"
|
||||
if (value === 'all') {
|
||||
if (checkbox.checked) {
|
||||
// Если "All Projects" выбран, снимаем все остальные
|
||||
dropdown.querySelectorAll('.multi-select-option input[type="checkbox"]').forEach(cb => {
|
||||
if (cb !== checkbox) cb.checked = false;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Если выбран конкретный проект, снимаем "All Projects"
|
||||
const allCheckbox = dropdown.querySelector('#project-all');
|
||||
if (allCheckbox) allCheckbox.checked = false;
|
||||
}
|
||||
|
||||
// Обновляем отображение и загружаем сервисы
|
||||
const selectedProjects = getSelectedProjects();
|
||||
updateMultiSelect(selectedProjects);
|
||||
fetchServices();
|
||||
};
|
||||
});
|
||||
|
||||
// Закрытие dropdown при клике вне его
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!display.contains(e.target) && !dropdown.contains(e.target)) {
|
||||
dropdown.style.display = 'none';
|
||||
display.classList.remove('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2154,8 +2598,29 @@ window.addEventListener('keydown', (e)=>{
|
||||
// Добавляем обработчики для счетчиков
|
||||
addCounterClickHandlers();
|
||||
|
||||
// Добавляем обработчик для выпадающего списка проектов в заголовке
|
||||
addHeaderProjectSelectHandler();
|
||||
// Добавляем обработчик для выпадающего списка проектов в заголовке
|
||||
addMultiSelectHandlers();
|
||||
|
||||
// Загружаем и отображаем исключенные контейнеры
|
||||
loadExcludedContainers().then(containers => {
|
||||
renderExcludedContainers(containers);
|
||||
});
|
||||
|
||||
// Добавляем обработчики для исключенных контейнеров
|
||||
const addExcludedBtn = document.getElementById('addExcludedContainer');
|
||||
const newExcludedInput = document.getElementById('newExcludedContainer');
|
||||
|
||||
if (addExcludedBtn) {
|
||||
addExcludedBtn.onclick = addExcludedContainer;
|
||||
}
|
||||
|
||||
if (newExcludedInput) {
|
||||
newExcludedInput.onkeypress = (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
addExcludedContainer();
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user