Jetzt mit einem Ordner für neue Dokumente
This commit is contained in:
BIN
com_eis/.DS_Store
vendored
BIN
com_eis/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
BIN
com_eis/administrator/.DS_Store
vendored
BIN
com_eis/administrator/.DS_Store
vendored
Binary file not shown.
BIN
com_eis/administrator/src/.DS_Store
vendored
BIN
com_eis/administrator/src/.DS_Store
vendored
Binary file not shown.
@@ -34,7 +34,10 @@ class DisplayController extends BaseController
|
|||||||
$path = SettingsHelper::getSetting('document_root', '/var/www/pdf');
|
$path = SettingsHelper::getSetting('document_root', '/var/www/pdf');
|
||||||
|
|
||||||
if (!$path || !is_dir($path)) {
|
if (!$path || !is_dir($path)) {
|
||||||
$app->enqueueMessage(Text::sprintf('COM_EIS_MSG_PATH_NOT_EXISTS', $path) ?: ('Pfad ungültig oder nicht gesetzt: ' . $path), 'error');
|
$app->enqueueMessage(
|
||||||
|
Text::sprintf('COM_EIS_MSG_PATH_NOT_EXISTS', $path) ?: ('Pfad ungültig oder nicht gesetzt: ' . $path),
|
||||||
|
'error'
|
||||||
|
);
|
||||||
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -45,12 +48,16 @@ class DisplayController extends BaseController
|
|||||||
// Alte Einträge löschen (Hinweis: Dann sind ALLE eingefügten „neu“)
|
// Alte Einträge löschen (Hinweis: Dann sind ALLE eingefügten „neu“)
|
||||||
$db->truncateTable('#__eis_documents');
|
$db->truncateTable('#__eis_documents');
|
||||||
|
|
||||||
// In Datenbank speichern und neue IDs sammeln
|
// In Datenbank speichern und neue IDs sammeln (nur Dateien)
|
||||||
$newIds = $this->saveToDb($data, null, $db);
|
$newIds = $this->saveToDb($data, null, $db);
|
||||||
|
|
||||||
// Neue IDs im UserState für die View -> virtueller Ordner "Neue Dokumente"
|
// Neue IDs im UserState für die View -> virtueller Ordner "Neue Dokumente"
|
||||||
$app->setUserState('com_eis.new_ids', $newIds);
|
$app->setUserState('com_eis.new_ids', $newIds);
|
||||||
|
|
||||||
|
// NEU: dauerhaft speichern (für das Frontend-Modul)
|
||||||
|
SettingsHelper::setSetting('last_new_ids', json_encode($newIds, JSON_UNESCAPED_SLASHES));
|
||||||
|
SettingsHelper::setSetting('last_scan_at', date('Y-m-d H:i:s'));
|
||||||
|
|
||||||
// Erfolgsmeldung
|
// Erfolgsmeldung
|
||||||
$app->enqueueMessage(Text::_('COM_EIS_MSG_SCAN_DONE') ?: 'PDF-Struktur erfolgreich gespeichert.', 'message');
|
$app->enqueueMessage(Text::_('COM_EIS_MSG_SCAN_DONE') ?: 'PDF-Struktur erfolgreich gespeichert.', 'message');
|
||||||
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||||
@@ -90,7 +97,7 @@ class DisplayController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alphabetisch stabil sortieren (Ordner/Dateien je Ebene)
|
// Alphabetisch stabil sortieren
|
||||||
usort($result, static function ($a, $b) {
|
usort($result, static function ($a, $b) {
|
||||||
return strcasecmp((string)$a['name'], (string)$b['name']);
|
return strcasecmp((string)$a['name'], (string)$b['name']);
|
||||||
});
|
});
|
||||||
|
|||||||
Binary file not shown.
@@ -31,16 +31,55 @@ class ModEisAnzeigeHelper
|
|||||||
|
|
||||||
// Sortieren nach name (case-insensitive)
|
// Sortieren nach name (case-insensitive)
|
||||||
foreach ($grouped as &$group) {
|
foreach ($grouped as &$group) {
|
||||||
usort($group, fn($a, $b) => strcasecmp($a['name'], $b['name']));
|
usort($group, fn($a, $b) => strcasecmp((string)$a['name'], (string)$b['name']));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $grouped;
|
return $grouped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Liest param/value aus #__eis_settings (Key/Value) */
|
||||||
|
private static function getSetting(string $param, $default = '')
|
||||||
|
{
|
||||||
|
$db = Factory::getDbo();
|
||||||
|
try {
|
||||||
|
$q = $db->getQuery(true)
|
||||||
|
->select($db->quoteName('value'))
|
||||||
|
->from($db->quoteName('#__eis_settings'))
|
||||||
|
->where($db->quoteName('param') . ' = ' . $db->quote($param))
|
||||||
|
->setLimit(1);
|
||||||
|
$db->setQuery($q);
|
||||||
|
$val = $db->loadResult();
|
||||||
|
return ($val !== null && $val !== '') ? $val : $default;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holt die zuletzt gespeicherten neuen Datei-IDs (vom Backend-Scan) */
|
||||||
|
private static function getLastNewIds(): array
|
||||||
|
{
|
||||||
|
$json = (string) self::getSetting('last_new_ids', '[]');
|
||||||
|
$arr = json_decode($json, true);
|
||||||
|
if (!is_array($arr)) return [];
|
||||||
|
return array_values(array_unique(array_map('intval', $arr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Baut einen flachen Index id => row über alle Items */
|
||||||
|
private static function buildFlatIndex(array $grouped): array
|
||||||
|
{
|
||||||
|
$idx = [];
|
||||||
|
foreach ($grouped as $group) {
|
||||||
|
foreach ($group as $row) {
|
||||||
|
$idx[(int) $row['id']] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $idx;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hauptfunktion zum Rendern des Baums
|
* Hauptfunktion zum Rendern des Baums (klassisch, ohne „Neue Dokumente“)
|
||||||
* - Nutzt title als alternativen Anzeigenamen (Fallback name)
|
* - Nutzt title als alternativen Anzeigenamen (Fallback name)
|
||||||
* - Fügt für Ordner eine klickbare Label-Zeile hinzu (bessere Tap-Ziele auf iPad)
|
* - Fügt für Ordner eine klickbare Label-Zeile hinzu
|
||||||
* - Liefert data-* Attribute für spätere Inline-Edits / Preview
|
* - Liefert data-* Attribute für spätere Inline-Edits / Preview
|
||||||
*/
|
*/
|
||||||
public static function renderTree(array $items, ?int $parentId = null): string
|
public static function renderTree(array $items, ?int $parentId = null): string
|
||||||
@@ -61,46 +100,23 @@ class ModEisAnzeigeHelper
|
|||||||
$displayName = htmlspecialchars($displayName, ENT_QUOTES, 'UTF-8');
|
$displayName = htmlspecialchars($displayName, ENT_QUOTES, 'UTF-8');
|
||||||
|
|
||||||
if ($isFolder) {
|
if ($isFolder) {
|
||||||
$fileCount = self::countFilesRecursive($items, $item['id']);
|
$fileCount = self::countFilesRecursive($items, (int)$item['id']);
|
||||||
|
|
||||||
// Ordner-<li> inkl. Data-Attribute + große Tap-Ziele (toggle + folder-label)
|
// Ordner-<li> inkl. Data-Attribute + große Tap-Ziele (toggle + folder-label)
|
||||||
$html .= '<li class="folder"'
|
$html .= '<li class="folder"'
|
||||||
. ' data-id="' . (int) $item['id'] . '"'
|
. ' data-id="' . (int) $item['id'] . '"'
|
||||||
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
||||||
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
||||||
|
. ' data-count="' . (int) $fileCount . '"'
|
||||||
. '>';
|
. '>';
|
||||||
$html .= '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▶</span> ';
|
$html .= '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▶</span> ';
|
||||||
$html .= '<span class="folder-label">📁 ' . $displayName . ' <small class="count">(' . (int) $fileCount . ')</small></span>';
|
$html .= '<span class="folder-label">📁 ' . $displayName . ' <small class="count">(' . (int) $fileCount . ')</small></span>';
|
||||||
|
|
||||||
// Kindknoten
|
// Kindknoten
|
||||||
$html .= self::renderTree($items, $item['id']);
|
$html .= self::renderTree($items, (int)$item['id']);
|
||||||
$html .= '</li>';
|
$html .= '</li>';
|
||||||
} else {
|
} else {
|
||||||
$link = Route::_('index.php?option=com_eis&task=download.download&id=' . $fileId);
|
$html .= self::renderSingleFileLi($item, $displayName);
|
||||||
|
|
||||||
// Tooltip + (optional) inline-Anzeige der Dateigröße
|
|
||||||
$tooltip = '';
|
|
||||||
$sizeStr = '';
|
|
||||||
if (!empty($item['path']) && is_file($item['path'])) {
|
|
||||||
$size = @filesize($item['path']);
|
|
||||||
if ($size !== false) {
|
|
||||||
$formatted = self::formatFileSize((int) $size);
|
|
||||||
$tooltip = ' title="Größe: ' . $formatted . '"';
|
|
||||||
// Wenn du die Größe auch sichtbar möchtest, Zeile darunter einkommentieren:
|
|
||||||
// $sizeStr = ' <small class="meta">(' . $formatted . ')</small>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Datei-<li> inkl. Data-Attribute + data-filename am Link (für Preview-Anzeige)
|
|
||||||
$html .= '<li class="file"'
|
|
||||||
. ' data-id="' . $fileId . '"'
|
|
||||||
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
|
||||||
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
|
||||||
. '>';
|
|
||||||
$html .= '📄 <a class="file-link" href="' . $link . '"' . $tooltip
|
|
||||||
. ' data-filename="' . $displayName . '">'
|
|
||||||
. $displayName . '</a>' . $sizeStr;
|
|
||||||
$html .= '</li>';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +124,87 @@ class ModEisAnzeigeHelper
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NEU: Rendert (falls vorhanden) zuerst einen virtuellen Ordner „Neue Dokumente“,
|
||||||
|
* danach den normalen Baum.
|
||||||
|
*/
|
||||||
|
public static function renderTreeWithNew(array $items): string
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
|
||||||
|
// 1) Virtueller Ordner „Neue Dokumente“
|
||||||
|
$newIds = self::getLastNewIds();
|
||||||
|
if (!empty($newIds)) {
|
||||||
|
$idx = self::buildFlatIndex($items);
|
||||||
|
$files = [];
|
||||||
|
|
||||||
|
foreach ($newIds as $id) {
|
||||||
|
if (!isset($idx[$id])) continue;
|
||||||
|
$row = $idx[$id];
|
||||||
|
if (!empty($row['is_folder'])) continue; // nur Dateien
|
||||||
|
$files[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($files)) {
|
||||||
|
$label = 'Neue Dokumente'; // optional via Sprachschlüssel ersetzen
|
||||||
|
|
||||||
|
$html .= '<ul class="pdf-tree">';
|
||||||
|
$html .= '<li class="folder" data-id="new" data-title="' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '" data-name="' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '" data-count="' . count($files) . '">';
|
||||||
|
$html .= '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▼</span> ';
|
||||||
|
$html .= '<span class="folder-label">🆕 ' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . ' <small class="count">(' . (int) count($files) . ')</small></span>';
|
||||||
|
|
||||||
|
// Kinder direkt sichtbar
|
||||||
|
$html .= '<ul style="display:block">';
|
||||||
|
foreach ($files as $fileRow) {
|
||||||
|
$html .= self::renderSingleFileLi($fileRow);
|
||||||
|
}
|
||||||
|
$html .= '</ul>';
|
||||||
|
|
||||||
|
$html .= '</li>';
|
||||||
|
$html .= '</ul>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Normaler Baum
|
||||||
|
$html .= self::renderTree($items, null);
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Einzelnes <li> für Datei (wiederverwendbar) */
|
||||||
|
private static function renderSingleFileLi(array $item, ?string $displayNameEscaped = null): string
|
||||||
|
{
|
||||||
|
$fileId = (int) $item['id'];
|
||||||
|
$rawName = $item['title'] ?: $item['name'];
|
||||||
|
$display = $displayNameEscaped ?? htmlspecialchars(preg_replace('/\.pdf$/i', '', (string)$rawName), ENT_QUOTES, 'UTF-8');
|
||||||
|
|
||||||
|
// Tooltip + (optional) inline-Anzeige der Dateigröße
|
||||||
|
$tooltip = '';
|
||||||
|
$sizeStr = '';
|
||||||
|
if (!empty($item['path']) && is_file((string)$item['path'])) {
|
||||||
|
$bytes = @filesize((string)$item['path']);
|
||||||
|
if ($bytes !== false) {
|
||||||
|
$formatted = self::formatFileSize((int)$bytes);
|
||||||
|
$tooltip = ' title="Größe: ' . $formatted . '"';
|
||||||
|
// $sizeStr = ' <small class="meta">(' . $formatted . ')</small>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$link = Route::_('index.php?option=com_eis&task=download.download&id=' . $fileId);
|
||||||
|
|
||||||
|
$html = '<li class="file"'
|
||||||
|
. ' data-id="' . $fileId . '"'
|
||||||
|
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
||||||
|
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
||||||
|
. '>';
|
||||||
|
$html .= '📄 <a class="file-link" href="' . $link . '"' . $tooltip
|
||||||
|
. ' data-filename="' . $display . '">'
|
||||||
|
. $display . '</a>' . $sizeStr;
|
||||||
|
$html .= '</li>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zählt alle PDF-Dateien unterhalb eines Ordners rekursiv
|
* Zählt alle PDF-Dateien unterhalb eines Ordners rekursiv
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ $pdfjsViewer = Uri::root() . 'media/com_eis/pdfjs/web/viewer.html';
|
|||||||
|
|
||||||
<div class="pdf-tree-wrapper" id="eis-wrapper">
|
<div class="pdf-tree-wrapper" id="eis-wrapper">
|
||||||
<div class="pdf-tree-container" id="eis-tree">
|
<div class="pdf-tree-container" id="eis-tree">
|
||||||
<?= ModEisAnzeigeHelper::renderTree($items); ?>
|
<?php // >>> einzige Änderung: mit virtuellem Ordner "Neue Dokumente"
|
||||||
|
echo ModEisAnzeigeHelper::renderTreeWithNew($items);
|
||||||
|
?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pdf-preview">
|
<div id="pdf-preview">
|
||||||
|
|||||||
Reference in New Issue
Block a user