263 lines
8.1 KiB
HTML
263 lines
8.1 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{% block title %}Search-DB Analyse{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container">
|
|
<h2>Index auswerten</h2>
|
|
<p class="text-muted">
|
|
Ordner auswählen und die Anzahl der Dateien pro Kategorie aus der Dateiindex abrufen.
|
|
</p>
|
|
|
|
<form id="analyzer-form" class="row g-3">
|
|
<div class="col-12">
|
|
<label class="form-label">Ordnerauswahl</label>
|
|
<div id="folder-levels" class="d-flex flex-wrap gap-2 align-items-end"></div>
|
|
<div class="form-text">Wähle zuerst den Hauptordner, füge dann bei Bedarf Unterordner hinzu.</div>
|
|
</div>
|
|
<div class="col-md-2 col-12 d-flex align-items-end">
|
|
<button type="submit" class="btn btn-primary w-100">Abfrage starten</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div id="analyzer-feedback" class="mt-3 text-danger" style="display: none;"></div>
|
|
|
|
<div id="analyzer-result" class="mt-4" style="display: none;">
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<h4 class="mb-0">Ergebnis</h4>
|
|
<span class="badge bg-secondary" id="totalCount"></span>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Kategorie</th>
|
|
<th>Anzahl Dateien</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="result-body"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
{{ super() }}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const form = document.getElementById('analyzer-form');
|
|
const feedback = document.getElementById('analyzer-feedback');
|
|
const resultWrapper = document.getElementById('analyzer-result');
|
|
const resultBody = document.getElementById('result-body');
|
|
const totalCount = document.getElementById('totalCount');
|
|
const levelsContainer = document.getElementById('folder-levels');
|
|
|
|
const levelSelects = [];
|
|
|
|
const createSelect = (level, options) => {
|
|
const wrapper = document.createElement('div');
|
|
wrapper.className = 'folder-level';
|
|
const select = document.createElement('select');
|
|
select.className = 'form-select';
|
|
select.dataset.level = level;
|
|
select.required = level === 0;
|
|
|
|
const placeholder = document.createElement('option');
|
|
placeholder.value = '';
|
|
placeholder.textContent = level === 0 ? 'Bitte auswählen' : 'Optionaler Unterordner';
|
|
select.appendChild(placeholder);
|
|
|
|
options.forEach((opt) => {
|
|
const option = document.createElement('option');
|
|
option.value = opt;
|
|
option.textContent = opt;
|
|
select.appendChild(option);
|
|
});
|
|
|
|
select.addEventListener('change', () => {
|
|
removeLevelsFrom(level + 1);
|
|
updateControlButtons();
|
|
});
|
|
|
|
const controls = document.createElement('div');
|
|
controls.className = 'd-flex gap-2 align-items-center';
|
|
const btnGroup = document.createElement('div');
|
|
btnGroup.className = 'btn-group btn-group-sm';
|
|
|
|
const addBtn = document.createElement('button');
|
|
addBtn.type = 'button';
|
|
addBtn.className = 'btn btn-outline-secondary';
|
|
addBtn.textContent = '+';
|
|
addBtn.addEventListener('click', () => handleAddLevel());
|
|
btnGroup.appendChild(addBtn);
|
|
|
|
let removeBtn = null;
|
|
if (level > 0) {
|
|
removeBtn = document.createElement('button');
|
|
removeBtn.type = 'button';
|
|
removeBtn.className = 'btn btn-outline-danger';
|
|
removeBtn.textContent = '-';
|
|
removeBtn.addEventListener('click', () => {
|
|
removeLevelsFrom(level);
|
|
updateControlButtons();
|
|
});
|
|
btnGroup.appendChild(removeBtn);
|
|
}
|
|
|
|
controls.append(select, btnGroup);
|
|
wrapper.append(controls);
|
|
levelsContainer.appendChild(wrapper);
|
|
levelSelects.push({ wrapper, select, addBtn, removeBtn, btnGroup });
|
|
};
|
|
|
|
const removeLevelsFrom = (startIndex) => {
|
|
while (levelSelects.length > startIndex) {
|
|
const item = levelSelects.pop();
|
|
levelsContainer.removeChild(item.wrapper);
|
|
}
|
|
};
|
|
|
|
const currentPath = () => {
|
|
const parts = levelSelects
|
|
.map(({ select }) => select.value)
|
|
.filter((v) => v && v.trim() !== '');
|
|
return parts.join('/');
|
|
};
|
|
|
|
const fetchChildren = async (parentPath = '') => {
|
|
const params = parentPath ? `?parent=${encodeURIComponent(parentPath)}` : '';
|
|
const response = await fetch(`{{ url_for("search_db_folders") }}${params}`);
|
|
const data = await response.json();
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Ordner konnten nicht geladen werden.');
|
|
}
|
|
return data.children || [];
|
|
};
|
|
|
|
const updateControlButtons = () => {
|
|
if (!levelSelects.length) {
|
|
return;
|
|
}
|
|
levelSelects.forEach((item, idx) => {
|
|
const isLast = idx === levelSelects.length - 1;
|
|
if (item.btnGroup) {
|
|
item.btnGroup.classList.toggle('d-none', !isLast);
|
|
}
|
|
if (item.addBtn) {
|
|
item.addBtn.disabled = !item.select.value;
|
|
}
|
|
if (item.removeBtn) {
|
|
const hideRemove = !isLast || idx === 0;
|
|
item.removeBtn.classList.toggle('d-none', hideRemove);
|
|
item.removeBtn.disabled = hideRemove;
|
|
}
|
|
});
|
|
};
|
|
|
|
const initBaseLevel = async () => {
|
|
try {
|
|
const children = await fetchChildren('');
|
|
if (!children.length) {
|
|
feedback.textContent = 'Keine Ordner in der Datenbank gefunden.';
|
|
feedback.style.display = 'block';
|
|
return;
|
|
}
|
|
createSelect(0, children);
|
|
updateControlButtons();
|
|
} catch (error) {
|
|
feedback.textContent = error.message;
|
|
feedback.style.display = 'block';
|
|
}
|
|
};
|
|
|
|
const handleAddLevel = async () => {
|
|
feedback.style.display = 'none';
|
|
const path = currentPath();
|
|
if (!path) {
|
|
feedback.textContent = 'Bitte zuerst einen Hauptordner auswählen.';
|
|
feedback.style.display = 'block';
|
|
return;
|
|
}
|
|
try {
|
|
const children = await fetchChildren(path);
|
|
if (!children.length) {
|
|
feedback.textContent = 'Keine weiteren Unterordner vorhanden.';
|
|
feedback.style.display = 'block';
|
|
return;
|
|
}
|
|
createSelect(levelSelects.length, children);
|
|
updateControlButtons();
|
|
} catch (error) {
|
|
feedback.textContent = error.message;
|
|
feedback.style.display = 'block';
|
|
}
|
|
};
|
|
|
|
initBaseLevel();
|
|
|
|
form.addEventListener('submit', async (event) => {
|
|
event.preventDefault();
|
|
feedback.style.display = 'none';
|
|
resultWrapper.style.display = 'none';
|
|
|
|
const folderPath = currentPath();
|
|
|
|
if (!folderPath) {
|
|
feedback.textContent = 'Bitte einen Ordner auswählen.';
|
|
feedback.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
const submitButton = form.querySelector('button[type="submit"]');
|
|
submitButton.disabled = true;
|
|
submitButton.textContent = 'Wird geladen...';
|
|
|
|
try {
|
|
const response = await fetch('{{ url_for("search_db_query") }}', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ folder_path: folderPath })
|
|
});
|
|
|
|
const data = await response.json();
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Abfrage fehlgeschlagen.');
|
|
}
|
|
|
|
resultBody.innerHTML = '';
|
|
if (data.categories && data.categories.length) {
|
|
data.categories.forEach((row) => {
|
|
const tr = document.createElement('tr');
|
|
const cat = document.createElement('td');
|
|
const cnt = document.createElement('td');
|
|
|
|
cat.textContent = row.category || 'Keine Kategorie';
|
|
cnt.textContent = row.count;
|
|
|
|
tr.append(cat, cnt);
|
|
resultBody.appendChild(tr);
|
|
});
|
|
} else {
|
|
const tr = document.createElement('tr');
|
|
const td = document.createElement('td');
|
|
td.colSpan = 2;
|
|
td.textContent = 'Keine Treffer gefunden.';
|
|
tr.appendChild(td);
|
|
resultBody.appendChild(tr);
|
|
}
|
|
|
|
totalCount.textContent = `${data.total || 0} Dateien`;
|
|
resultWrapper.style.display = 'block';
|
|
} catch (error) {
|
|
feedback.textContent = error.message;
|
|
feedback.style.display = 'block';
|
|
} finally {
|
|
submitButton.disabled = false;
|
|
submitButton.textContent = 'Abfrage starten';
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|