erste Lauffähige Fassung

This commit is contained in:
Thomas Spohr
2025-07-29 10:33:26 +02:00
parent af2ebf4ab6
commit a481866b66
26 changed files with 500 additions and 76619 deletions

99
mod_pdf_tree/helper.php Normal file
View File

@@ -0,0 +1,99 @@
<?php
// Direktzugriff verhindern
defined('_JEXEC') or die;
// Hilfsklasse zur URI-Verarbeitung einbinden
use Joomla\CMS\Uri\Uri;
/**
* Modul-Hilfsklasse: Baumstruktur aus JSON-Datei aufbereiten
*/
class ModEisAnzeigeHelper
{
/**
* JSON-Datei einlesen und als Array zurückgeben
* @param string $jsonPath Pfad relativ zum Joomla-Root
* @return array Strukturierte Baumdaten oder leeres Array
*/
public static function getItems(string $jsonPath): array
{
$file = JPATH_ROOT . DIRECTORY_SEPARATOR . ltrim($jsonPath, '/');
if (!file_exists($file)) {
return [];
}
$json = file_get_contents($file);
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
return [];
}
return $data;
}
/**
* Baumstruktur als HTML generieren (rekursiv)
* @param array $items Eingelesene JSON-Daten
* @return string HTML-Ausgabe
*/
public static function renderTree(array $items): string
{
$html = '<ul class="pdf-tree">';
foreach ($items as $node) {
$name = htmlspecialchars($node['name'], ENT_QUOTES, 'UTF-8');
// Ordner: hat Kinder
if (isset($node['children']) && is_array($node['children'])) {
$count = self::countFiles($node['children']);
$html .= '<li class="folder">'
. '<span class="toggle">▶</span>'
. '<span class="folder-icon"></span>'
. '<span class="folder-name">'
. $name . ' (' . $count . ')'
. '</span>';
// Rekursiver Aufruf
$html .= self::renderTree($node['children']);
$html .= '</li>';
} else {
// Datei
$path = $node['path'] ?? '';
$relative = str_replace(JPATH_ROOT, '', $path);
$url = Uri::root(true) . '/' . ltrim(str_replace(DIRECTORY_SEPARATOR, '/', $relative), '/');
$html .= '<li class="file">'
. '<span class="file-icon"></span>'
. '<a href="' . $url . '" class="file-link" download>'
. $name . '</a>'
. '</li>';
}
}
$html .= '</ul>';
return $html;
}
/**
* Dateien im aktuellen Knotenbaum zählen
* @param array $items Unterknoten
* @return int Anzahl Dateien
*/
private static function countFiles(array $items): int
{
$count = 0;
foreach ($items as $node) {
if (isset($node['children']) && is_array($node['children'])) {
$count += self::countFiles($node['children']);
} else {
$count++;
}
}
return $count;
}
}

View File

@@ -0,0 +1,20 @@
<?php
// Prevent direct access
defined('_JEXEC') or die;
// Include the helper class
require_once __DIR__ . '/helper.php';
// Retrieve JSON path and access params
$jsonPath = $params->get('json_path', 'media/com_eis/documents.json');
$confidentialLevel = $params->get('confidential_level');
$privateUserId = $params->get('private_user');
// Load and parse JSON document tree
$items = ModEisAnzeigeHelper::getItems($jsonPath);
// TODO: Apply access filtering
// $items = ModEisAnzeigeHelper::filterByAccess($items, $confidentialLevel, $privateUserId);
// Render module layout
require JModuleHelper::getLayoutPath('mod_eis_anzeige', $params->get('layout', 'default'));

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="5.0" client="site" method="upgrade">
<name>EIS-Anzeige</name>
<author>Ich</author>
<version>1.0.1</version>
<description>Anzeige des PDF-Baums mit Dokumentenzählung und Expand/Collapse-All</description>
<files>
<filename module="mod_eis_anzeige">mod_eis_anzeige.php</filename>
<filename>helper.php</filename>
<folder>tmpl</folder>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field name="json_path" type="text"
default="media/com_eis/documents.json"
label="JSON Path"
description="Pfad zur JSON-Datei relativ zum Joomla Root" />
<field name="confidential_level" type="viewlevels"
label="Confidential Access Level"
description="View level for confidential documents" />
<field name="private_user" type="user"
label="Private Document Owner"
description="User who can view private documents" />
</fieldset>
</fields>
</config>
</extension>

View File

@@ -0,0 +1,114 @@
<?php defined('_JEXEC') or die; ?>
<!-- Styles für Struktur, Vorschau und Icons -->
<style>
/* Baum und Vorschau nebeneinander */
.pdf-tree-wrapper { display: flex; }
.pdf-tree-container { flex: 1; }
/* Verzeichnisliste zurücksetzen */
.pdf-tree, .pdf-tree ul {
list-style: none;
margin: 0;
padding: 0;
}
.pdf-tree li { margin: 0.3em 0; }
/* Ordner-Icons & Pfeile */
.folder > .toggle { cursor: pointer; display: inline-block; width: 1em; }
.folder-icon::before { content: "📁"; margin-right: 4px; }
/* Datei-Icon */
.file-icon::before { content: "📄"; margin-right: 4px; }
/* Standard: Unterverzeichnisse einklappen */
.pdf-tree ul {
display: none;
margin-left: 1.5em;
}
/* Vorschaufenster rechts */
#pdf-preview {
flex: 1;
margin-left: 1em;
border: 1px solid #ccc;
background: #fff;
display: none;
}
#pdf-preview iframe {
width: 100%;
height: 100%;
border: none;
}
/* Buttons oben */
.expand-collapse { margin-bottom: 0.5em; }
.expand-collapse button { margin-right: 0.5em; }
</style>
<!-- Steuerbuttons oben -->
<div class="expand-collapse">
<button id="expand-all">Expand All</button>
<button id="collapse-all">Collapse All</button>
</div>
<div class="pdf-tree-wrapper">
<!-- Links: Verzeichnisbaum -->
<div class="pdf-tree-container">
<?php echo ModEisAnzeigeHelper::renderTree($items); ?>
</div>
<!-- Rechts: Vorschau-Bereich -->
<div id="pdf-preview"></div>
</div>
<!-- Interaktivität: Vorschau, Toggle, Buttons -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// (1) Verzeichnisse auf-/zuklappen per Klick
document.querySelectorAll('.pdf-tree .toggle').forEach(function(toggle) {
toggle.addEventListener('click', function() {
var li = this.parentNode;
var ul = li.querySelector('ul');
if (!ul) return;
if (ul.style.display === 'block') {
ul.style.display = 'none'; this.textContent = '▶';
} else {
ul.style.display = 'block'; this.textContent = '▼';
}
});
});
// (2) Alle ausklappen
document.getElementById('expand-all').addEventListener('click', function() {
document.querySelectorAll('.pdf-tree ul').forEach(function(ul) {
ul.style.display = 'block';
});
document.querySelectorAll('.pdf-tree .toggle').forEach(function(toggle) {
toggle.textContent = '▼';
});
});
// (3) Alle einklappen
document.getElementById('collapse-all').addEventListener('click', function() {
document.querySelectorAll('.pdf-tree ul').forEach(function(ul) {
ul.style.display = 'none';
});
document.querySelectorAll('.pdf-tree .toggle').forEach(function(toggle) {
toggle.textContent = '▶';
});
});
// (4) Vorschau anzeigen beim Klick
var preview = document.getElementById('pdf-preview');
document.querySelectorAll('.pdf-tree .file-link').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
preview.style.display = 'block';
preview.innerHTML = '<iframe src="' + this.href + '"></iframe>';
});
});
});
</script>