Thesaurus/index.php
2026-02-23 16:11:35 +01:00

540 lines
15 KiB
PHP

<?php
include "templates/Header.html";
?>
<style>
/* Dashboard Styles */
.dashboard-section {
margin-bottom: 30px;
}
.section-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--primary-color);
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid var(--primary-color);
display: flex;
align-items: center;
gap: 10px;
}
/* Statistik-Karten */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 15px;
margin-bottom: 20px;
}
.stat-card {
background: white;
border-radius: var(--radius-md);
padding: 20px;
border: 1px solid var(--border-color);
text-align: center;
transition: transform 0.2s, box-shadow 0.2s;
}
.stat-card:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-md);
}
.stat-icon {
font-size: 2rem;
margin-bottom: 10px;
}
.stat-value {
font-size: 2rem;
font-weight: 700;
color: var(--primary-color);
line-height: 1;
}
.stat-label {
font-size: 0.875rem;
color: var(--text-muted);
margin-top: 5px;
}
.stat-card.subject { border-top: 4px solid #28a745; }
.stat-card.subject .stat-icon { color: #28a745; }
.stat-card.person { border-top: 4px solid #007bff; }
.stat-card.person .stat-icon { color: #007bff; }
.stat-card.corporate { border-top: 4px solid #fd7e14; }
.stat-card.corporate .stat-icon { color: #fd7e14; }
.stat-card.publisher { border-top: 4px solid #6f42c1; }
.stat-card.publisher .stat-icon { color: #6f42c1; }
.stat-card.classification { border-top: 4px solid #20c997; }
.stat-card.classification .stat-icon { color: #20c997; }
.stat-card.total { border-top: 4px solid var(--primary-color); }
.stat-card.total .stat-icon { color: var(--primary-color); }
/* Zwei-Spalten Layout */
.dashboard-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 20px;
}
/* Listen-Karten */
.list-card {
background: white;
border-radius: var(--radius-md);
border: 1px solid var(--border-color);
overflow: hidden;
}
.list-card-header {
background: var(--bg-light);
padding: 12px 15px;
font-weight: 600;
color: var(--text-primary);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
gap: 8px;
}
.list-card-body {
padding: 0;
max-height: 300px;
overflow-y: auto;
}
.list-item {
padding: 10px 15px;
border-bottom: 1px solid var(--border-light);
display: flex;
justify-content: space-between;
align-items: center;
transition: background 0.2s;
}
.list-item:hover {
background: var(--bg-light);
}
.list-item:last-child {
border-bottom: none;
}
.list-item-text {
flex: 1;
font-weight: 500;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
.list-item-meta {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
.list-item-type {
font-size: 11px;
padding: 2px 8px;
border-radius: 10px;
background: var(--bg-light);
color: var(--text-muted);
}
.list-item-date {
font-size: 12px;
color: var(--text-muted);
}
.list-item-link {
color: var(--primary-color);
text-decoration: none;
}
.list-item-link:hover {
text-decoration: underline;
}
/* Qualitäts-Indikatoren */
.quality-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
}
.quality-item {
background: white;
border-radius: var(--radius-sm);
padding: 12px;
border: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.quality-label {
font-size: 0.875rem;
color: var(--text-muted);
}
.quality-value {
font-weight: 600;
font-size: 1.1rem;
}
.quality-value.warning {
color: #dc3545;
}
.quality-value.ok {
color: #28a745;
}
/* Loading */
.loading-spinner {
display: flex;
justify-content: center;
align-items: center;
padding: 40px;
color: var(--text-muted);
}
.loading-spinner i {
font-size: 2rem;
margin-right: 10px;
}
/* Navigation Cards */
.nav-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.nav-card {
background: white;
border-radius: var(--radius-md);
padding: 25px 20px;
border: 1px solid var(--border-color);
text-align: center;
text-decoration: none;
color: var(--text-primary);
transition: all 0.2s;
}
.nav-card:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-md);
border-color: var(--primary-color);
color: var(--primary-color);
}
.nav-card-icon {
font-size: 2.5rem;
margin-bottom: 10px;
}
.nav-card-title {
font-weight: 600;
font-size: 1.1rem;
}
</style>
<!-- Main Content -->
<main class="main-content">
<div class="container">
<!-- Navigation -->
<div class="card dashboard-section">
<h2 class="section-title">
<i class="fas fa-th-large"></i> Normdateien verwalten
</h2>
<div class="nav-grid">
<a href="Subjects.php" class="nav-card">
<div class="nav-card-icon">🏷️</div>
<div class="nav-card-title">Schlagworte</div>
</a>
<a href="Persons.php" class="nav-card">
<div class="nav-card-icon">👥</div>
<div class="nav-card-title">Personen</div>
</a>
<a href="Corporates.php" class="nav-card">
<div class="nav-card-icon">🏢</div>
<div class="nav-card-title">Körperschaften</div>
</a>
<a href="Publishers.php" class="nav-card">
<div class="nav-card-icon">📚</div>
<div class="nav-card-title">Verlage</div>
</a>
<a href="Classifications.php" class="nav-card">
<div class="nav-card-icon">🗂️</div>
<div class="nav-card-title">Klassifikation</div>
</a>
<a href="Treeview.php" class="nav-card">
<div class="nav-card-icon">🌳</div>
<div class="nav-card-title">Klassifikationsbaum</div>
</a>
</div>
</div>
<!-- Übersicht Card -->
<div class="card dashboard-section">
<h2 class="section-title">
<i class="fas fa-chart-bar"></i> Übersicht
</h2>
<!-- Statistik-Karten -->
<div id="stats-container">
<div class="loading-spinner">
<i class="fas fa-circle-notch fa-spin"></i>
<span>Lade Statistiken...</span>
</div>
</div>
</div>
<!-- Aktivität & Qualität -->
<div class="dashboard-row dashboard-section">
<!-- Zuletzt geändert -->
<div class="list-card">
<div class="list-card-header">
<i class="fas fa-clock"></i> Zuletzt geändert
</div>
<div class="list-card-body" id="recently-modified">
<div class="loading-spinner">
<i class="fas fa-circle-notch fa-spin"></i>
</div>
</div>
</div>
<!-- Zuletzt hinzugefügt -->
<div class="list-card">
<div class="list-card-header">
<i class="fas fa-plus-circle"></i> Zuletzt hinzugefügt
</div>
<div class="list-card-body" id="recently-created">
<div class="loading-spinner">
<i class="fas fa-circle-notch fa-spin"></i>
</div>
</div>
</div>
</div>
<!-- Qualitäts-Check -->
<div class="card dashboard-section">
<h2 class="section-title">
<i class="fas fa-check-circle"></i> Qualitäts-Check
</h2>
<p class="text-muted mb-15">Einträge ohne Relationen (Waisen)</p>
<div id="quality-container">
<div class="loading-spinner">
<i class="fas fa-circle-notch fa-spin"></i>
</div>
</div>
</div>
</div>
</main>
<script>
$(document).ready(function() {
loadDashboardStats();
});
function loadDashboardStats() {
$.get('/Thesaurus/ajax/getDashboardStats.php', function(data) {
var stats = typeof data === 'string' ? JSON.parse(data) : data;
if (stats.error) {
$('#stats-container').html('<div class="text-center text-muted p-4">Fehler beim Laden der Statistiken</div>');
return;
}
// Statistik-Karten rendern
renderStatsCards(stats);
// Zuletzt geändert
renderRecentList('#recently-modified', stats.recentlyModified);
// Zuletzt hinzugefügt
renderRecentList('#recently-created', stats.recentlyCreated);
// Qualitäts-Check
renderQualityCheck(stats);
}).fail(function() {
$('#stats-container').html('<div class="text-center text-muted p-4">Fehler beim Laden der Statistiken</div>');
});
}
function renderStatsCards(stats) {
var html = '<div class="stats-grid">';
html += '<div class="stat-card subject">';
html += '<div class="stat-icon">🏷️</div>';
html += '<div class="stat-value">' + formatNumber(stats.counts.Subject) + '</div>';
html += '<div class="stat-label">Schlagworte</div>';
html += '</div>';
html += '<div class="stat-card person">';
html += '<div class="stat-icon">👥</div>';
html += '<div class="stat-value">' + formatNumber(stats.counts.Person) + '</div>';
html += '<div class="stat-label">Personen</div>';
html += '</div>';
html += '<div class="stat-card corporate">';
html += '<div class="stat-icon">🏢</div>';
html += '<div class="stat-value">' + formatNumber(stats.counts.Corporate) + '</div>';
html += '<div class="stat-label">Körperschaften</div>';
html += '</div>';
html += '<div class="stat-card publisher">';
html += '<div class="stat-icon">📚</div>';
html += '<div class="stat-value">' + formatNumber(stats.counts.Publisher) + '</div>';
html += '<div class="stat-label">Verlage</div>';
html += '</div>';
html += '<div class="stat-card classification">';
html += '<div class="stat-icon">🗂️</div>';
html += '<div class="stat-value">' + formatNumber(stats.counts.Classification) + '</div>';
html += '<div class="stat-label">Klassifikationen</div>';
html += '</div>';
html += '<div class="stat-card total">';
html += '<div class="stat-icon"><i class="fas fa-database"></i></div>';
html += '<div class="stat-value">' + formatNumber(stats.total) + '</div>';
html += '<div class="stat-label">Gesamt</div>';
html += '</div>';
html += '</div>';
// Zusätzliche Info-Zeile
html += '<div class="d-flex gap-4 mt-15 text-muted" style="font-size: 0.9rem;">';
html += '<span><i class="fas fa-link me-1"></i> ' + formatNumber(stats.relationsTotal) + ' Relationen</span>';
html += '<span><i class="fas fa-check me-1"></i> ' + formatNumber(stats.descriptors) + ' Deskriptoren</span>';
html += '<span><i class="fas fa-times me-1"></i> ' + formatNumber(stats.nonDescriptors) + ' Non-Deskriptoren</span>';
html += '</div>';
$('#stats-container').html(html);
}
function renderRecentList(container, items) {
if (!items || items.length === 0) {
$(container).html('<div class="text-center text-muted p-4">Keine Einträge</div>');
return;
}
var html = '';
items.forEach(function(item) {
var typeLabel = getTypeLabel(item.type);
var link = getTypeLink(item.type, item.id);
var date = formatDate(item.date);
html += '<div class="list-item">';
html += '<a href="' + link + '" class="list-item-text list-item-link" title="' + escapeHtml(item.text) + '">' + escapeHtml(item.text) + '</a>';
html += '<div class="list-item-meta">';
html += '<span class="list-item-type">' + typeLabel + '</span>';
html += '<span class="list-item-date">' + date + '</span>';
html += '</div>';
html += '</div>';
});
$(container).html(html);
}
function renderQualityCheck(stats) {
var html = '<div class="quality-grid">';
var types = [
{ key: 'Subject', label: 'Schlagworte', icon: '🏷️' },
{ key: 'Person', label: 'Personen', icon: '👥' },
{ key: 'Corporate', label: 'Körperschaften', icon: '🏢' },
{ key: 'Publisher', label: 'Verlage', icon: '📚' },
{ key: 'Classification', label: 'Klassifikation', icon: '🗂️' }
];
types.forEach(function(type) {
var count = stats.orphans[type.key] || 0;
var valueClass = count > 0 ? 'warning' : 'ok';
html += '<div class="quality-item">';
html += '<span class="quality-label">' + type.icon + ' ' + type.label + '</span>';
html += '<span class="quality-value ' + valueClass + '">' + formatNumber(count) + '</span>';
html += '</div>';
});
html += '</div>';
// Gesamt-Waisen
var totalOrphans = stats.orphansTotal || 0;
html += '<div class="mt-15 text-muted" style="font-size: 0.9rem;">';
html += '<i class="fas fa-exclamation-triangle me-1"></i> ';
html += 'Gesamt: <strong>' + formatNumber(totalOrphans) + '</strong> Einträge ohne Relationen';
html += '</div>';
$('#quality-container').html(html);
}
function getTypeLabel(type) {
var labels = {
'Subject': 'Schlagwort',
'Person': 'Person',
'Corporate': 'Körperschaft',
'Publisher': 'Verlag',
'Classification': 'Klassifikation'
};
return labels[type] || type;
}
function getTypeLink(type, id) {
var links = {
'Subject': 'Subjects.php?edit=',
'Person': 'Persons.php?edit=',
'Corporate': 'Corporates.php?edit=',
'Publisher': 'Publishers.php?edit=',
'Classification': 'Classifications.php?edit='
};
return (links[type] || 'Subjects.php?edit=') + id;
}
function formatNumber(num) {
if (!num) return '0';
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
function formatDate(dateStr) {
if (!dateStr || dateStr === '0000-00-00 00:00:00') return '-';
var date = new Date(dateStr);
return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
}
function escapeHtml(text) {
if (!text) return '';
var div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
</script>
<?php
include "templates/Footer.html";
?>