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

546 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
include "templates/Header.html";
?>
<!-- Hidden Fields -->
<input type="hidden" id="locale" value="de-DE">
<input type="hidden" id="ID" value="">
<input type="hidden" id="authType" value="Subject">
<!-- Main Content -->
<main class="main-content">
<div class="container">
<!-- Content Card -->
<div class="card">
<div class="d-flex justify-between align-center mb-20">
<h1 class="card-title" style="margin: 0;">🏷️ Schlagwortverwaltung</h1>
<button id="add" class="btn btn-primary" onclick="newSubjectShow()">
<i class="fas fa-plus"></i> Neuer Deskriptor
</button>
</div>
<!-- Bootstrap Table -->
<table
id="table"
data-toolbar="#toolbar"
data-search="true"
data-query-params-type="limit"
data-show-refresh="false"
data-show-toggle="false"
data-show-fullscreen="false"
data-show-columns="false"
data-show-columns-toggle-all="false"
data-detail-view="false"
data-show-export="false"
data-click-to-select="false"
data-trim-on-search="false"
data-minimum-count-columns="2"
data-show-pagination-switch="false"
data-page-size="25"
data-pagination="true"
data-id-field="ID"
data-page-list="[10, 25, 50, 100, all]"
data-show-footer="true"
data-side-pagination="server"
data-server-sort="true"
data-url="/Thesaurus/ajax/getSubjectData.php"
data-response-handler="responseHandler">
</table>
</div>
<!-- Records Content -->
<div class="row">
<div class="records_content"></div>
</div>
</div>
</main>
<script>
var $table = $('#table')
var $remove = $('#remove')
var selections = []
function getIdSelections() {
return $.map($table.bootstrapTable('getSelections'), function (row) {
return row.ID
})
}
function responseHandler(res) {
$.each(res.rows, function (i, row) {
row.state = $.inArray(row.ID, selections) !== -1
})
return res
}
function detailFormatter(index, row) {
var html = []
$.each(row, function (key, value) {
if (key !== "ID" && key !== "state" && key != "Text" && key != "Descriptor") {
if (value !== null && value !== undefined && String(value).length > 0)
html.push('<p><b>' + key + ':</b> ' + value + '</p>')
}
})
return html.join('')
}
function copyFormatter(value, row, index) {
if (row.Descriptor === true || row.Descriptor === 'true' || row.Descriptor === 1) {
return '<button class="btn btn-sm btn-outline-secondary copy-btn" style="padding: 2px 6px; line-height: 1;" ' +
'onclick="event.stopPropagation(); copyTermToClipboard(\'' + row.Text.replace(/'/g, "\\'") + '\', this)" ' +
'title="Begriff kopieren">' +
'<i class="fas fa-copy" style="font-size: 0.75rem;"></i>' +
'</button>';
}
return '';
}
function dspaceCountFormatter(value, row, index) {
if (row.Descriptor !== true && row.Descriptor !== 'true' && row.Descriptor !== 1) {
return '<span class="text-muted" title="Kein Deskriptor"></span>';
}
return '<span class="dspace-count-cell" data-term="' + row.Text.replace(/"/g, '&quot;') + '" data-authtype="Subject">' +
'<span class="spinner-border spinner-border-sm text-muted" style="width: 12px; height: 12px;" role="status"></span>' +
'</span>';
}
function operateFormatter(value, row, index) {
return [
'<div class="table-actions">',
'<a class="relations btn btn-sm btn-secondary" href="javascript:void(0)" title="Relationen anzeigen">',
'<i class="fas fa-table"></i>',
'</a>',
'<a class="details btn btn-sm btn-info" href="javascript:void(0)" title="Semantisches Netz">',
'<i class="fas fa-project-diagram"></i>',
'</a>',
'<a class="modify btn btn-sm btn-primary" href="javascript:void(0)" title="Bearbeiten">',
'<i class="fas fa-edit"></i>',
'</a>',
'<a class="remove btn btn-sm btn-danger" href="javascript:void(0)" title="Löschen">',
'<i class="fas fa-trash"></i>',
'</a>',
'</div>'
].join('')
}
window.operateEvents = {
'click .relations': function (e, value, row, index) {
ShowRelationsModal(row.ID, 'Subject')
},
'click .details': function (e, value, row, index) {
ShowModalDetails(row.ID)
},
'click .modify': function (e, value, row, index) {
ModifyTerm([row.ID]),
$table.bootstrapTable('refresh')
},
'click .remove': function (e, value, row, index) {
if (!confirm('Möchten Sie diesen Eintrag wirklich löschen?')) {
return;
}
$table.bootstrapTable('remove', {
field: 'ID',
values: [row.ID]
})
DeleteTerm([row.ID])
}
}
function totalTextFormatter(data) {
return 'Total'
}
function totalNameFormatter(data) {
return data.length
}
function initTableSubject() {
$table.bootstrapTable('destroy').bootstrapTable({
locale: $('#locale').val(),
columns: [
[{
title: 'Schlagworte',
colspan: 4,
align: 'center'
}],
[{
field: 'copy',
title: '',
align: 'center',
width: 40,
clickToSelect: false,
formatter: copyFormatter
},
{
field: 'Text',
title: 'Begriff',
sortable: true,
align: 'left'
},
{
field: 'DSpaceCount',
title: 'DSpace',
align: 'center',
width: 80,
clickToSelect: false,
formatter: dspaceCountFormatter
},
{
field: 'operate',
title: 'Funktionen',
align: 'center',
width: 190,
clickToSelect: false,
events: window.operateEvents,
formatter: operateFormatter
}]
]
})
$table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table',
function () {
$remove.prop('disabled', !$table.bootstrapTable('getSelections').length)
selections = getIdSelections()
}
)
$table.on('all.bs.table', function (e, name, args) {
console.log(name, args)
})
$remove.click(function () {
var ids = getIdSelections()
$table.bootstrapTable('remove', {
field: 'ID',
values: ids
})
$remove.prop('disabled', true)
})
}
function ReadDetails(RecordID) {
$('#ID').val(RecordID);
console.log('✅ RecordID gesetzt in #ID:', RecordID);
$('#search_relation').data('record-id', RecordID);
getData(1, 1, RecordID);
}
function getData(number, size, idvalue) {
var Type = document.getElementById("authType").value;
if (typeof idvalue == "undefined") {
var search = $("div.bootstrap-table > div.fixed-table-toolbar > div.search > input.form-control").val();
var id = 0
} else {
var id = idvalue
var search = ''
}
$.get('/Thesaurus/ajax/getSubjectData.php', {
id: id,
search: search,
offset: (number - 1) * size,
authType: Type,
limit: size
}, function (res) {
$table.bootstrapTable('load', res)
})
}
$(function() {
$table.on('page-change.bs.table', function (e, number, size, id) {
getData(number, size, id)
})
var options = $table.bootstrapTable('getOptions')
getData(options.pageNumber, options.pageSize)
})
// DSpace-Counts asynchron laden nach dem Rendern der Tabelle
$(function() {
$table.on('post-body.bs.table', function () {
loadDSpaceCounts();
})
})
function loadDSpaceCounts() {
$('.dspace-count-cell').each(function() {
var $cell = $(this);
var term = $cell.data('term');
var authType = $cell.data('authtype');
if (!term || $cell.data('loaded')) return;
$cell.data('loaded', true);
$.ajax({
url: '/Thesaurus/ajax/getDSpaceCount.php',
type: 'GET',
data: { authType: authType, query: term },
dataType: 'json',
timeout: 15000,
success: function(data) {
var count = (data && typeof data.count !== 'undefined') ? data.count : 0;
if (count === -1) {
$cell.html('<span class="text-muted" title="DSpace nicht erreichbar"><i class="fas fa-exclamation-triangle" style="font-size: 0.75rem;"></i></span>');
} else if (count > 0) {
$cell.html('<span class="badge" style="background-color: #1a3a5c;" title="' + count + ' Datensätze in DSpace">' + count + '</span>');
} else {
$cell.html('<span class="badge bg-danger" title="Keine Datensätze in DSpace">0</span>');
}
},
error: function() {
$cell.html('<span class="text-muted" title="Fehler"><i class="fas fa-exclamation-triangle" style="font-size: 0.75rem;"></i></span>');
}
});
});
}
$(function() {
initTableSubject()
$('#locale').change(initTableSubject)
})
</script>
<!-- Custom JS file - muss vor dem Autocomplete-Script geladen werden -->
<script type="text/javascript" src="js/SubjectScript.js"></script>
<script>
// Globale searchRelation Funktion
window.searchRelation = function() {
const $input = $('#search_relation');
if ($input.length === 0) {
console.warn('⚠️ Element #search_relation nicht gefunden');
return;
}
// Entferne alte Event-Handler um Duplikate zu vermeiden
$input.off('input blur focus');
console.log('✓ Autocomplete initialisiert für:', $input.attr('id'));
let currentRequest = null;
$input.on('input', function() {
const query = $(this).val().trim();
console.log('🔍 Input erkannt:', query);
if (currentRequest) {
currentRequest.abort();
}
if (query.length < 2) {
console.log('⚠️ Zu kurz (minimum 2 Zeichen)');
$('.autocomplete-dropdown').remove();
return;
}
console.log('📡 Sende AJAX Anfrage...');
currentRequest = $.ajax({
url: '/Thesaurus/ajax/Autocomplete.php',
method: 'POST',
data: {
query: query,
authType: 'Subject'
},
dataType: 'json',
success: function(data) {
console.log('✅ Daten erhalten:', data.length, 'Einträge');
showAutocompleteResults(data, $input);
currentRequest = null;
},
error: function(xhr, status, error) {
if (status !== 'abort') {
console.error('❌ AJAX Fehler:', error);
}
currentRequest = null;
}
});
});
$input.on('blur', function() {
setTimeout(function() {
$('.autocomplete-dropdown').remove();
}, 200);
});
$input.on('focus', function() {
const query = $(this).val().trim();
if (query.length >= 2) {
$(this).trigger('input');
}
});
$(window).on('scroll resize', function() {
if ($('.autocomplete-dropdown').length > 0) {
const offset = $input.offset();
const inputHeight = $input.outerHeight();
const scrollTop = $(window).scrollTop();
const scrollLeft = $(window).scrollLeft();
$('.autocomplete-dropdown').css({
top: offset.top - scrollTop + inputHeight,
left: offset.left - scrollLeft
});
}
});
function showAutocompleteResults(data, $input) {
$('.autocomplete-dropdown').remove();
if (data.length === 0) {
console.log('⚠️ Keine Ergebnisse');
return;
}
const $dropdown = $('<div class="autocomplete-dropdown"></div>');
data.forEach(function(item) {
const match = item.match(/^(.+?)\s*\(ID:\s*(\d+)\)$/);
const label = match ? match[1].trim() : item;
const value = match ? match[2] : item;
const $item = $('<a class="dropdown-item" href="#"></a>')
.text(label)
.data('value', value)
.data('label', label)
.data('fulltext', item);
$item.on('click', function(e) {
e.preventDefault();
const selectedItem = {
label: $(this).data('label'),
value: $(this).data('value'),
fullText: $(this).data('fulltext')
};
console.log('✅ Ausgewählt:', selectedItem);
$input.val(selectedItem.label);
$input.data('selected-id', selectedItem.value);
$input.trigger('autocomplete:select', [selectedItem]);
$('.autocomplete-dropdown').remove();
// Speichere die Werte in Data-Attributen auf dem Button
const recordID = $('#ID').val();
const recordText = $('#new_term').val(); // Text des aktuellen Schlagworts
console.log('🔍 recordID:', recordID);
console.log('🔍 recordText:', recordText);
console.log('🔍 selectedItem.value:', selectedItem.value);
console.log('🔍 selectedItem.label:', selectedItem.label);
$('#subject-anlegen').data('record-id', recordID);
$('#subject-anlegen').data('record-text', recordText);
$('#subject-anlegen').data('relation-id', selectedItem.value);
$('#subject-anlegen').data('relation-text', selectedItem.label);
console.log('✅ Data-Attribute gesetzt auf #subject-anlegen');
});
$dropdown.append($item);
});
$('body').append($dropdown);
const offset = $input.offset();
const inputHeight = $input.outerHeight();
const inputWidth = $input.outerWidth();
const scrollTop = $(window).scrollTop();
const scrollLeft = $(window).scrollLeft();
$dropdown.css({
position: 'fixed',
top: offset.top - scrollTop + inputHeight,
left: offset.left - scrollLeft,
width: inputWidth,
'min-width': inputWidth,
'z-index': 9999
});
console.log('📋 Dropdown angezeigt mit', data.length, 'Einträgen');
}
};
// Automatische Initialisierung
$(document).ready(function() {
console.log('jQuery bereit');
$('.modal').on('shown.bs.modal', function () {
console.log('📂 Modal geöffnet');
if ($('#search_relation').length > 0) {
console.log('✅ search_relation gefunden, initialisiere...');
searchRelation();
}
});
if ($('#search_relation').length > 0) {
console.log('✅ search_relation beim Laden gefunden, initialisiere...');
searchRelation();
}
// Click-Handler für den "Hinzufügen" Button
$(document).on('click', '#subject-anlegen', function(event) {
event.preventDefault();
event.stopPropagation();
const recordID = $(this).data('record-id');
const recordText = $(this).data('record-text');
const relationID = $(this).data('relation-id');
const relationText = $(this).data('relation-text');
const relationType = $('#new_relationtype').val();
console.log('🚀 Button geklickt - recordID:', recordID, '- relationID:', relationID, '- relationType:', relationType);
if (recordID && relationID) {
// Bei Synonym-Typ: andere Speicherfunktion verwenden
if (relationType === 'SYN') {
CreateNewSynonym(recordText, relationText, recordID, event);
} else {
CreateNewRelation(recordID, relationID, event);
}
} else {
console.warn('⚠️ recordID oder relationID fehlt!');
alert('Bitte zuerst einen Begriff aus der Autocomplete-Liste auswählen.');
}
});
});
</script>
<!-- Bootstrap Modals -->
<?php
$fp = fopen("templates/SubjectsModal.tpl", "r");
if ($fp) {
echo (fread($fp, filesize("templates/SubjectsModal.tpl")));
fclose($fp);
}
?>
<?php
$fp = fopen("templates/SubjectDetailsModal.tpl", "r");
if ($fp) {
echo (fread($fp, filesize("templates/SubjectDetailsModal.tpl")));
fclose($fp);
}
?>
<?php
$fp = fopen("templates/newSubject.tpl", "r");
if ($fp) {
echo (fread($fp, filesize("templates/newSubject.tpl")));
fclose($fp);
}
?>
<?php
$fp = fopen("templates/RelationsModal.tpl", "r");
if ($fp) {
echo (fread($fp, filesize("templates/RelationsModal.tpl")));
fclose($fp);
}
?>
<?php
include "templates/Footer.html";
?>