552 lines
24 KiB
HTML
552 lines
24 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Dokumentenverwaltung - Stiftung{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1><i class="fas fa-folder-open me-2"></i>Dokumentenverwaltung</h1>
|
|
<div>
|
|
<a href="{% url 'stiftung:dokument_list' %}" class="btn btn-outline-primary">
|
|
<i class="fas fa-list me-1"></i>Alle Dokumente anzeigen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="statusMessages"></div>
|
|
|
|
<!-- Filter -->
|
|
<div class="card mb-3">
|
|
<div class="card-header">
|
|
<i class="fas fa-filter me-2"></i>Filter
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-3">
|
|
<label class="form-label">Kategorie</label>
|
|
<select id="filterCategory" class="form-select">
|
|
<option value="all">Alle</option>
|
|
<option value="destinaere">Destinatäre</option>
|
|
<option value="land">Ländereien</option>
|
|
<option value="admin">Administration</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Suche im Titel</label>
|
|
<input id="filterQuery" class="form-control" placeholder="Titel enthält..." />
|
|
</div>
|
|
<div class="col-md-3 d-flex align-items-end">
|
|
<button id="refreshDocuments" class="btn btn-primary w-100">
|
|
<i class="fas fa-sync me-1"></i>Aktualisieren
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dokumente-Liste -->
|
|
<div class="card">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<div><i class="fas fa-file-alt me-2"></i>Dokumente</div>
|
|
<small class="text-muted" id="counts"></small>
|
|
</div>
|
|
<div class="card-body" id="documentsContainer">
|
|
<div class="text-center py-5 text-muted" id="loadingState">
|
|
<div class="spinner-border" role="status"></div>
|
|
<p class="mt-2">Lade Dokumente...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Re-Link Modal -->
|
|
<div class="modal fade" id="relinkModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Dokument neu verknüpfen</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3"><strong id="relinkDocTitle"></strong></div>
|
|
<div id="currentLinks" class="mb-3"></div>
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<label class="form-label">Kategorie</label>
|
|
<select id="relinkCategory" class="form-select">
|
|
<option value="destinataer">Destinatäre</option>
|
|
<option value="land">Ländereien</option>
|
|
<option value="paechter">Pächter</option>
|
|
<option value="verpachtung">Verpachtungen</option>
|
|
<option value="rentmeister">Rentmeister</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<label class="form-label">Suche</label>
|
|
<div class="input-group">
|
|
<input id="relinkQuery" class="form-control" placeholder="Name, Ort, E-Mail, Telefon, Adresse..." />
|
|
<button id="relinkSearch" class="btn btn-outline-secondary"><i class="fas fa-search"></i></button>
|
|
</div>
|
|
<small class="form-text text-muted">Durchsucht Name, Adresse, E-Mail, Telefon und weitere Felder</small>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3" id="relinkResults" style="max-height: 400px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: 0.375rem; padding: 0.5rem;"></div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Schließen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.search-result-item:hover {
|
|
background-color: #f8f9fa !important;
|
|
border-color: #0d6efd !important;
|
|
}
|
|
#relinkResults::-webkit-scrollbar {
|
|
width: 8px;
|
|
}
|
|
#relinkResults::-webkit-scrollbar-track {
|
|
background: #f1f1f1;
|
|
border-radius: 4px;
|
|
}
|
|
#relinkResults::-webkit-scrollbar-thumb {
|
|
background: #c1c1c1;
|
|
border-radius: 4px;
|
|
}
|
|
#relinkResults::-webkit-scrollbar-thumb:hover {
|
|
background: #a8a8a8;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block javascript %}
|
|
<script>
|
|
let allDocuments = [];
|
|
let linksByPaperlessId = new Map();
|
|
let currentRelink = { linkId: null, paperlessId: null };
|
|
|
|
function showMessage(message, type) {
|
|
const statusDiv = document.getElementById('statusMessages');
|
|
const alert = document.createElement('div');
|
|
alert.className = `alert alert-${type} alert-dismissible fade show`;
|
|
alert.innerHTML = `${message}<button type="button" class="btn-close" data-bs-dismiss="alert"></button>`;
|
|
statusDiv.appendChild(alert);
|
|
setTimeout(() => alert.remove(), 5000);
|
|
}
|
|
|
|
function fetchData() {
|
|
console.log('Fetching updated document data...'); // Debug log
|
|
const loadingState = document.getElementById('loadingState');
|
|
if (loadingState) {
|
|
loadingState.style.display = 'block';
|
|
}
|
|
|
|
console.log('Making API calls to:', [
|
|
'/api/paperless/documents/?poll=1',
|
|
'/api/link-document/list/'
|
|
]);
|
|
|
|
Promise.all([
|
|
fetch('/api/paperless/documents/?poll=1').then(r => {
|
|
console.log('Paperless API response status:', r.status, r.ok);
|
|
if (!r.ok) {
|
|
throw new Error(`Paperless API failed: ${r.status} ${r.statusText}`);
|
|
}
|
|
return r.json();
|
|
}),
|
|
fetch('/api/link-document/list/').then(r => {
|
|
console.log('Link API response status:', r.status, r.ok);
|
|
if (!r.ok) {
|
|
throw new Error(`Link API failed: ${r.status} ${r.statusText}`);
|
|
}
|
|
return r.json();
|
|
})
|
|
]).then(([docs, linksResp]) => {
|
|
console.log('Data fetched successfully:', { docs: docs.documents?.length, links: linksResp.links?.length }); // Debug log
|
|
console.log('Full docs response:', docs); // Debug the full response
|
|
console.log('Full links response:', linksResp); // Debug the full response
|
|
allDocuments = docs.documents || [];
|
|
linksByPaperlessId = new Map();
|
|
// Handle new grouped links format
|
|
(linksResp.links || []).forEach(docLinks => {
|
|
console.log(`Setting linksByPaperlessId for document ${docLinks.paperless_id}:`, docLinks);
|
|
linksByPaperlessId.set(docLinks.paperless_id, docLinks);
|
|
});
|
|
console.log('Final linksByPaperlessId Map:', linksByPaperlessId);
|
|
renderDocuments();
|
|
const countsElement = document.getElementById('counts');
|
|
if (countsElement) {
|
|
countsElement.textContent = `Gesamt: ${docs.total_all} | Destinatäre: ${docs.total_destinaere} | Land: ${docs.total_land} | Admin: ${docs.total_admin}`;
|
|
}
|
|
}).catch(err => {
|
|
console.error('Error fetching data:', err);
|
|
console.error('Error details:', {
|
|
message: err.message,
|
|
stack: err.stack,
|
|
name: err.name
|
|
});
|
|
showMessage('Fehler beim Laden der Daten: ' + err.message, 'danger');
|
|
|
|
// Show error in the container
|
|
const container = document.getElementById('documentsContainer');
|
|
if (container) {
|
|
container.innerHTML = `
|
|
<div class="alert alert-danger">
|
|
<h6><i class="fas fa-exclamation-triangle me-2"></i>Fehler beim Laden der Dokumente</h6>
|
|
<p class="mb-0">${err.message}</p>
|
|
<button class="btn btn-primary mt-2" onclick="fetchData()">
|
|
<i class="fas fa-sync me-1"></i>Erneut versuchen
|
|
</button>
|
|
</div>
|
|
`;
|
|
}
|
|
}).finally(() => {
|
|
const loadingState = document.getElementById('loadingState');
|
|
if (loadingState) {
|
|
loadingState.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
function renderDocuments() {
|
|
const container = document.getElementById('documentsContainer');
|
|
const category = document.getElementById('filterCategory').value;
|
|
const query = document.getElementById('filterQuery').value.toLowerCase();
|
|
let filtered = allDocuments.slice();
|
|
if (category !== 'all') {
|
|
filtered = filtered.filter(d => d.tag_category === category);
|
|
}
|
|
if (query) {
|
|
filtered = filtered.filter(d => (d.title || '').toLowerCase().includes(query));
|
|
}
|
|
if (!filtered.length) {
|
|
container.innerHTML = '<p class="text-muted">Keine Dokumente gefunden.</p>';
|
|
return;
|
|
}
|
|
|
|
let html = '<div class="table-responsive"><table class="table table-striped align-middle"><thead><tr><th>Titel</th><th>Kategorie</th><th>Verknüpft mit</th><th>Aktionen</th></tr></thead><tbody>';
|
|
filtered.forEach(doc => {
|
|
const linkData = linksByPaperlessId.get(doc.id);
|
|
let linkedTo = '<span class="text-muted">nicht verknüpft</span>';
|
|
let hasLinks = false;
|
|
|
|
if (linkData && linkData.links && linkData.links.length > 0) {
|
|
console.log(`Document ${doc.id} (${doc.title}) has ${linkData.links.length} links:`, linkData.links);
|
|
hasLinks = true;
|
|
const linkItems = linkData.links.map(link => {
|
|
const obj = link.linked_object;
|
|
if (!obj) {
|
|
console.warn('Link missing linked_object:', link);
|
|
return `<div class="mb-1"><span class="badge bg-warning me-1">Fehler</span> Fehlerhafter Link</div>`;
|
|
}
|
|
// Generate the appropriate detail URL based on link type
|
|
let detailUrl = '#';
|
|
if (link.link_type === 'destinataer') {
|
|
detailUrl = `/destinataere/${obj.id}/`;
|
|
} else if (link.link_type === 'land') {
|
|
detailUrl = `/laendereien/${obj.id}/`;
|
|
} else if (link.link_type === 'paechter') {
|
|
detailUrl = `/paechter/${obj.id}/`;
|
|
} else if (link.link_type === 'verpachtung') {
|
|
detailUrl = `/verpachtungen/${obj.id}/`;
|
|
} else if (link.link_type === 'rentmeister') {
|
|
detailUrl = `/geschaeftsfuehrung/rentmeister/${obj.id}/`;
|
|
}
|
|
|
|
return `<div class="mb-1 d-flex align-items-center justify-content-between">
|
|
<div class="flex-grow-1">
|
|
<span class="badge bg-info me-1">${obj?.type || 'Unbekannt'}</span>
|
|
<a href="${detailUrl}" class="text-decoration-none small text-primary" title="Zu ${obj?.type || 'Entität'} navigieren">
|
|
${obj?.name || 'Unbekannt'}
|
|
<i class="fas fa-external-link-alt ms-1" style="font-size: 0.7em;"></i>
|
|
</a>
|
|
</div>
|
|
<button class="btn btn-sm btn-outline-danger ms-2" onclick="onDeleteLink('${link.id}')" title="Diese Verknüpfung löschen">
|
|
<i class="fas fa-times" style="font-size: 0.7em;"></i>
|
|
</button>
|
|
</div>`;
|
|
}).join('');
|
|
linkedTo = `<div class="small">${linkItems}</div>`;
|
|
console.log(`Final linkedTo HTML for doc ${doc.id}:`, linkedTo);
|
|
}
|
|
|
|
const openUrl = `/api/paperless/documents/${doc.id}/`;
|
|
html += `
|
|
<tr>
|
|
<td><strong>${doc.title || 'Ohne Titel'}</strong><br><small class="text-muted">Paperless-ID: ${doc.id}</small></td>
|
|
<td><span class="badge bg-secondary">${doc.tag_category}</span></td>
|
|
<td>${linkedTo}</td>
|
|
<td>
|
|
<a class="btn btn-sm btn-outline-primary" href="${openUrl}" target="_blank" title="In Paperless öffnen"><i class="fas fa-external-link-alt"></i></a>
|
|
${hasLinks ? `<button class="btn btn-sm btn-outline-danger" onclick="onDeleteAllLinks(${doc.id})" title="Alle Verknüpfungen löschen"><i class="fas fa-trash"></i></button>` : ''}
|
|
<button class="btn btn-sm btn-outline-success" onclick="onRelink('', ${doc.id}, '${(doc.title||'').replace(/'/g, "'")}')" title="Neu verknüpfen"><i class="fas fa-link"></i></button>
|
|
</td>
|
|
</tr>`;
|
|
});
|
|
html += '</tbody></table></div>';
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
function onRelink(linkId, paperlessId, title) {
|
|
currentRelink = { linkId, paperlessId };
|
|
document.getElementById('relinkDocTitle').textContent = title;
|
|
|
|
// Show current links in modal
|
|
const linkData = linksByPaperlessId.get(paperlessId);
|
|
const currentLinksDiv = document.getElementById('currentLinks');
|
|
if (linkData && linkData.links && linkData.links.length > 0) {
|
|
let currentLinksHtml = '<div class="alert alert-info"><strong>Aktuell verknüpft mit:</strong><ul class="mb-0 mt-2">';
|
|
linkData.links.forEach(link => {
|
|
const obj = link.linked_object;
|
|
currentLinksHtml += `<li><span class="badge bg-secondary me-1">${obj?.type || 'Unbekannt'}</span> ${obj?.name || 'Unbekannt'}</li>`;
|
|
});
|
|
currentLinksHtml += '</ul></div>';
|
|
currentLinksDiv.innerHTML = currentLinksHtml;
|
|
} else {
|
|
currentLinksDiv.innerHTML = '<div class="alert alert-warning">Dieses Dokument ist noch nicht verknüpft.</div>';
|
|
}
|
|
|
|
document.getElementById('relinkResults').innerHTML = '';
|
|
const modal = new bootstrap.Modal(document.getElementById('relinkModal'));
|
|
modal.show();
|
|
}
|
|
|
|
document.getElementById('relinkSearch').addEventListener('click', function() {
|
|
const category = document.getElementById('relinkCategory').value;
|
|
const q = document.getElementById('relinkQuery').value || 'all';
|
|
const target = document.getElementById('relinkResults');
|
|
target.innerHTML = '<div class="d-flex align-items-center"><div class="spinner-border spinner-border-sm me-2" role="status"></div>Suche...</div>';
|
|
fetch(`/api/link-document/search/?q=${encodeURIComponent(q)}&category=${category}`)
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
let items = data[category] || [];
|
|
if (!items.length) {
|
|
target.innerHTML = '<div class="text-center py-3 text-muted"><i class="fas fa-search me-2"></i>Keine Treffer gefunden.</div>';
|
|
return;
|
|
}
|
|
let html = `<div class="mb-2"><small class="text-muted">${items.length} Treffer gefunden</small></div>`;
|
|
|
|
// Get current links for this document to mark already linked entities
|
|
const linkData = linksByPaperlessId.get(currentRelink.paperlessId);
|
|
const currentlyLinkedIds = new Set();
|
|
if (linkData && linkData.links) {
|
|
linkData.links.forEach(link => {
|
|
if (link.linked_object && link.linked_object.id) {
|
|
currentlyLinkedIds.add(link.linked_object.id);
|
|
}
|
|
});
|
|
}
|
|
|
|
items.forEach(it => {
|
|
const isLinked = currentlyLinkedIds.has(it.id);
|
|
const linkClass = isLinked ? 'border-success bg-light' : 'border';
|
|
const buttonClass = isLinked ? 'btn-success' : 'btn-outline-primary';
|
|
const buttonIcon = isLinked ? 'fas fa-check-circle' : 'fas fa-plus';
|
|
const buttonText = isLinked ? 'Bereits verknüpft' : 'Verknüpfen';
|
|
|
|
html += `<div class="d-flex justify-content-between align-items-start ${linkClass} rounded p-3 mb-2 search-result-item" style="transition: all 0.2s;">
|
|
<div class="flex-grow-1">
|
|
<div class="fw-bold mb-1">${it.name}</div>
|
|
<div class="text-muted small mb-1">${it.details || ''}</div>
|
|
${isLinked ? '<span class="badge bg-success mt-1"><i class="fas fa-check-circle me-1"></i>Aktuell verknüpft</span>' : ''}
|
|
</div>
|
|
<button class="btn btn-sm ${buttonClass} ms-3" onclick="confirmRelink('${it.id}', '${category}')" title="${buttonText}" ${isLinked ? 'disabled' : ''}>
|
|
<i class="${buttonIcon} me-1"></i>${isLinked ? 'Verknüpft' : 'Auswählen'}
|
|
</button>
|
|
</div>`;
|
|
});
|
|
target.innerHTML = html;
|
|
})
|
|
.catch(() => { target.innerHTML = '<div class="text-center py-3 text-danger"><i class="fas fa-exclamation-triangle me-2"></i>Fehler bei der Suche</div>'; });
|
|
});
|
|
|
|
function onDeleteAllLinks(paperlessId) {
|
|
const linkData = linksByPaperlessId.get(paperlessId);
|
|
if (!linkData || !linkData.links || linkData.links.length === 0) {
|
|
showMessage('Keine Verknüpfungen zum Löschen gefunden', 'warning');
|
|
return;
|
|
}
|
|
|
|
if (!confirm(`Möchten Sie wirklich alle ${linkData.links.length} Verknüpfung(en) für dieses Dokument löschen?`)) {
|
|
return;
|
|
}
|
|
|
|
console.log(`Deleting all ${linkData.links.length} links for document ${paperlessId}:`, linkData.links);
|
|
|
|
// Delete all links for this document with proper CSRF token
|
|
const deletePromises = linkData.links.map(link => {
|
|
console.log(`Deleting link ${link.id}`);
|
|
return fetch(`/api/link-document/delete/${link.id}/`, {
|
|
method: 'DELETE',
|
|
headers: { 'X-CSRFToken': getCookie('csrftoken') }
|
|
});
|
|
});
|
|
|
|
Promise.all(deletePromises).then(responses => {
|
|
console.log('All delete responses:', responses.map(r => ({ status: r.status, ok: r.ok })));
|
|
const allSuccessful = responses.every(r => r.ok);
|
|
const failedCount = responses.filter(r => !r.ok).length;
|
|
|
|
if (allSuccessful) {
|
|
showMessage('Alle Verknüpfungen erfolgreich gelöscht', 'success');
|
|
setTimeout(() => {
|
|
fetchData();
|
|
}, 300);
|
|
} else {
|
|
console.error(`${failedCount} of ${responses.length} delete requests failed`);
|
|
showMessage(`Fehler beim Löschen von ${failedCount} Verknüpfung(en)`, 'danger');
|
|
}
|
|
}).catch(err => {
|
|
console.error('Error during bulk delete:', err);
|
|
showMessage('Fehler beim Löschen der Verknüpfungen', 'danger');
|
|
});
|
|
}
|
|
|
|
// Add Enter key support for search
|
|
document.getElementById('relinkQuery').addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
document.getElementById('relinkSearch').click();
|
|
}
|
|
});
|
|
|
|
function confirmRelink(targetId, category) {
|
|
console.log('confirmRelink called:', { targetId, category, currentRelink });
|
|
|
|
const isUpdate = !!currentRelink.linkId;
|
|
const url = isUpdate ? '/api/link-document/update/' : '/api/link-document/create/';
|
|
const payload = isUpdate ? {
|
|
link_id: currentRelink.linkId,
|
|
link_type: category,
|
|
link_id_target: targetId
|
|
} : {
|
|
paperless_id: currentRelink.paperlessId,
|
|
paperless_title: document.getElementById('relinkDocTitle').textContent,
|
|
paperless_url: `/api/paperless/documents/${currentRelink.paperlessId}/`,
|
|
link_type: category,
|
|
link_id: targetId
|
|
};
|
|
|
|
console.log('Sending request:', { url, payload });
|
|
|
|
fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCookie('csrftoken') },
|
|
body: JSON.stringify(payload)
|
|
}).then(async r => {
|
|
console.log('Response status:', r.status, r.ok);
|
|
|
|
let resp = {};
|
|
try {
|
|
resp = await r.json();
|
|
console.log('Response data:', resp);
|
|
} catch (e) {
|
|
console.log('No JSON response, treating as success if status OK');
|
|
if (r.ok) {
|
|
resp = { success: true };
|
|
} else {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
}
|
|
|
|
if (r.ok && (resp.success || resp.message)) {
|
|
console.log('Success! Showing message and refreshing...');
|
|
showMessage(resp.message || 'Verknüpfung gespeichert', 'success');
|
|
|
|
// Close modal first, then refresh data
|
|
const modal = bootstrap.Modal.getInstance(document.getElementById('relinkModal'));
|
|
if (modal) {
|
|
console.log('Closing modal...');
|
|
modal.hide();
|
|
}
|
|
|
|
// Clear search results to prevent confusion
|
|
document.getElementById('relinkResults').innerHTML = '';
|
|
document.getElementById('relinkQuery').value = '';
|
|
|
|
// Try immediate refresh first
|
|
console.log('Calling fetchData() immediately...');
|
|
fetchData();
|
|
|
|
// Also schedule a backup refresh to be sure
|
|
console.log('Scheduling backup refresh in 500ms...');
|
|
setTimeout(() => {
|
|
console.log('Backup fetchData() call...');
|
|
fetchData();
|
|
}, 500);
|
|
} else {
|
|
console.log('Error response:', resp);
|
|
showMessage(resp.error || 'Fehler beim Speichern', 'danger');
|
|
}
|
|
}).catch(err => {
|
|
console.error('Relink error:', err);
|
|
showMessage('Fehler beim Speichern', 'danger');
|
|
});
|
|
}
|
|
|
|
function onDeleteLink(linkId) {
|
|
if (!confirm('Diese Verknüpfung wirklich löschen?')) return;
|
|
|
|
console.log('Deleting individual link:', linkId);
|
|
|
|
fetch(`/api/link-document/delete/${linkId}/`, {
|
|
method: 'DELETE',
|
|
headers: { 'X-CSRFToken': getCookie('csrftoken') }
|
|
})
|
|
.then(async r => {
|
|
console.log('Delete response status:', r.status, r.ok);
|
|
let data = {};
|
|
try {
|
|
data = await r.json();
|
|
console.log('Delete response data:', data);
|
|
} catch (_) {
|
|
console.log('No JSON response, treating as success if status OK');
|
|
}
|
|
|
|
if (r.ok && (data.success === undefined || data.success === true)) {
|
|
showMessage('Verknüpfung gelöscht', 'success');
|
|
setTimeout(() => {
|
|
fetchData();
|
|
}, 300);
|
|
} else {
|
|
showMessage((data && data.error) || 'Fehler beim Löschen', 'danger');
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.error('Delete error:', err);
|
|
showMessage('Fehler beim Löschen', 'danger');
|
|
});
|
|
}
|
|
|
|
function getCookie(name) {
|
|
let cookieValue = null;
|
|
if (document.cookie && document.cookie !== '') {
|
|
const cookies = document.cookie.split(';');
|
|
for (let i = 0; i < cookies.length; i++) {
|
|
const cookie = cookies[i].trim();
|
|
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return cookieValue;
|
|
}
|
|
|
|
document.getElementById('refreshDocuments').addEventListener('click', fetchData);
|
|
document.getElementById('filterCategory').addEventListener('change', renderDocuments);
|
|
document.getElementById('filterQuery').addEventListener('input', () => { renderDocuments(); });
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('Dokumentenverwaltung page loaded, calling fetchData()...');
|
|
fetchData();
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|
|
|