Neue Features: - Badge-Farben pro Feld konfigurierbar (Admin > Element-Typen) - Datei-Vorschau Tooltip beim Hover über Datei-Badge - Mobile/Kompakte Ansicht mit einheitlichen Button-Größen - Autocomplete für Textfelder - Backup/Restore für Konfiguration Bugfixes: - Dolibarr App Navigation: Vor/Zurück-Pfeile funktionieren jetzt (Module akzeptieren id UND socid/contactid Parameter) - Datei-Badge zeigt jetzt Büroklammer-Icon Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
947 lines
36 KiB
PHP
Executable file
947 lines
36 KiB
PHP
Executable file
<?php
|
|
/* Copyright (C) 2026 Alles Watt lauft
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*/
|
|
|
|
/**
|
|
* \file tabs/contact_anlagen.php
|
|
* \brief Tab for technical installations on contact/address card
|
|
*/
|
|
|
|
// Load Dolibarr environment
|
|
$res = 0;
|
|
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
|
|
if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
|
|
if (!$res && file_exists("../../../../main.inc.php")) $res = @include "../../../../main.inc.php";
|
|
if (!$res) die("Include of main fails");
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/contact.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
|
|
dol_include_once('/kundenkarte/class/anlage.class.php');
|
|
dol_include_once('/kundenkarte/class/anlagetype.class.php');
|
|
dol_include_once('/kundenkarte/class/anlagefile.class.php');
|
|
dol_include_once('/kundenkarte/lib/kundenkarte.lib.php');
|
|
|
|
// Load translation files
|
|
$langs->loadLangs(array('companies', 'kundenkarte@kundenkarte'));
|
|
|
|
// Get parameters
|
|
// Support both 'id' and 'contactid' for compatibility with Dolibarr's contact navigation arrows
|
|
$id = GETPOSTINT('id');
|
|
if ($id <= 0) {
|
|
$id = GETPOSTINT('contactid');
|
|
}
|
|
$action = GETPOST('action', 'aZ09');
|
|
$confirm = GETPOST('confirm', 'alpha');
|
|
$systemId = GETPOSTINT('system');
|
|
$anlageId = GETPOSTINT('anlage_id');
|
|
$parentId = GETPOSTINT('parent_id');
|
|
|
|
// Security check
|
|
if (!$user->hasRight('kundenkarte', 'read')) {
|
|
accessforbidden();
|
|
}
|
|
|
|
// Initialize objects
|
|
$object = new Contact($db);
|
|
$form = new Form($db);
|
|
$anlage = new Anlage($db);
|
|
$anlageType = new AnlageType($db);
|
|
|
|
// Load contact - id is required
|
|
if ($id <= 0) {
|
|
// If no id, try to get it from anlage_id
|
|
if ($anlageId > 0) {
|
|
$tmpAnlage = new Anlage($db);
|
|
if ($tmpAnlage->fetch($anlageId) > 0) {
|
|
$id = $tmpAnlage->fk_contact;
|
|
if ($id > 0) {
|
|
// Redirect to include id in URL for proper navigation
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action='.$action.'&anlage_id='.$anlageId);
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
// Still no id - show error
|
|
accessforbidden($langs->trans('ErrorRecordNotFound'));
|
|
}
|
|
|
|
$result = $object->fetch($id);
|
|
if ($result <= 0) {
|
|
dol_print_error($db, $object->error);
|
|
exit;
|
|
}
|
|
|
|
$permissiontoread = $user->hasRight('kundenkarte', 'read');
|
|
$permissiontoadd = $user->hasRight('kundenkarte', 'write');
|
|
$permissiontodelete = $user->hasRight('kundenkarte', 'delete');
|
|
|
|
// Load ALL available systems (from dictionary)
|
|
$allSystems = array();
|
|
$sql = "SELECT rowid, code, label, picto, color FROM ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system WHERE active = 1 ORDER BY position ASC";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
$allSystems[$obj->rowid] = $obj;
|
|
}
|
|
}
|
|
|
|
// Load systems ENABLED for this contact
|
|
$customerSystems = array();
|
|
$sql = "SELECT ss.rowid, ss.fk_system, s.code, s.label, s.picto, s.color
|
|
FROM ".MAIN_DB_PREFIX."kundenkarte_societe_system ss
|
|
JOIN ".MAIN_DB_PREFIX."c_kundenkarte_anlage_system s ON s.rowid = ss.fk_system
|
|
WHERE ss.fk_soc = ".((int) $object->socid)." AND ss.fk_contact = ".((int) $id)." AND ss.active = 1 AND s.active = 1
|
|
AND s.code != 'GLOBAL'
|
|
ORDER BY s.position ASC";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
$customerSystems[$obj->fk_system] = $obj;
|
|
}
|
|
}
|
|
|
|
// Default to first enabled system if not specified
|
|
if (empty($systemId) && !empty($customerSystems)) {
|
|
$systemId = array_key_first($customerSystems);
|
|
}
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
|
|
// Add system to contact
|
|
if ($action == 'add_system' && $permissiontoadd) {
|
|
$newSystemId = GETPOSTINT('new_system_id');
|
|
if ($newSystemId > 0 && !isset($customerSystems[$newSystemId])) {
|
|
$sql = "INSERT INTO ".MAIN_DB_PREFIX."kundenkarte_societe_system";
|
|
$sql .= " (entity, fk_soc, fk_contact, fk_system, date_creation, fk_user_creat, active)";
|
|
$sql .= " VALUES (".$conf->entity.", ".((int) $object->socid).", ".((int) $id).", ".((int) $newSystemId).", NOW(), ".((int) $user->id).", 1)";
|
|
$result = $db->query($sql);
|
|
if ($result) {
|
|
setEventMessages($langs->trans('SystemAdded'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$newSystemId);
|
|
exit;
|
|
} else {
|
|
setEventMessages($db->lasterror(), null, 'errors');
|
|
}
|
|
}
|
|
$action = '';
|
|
}
|
|
|
|
// Remove system from contact
|
|
if ($action == 'confirm_remove_system' && $confirm == 'yes' && $permissiontodelete) {
|
|
$removeSystemId = GETPOSTINT('remove_system_id');
|
|
if ($removeSystemId > 0) {
|
|
// Check if system has any elements for this contact
|
|
$sql = "SELECT COUNT(*) as cnt FROM ".MAIN_DB_PREFIX."kundenkarte_anlage WHERE fk_soc = ".((int) $object->socid)." AND fk_contact = ".((int) $id)." AND fk_system = ".((int) $removeSystemId);
|
|
$resql = $db->query($sql);
|
|
$obj = $db->fetch_object($resql);
|
|
|
|
if ($obj->cnt > 0) {
|
|
setEventMessages($langs->trans('ErrorSystemHasElements'), null, 'errors');
|
|
} else {
|
|
$sql = "DELETE FROM ".MAIN_DB_PREFIX."kundenkarte_societe_system WHERE fk_soc = ".((int) $object->socid)." AND fk_contact = ".((int) $id)." AND fk_system = ".((int) $removeSystemId);
|
|
$db->query($sql);
|
|
setEventMessages($langs->trans('SystemRemoved'), null, 'mesgs');
|
|
|
|
// Switch to another system or none
|
|
unset($customerSystems[$removeSystemId]);
|
|
if (!empty($customerSystems)) {
|
|
$systemId = array_key_first($customerSystems);
|
|
} else {
|
|
$systemId = 0;
|
|
}
|
|
}
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.($systemId ? '&system='.$systemId : ''));
|
|
exit;
|
|
}
|
|
|
|
if ($action == 'add' && $permissiontoadd) {
|
|
$anlage->label = GETPOST('label', 'alphanohtml');
|
|
$anlage->fk_soc = $object->socid;
|
|
$anlage->fk_contact = $id;
|
|
$anlage->fk_anlage_type = GETPOSTINT('fk_anlage_type');
|
|
$anlage->fk_parent = GETPOSTINT('fk_parent');
|
|
$anlage->fk_system = $systemId;
|
|
$anlage->manufacturer = GETPOST('manufacturer', 'alphanohtml');
|
|
$anlage->model = GETPOST('model', 'alphanohtml');
|
|
$anlage->serial_number = GETPOST('serial_number', 'alphanohtml');
|
|
$anlage->power_rating = GETPOST('power_rating', 'alphanohtml');
|
|
$anlage->location = GETPOST('location', 'alphanohtml');
|
|
$anlage->installation_date = dol_mktime(0, 0, 0, GETPOSTINT('installation_datemonth'), GETPOSTINT('installation_dateday'), GETPOSTINT('installation_dateyear'));
|
|
$anlage->note_private = isset($_POST['note_private']) ? $_POST['note_private'] : '';
|
|
$anlage->status = 1;
|
|
|
|
// Get type - but keep current system for GLOBAL types (buildings)
|
|
$type = new AnlageType($db);
|
|
if ($type->fetch($anlage->fk_anlage_type) > 0) {
|
|
// Only change system if type is NOT a global type
|
|
// Global types (buildings) should stay in the current system
|
|
if ($type->system_code !== 'GLOBAL') {
|
|
$anlage->fk_system = $type->fk_system;
|
|
}
|
|
}
|
|
|
|
// Dynamic fields
|
|
$fieldValues = array();
|
|
$fields = $type->fetchFields();
|
|
foreach ($fields as $field) {
|
|
$value = GETPOST('field_'.$field->field_code, 'alphanohtml');
|
|
if ($value !== '') {
|
|
$fieldValues[$field->field_code] = $value;
|
|
}
|
|
}
|
|
$anlage->setFieldValues($fieldValues);
|
|
|
|
$result = $anlage->create($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId);
|
|
exit;
|
|
} else {
|
|
setEventMessages($anlage->error, $anlage->errors, 'errors');
|
|
$action = 'create';
|
|
}
|
|
}
|
|
|
|
if ($action == 'update' && $permissiontoadd) {
|
|
$anlage->fetch($anlageId);
|
|
$anlage->label = GETPOST('label', 'alphanohtml');
|
|
$anlage->fk_anlage_type = GETPOSTINT('fk_anlage_type');
|
|
$anlage->fk_parent = GETPOSTINT('fk_parent');
|
|
$anlage->manufacturer = GETPOST('manufacturer', 'alphanohtml');
|
|
$anlage->model = GETPOST('model', 'alphanohtml');
|
|
$anlage->serial_number = GETPOST('serial_number', 'alphanohtml');
|
|
$anlage->power_rating = GETPOST('power_rating', 'alphanohtml');
|
|
$anlage->location = GETPOST('location', 'alphanohtml');
|
|
$anlage->installation_date = dol_mktime(0, 0, 0, GETPOSTINT('installation_datemonth'), GETPOSTINT('installation_dateday'), GETPOSTINT('installation_dateyear'));
|
|
$anlage->note_private = isset($_POST['note_private']) ? $_POST['note_private'] : '';
|
|
|
|
// Get type - but keep current system for GLOBAL types (buildings)
|
|
$type = new AnlageType($db);
|
|
if ($type->fetch($anlage->fk_anlage_type) > 0) {
|
|
// Only change system if type is NOT a global type
|
|
// Global types (buildings) should stay in their current system
|
|
if ($type->system_code !== 'GLOBAL') {
|
|
$anlage->fk_system = $type->fk_system;
|
|
}
|
|
}
|
|
|
|
// Dynamic fields
|
|
$fieldValues = array();
|
|
$fields = $type->fetchFields();
|
|
foreach ($fields as $field) {
|
|
$value = GETPOST('field_'.$field->field_code, 'alphanohtml');
|
|
if ($value !== '') {
|
|
$fieldValues[$field->field_code] = $value;
|
|
}
|
|
}
|
|
$anlage->setFieldValues($fieldValues);
|
|
|
|
$result = $anlage->update($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId);
|
|
exit;
|
|
} else {
|
|
setEventMessages($anlage->error, $anlage->errors, 'errors');
|
|
$action = 'edit';
|
|
}
|
|
}
|
|
|
|
if ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
|
|
$anlage->fetch($anlageId);
|
|
$systemIdBefore = $anlage->fk_system;
|
|
$result = $anlage->delete($user);
|
|
if ($result > 0) {
|
|
setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
|
|
} else {
|
|
setEventMessages($anlage->error, $anlage->errors, 'errors');
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemIdBefore);
|
|
exit;
|
|
}
|
|
|
|
// File upload
|
|
if ($action == 'uploadfile' && $permissiontoadd) {
|
|
$anlage->fetch($anlageId);
|
|
$upload_dir = $anlage->getFileDirectory();
|
|
|
|
// Create directory if not exists
|
|
if (!is_dir($upload_dir)) {
|
|
dol_mkdir($upload_dir);
|
|
}
|
|
|
|
if (!empty($_FILES['userfile']['name'])) {
|
|
$result = dol_add_file_process($upload_dir, 0, 1, 'userfile', '', null, '', 1);
|
|
if ($result > 0) {
|
|
// Add to database
|
|
$anlagefile = new AnlageFile($db);
|
|
$anlagefile->fk_anlage = $anlageId;
|
|
$anlagefile->filename = dol_sanitizeFileName($_FILES['userfile']['name']);
|
|
// IMPORTANT: Store ONLY relative path (anlagen/socid/anlageid/filename) - never full path!
|
|
$anlagefile->filepath = 'anlagen/'.$anlage->fk_soc.'/'.$anlage->id.'/'.$anlagefile->filename;
|
|
$anlagefile->filesize = $_FILES['userfile']['size'];
|
|
$anlagefile->mimetype = dol_mimetype($anlagefile->filename);
|
|
$anlagefile->create($user);
|
|
|
|
// Generate thumbnail
|
|
$anlagefile->generateThumbnail();
|
|
|
|
setEventMessages($langs->trans('FileUploaded'), null, 'mesgs');
|
|
}
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=view&anlage_id='.$anlageId);
|
|
exit;
|
|
}
|
|
|
|
// File delete (after confirmation)
|
|
if ($action == 'confirm_deletefile' && $confirm == 'yes' && $permissiontodelete) {
|
|
$fileId = GETPOSTINT('fileid');
|
|
if ($fileId > 0) {
|
|
$anlagefile = new AnlageFile($db);
|
|
if ($anlagefile->fetch($fileId) > 0) {
|
|
// Delete method handles physical file and database
|
|
if ($anlagefile->delete($user) > 0) {
|
|
setEventMessages($langs->trans('FileDeleted'), null, 'mesgs');
|
|
} else {
|
|
setEventMessages($langs->trans('Error'), null, 'errors');
|
|
}
|
|
}
|
|
}
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=view&anlage_id='.$anlageId);
|
|
exit;
|
|
}
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
// Use Dolibarr standard button classes
|
|
|
|
$title = $langs->trans('TechnicalInstallations').' - '.$object->getFullName($langs);
|
|
llxHeader('', $title, '', '', 0, 0, array('/kundenkarte/js/kundenkarte.js?v=1769963241'), array('/kundenkarte/css/kundenkarte.css?v=1769964233'));
|
|
|
|
// Prepare tabs
|
|
$head = contact_prepare_head($object);
|
|
|
|
print dol_get_fiche_head($head, 'anlagen', $langs->trans("ContactAddress"), -1, 'contact');
|
|
|
|
// Contact card
|
|
$linkback = '<a href="'.DOL_URL_ROOT.'/contact/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
|
|
dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'nom');
|
|
|
|
print '<div class="fichecenter">';
|
|
|
|
// Confirmation dialogs
|
|
if ($action == 'delete') {
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?id='.$id.'&anlage_id='.$anlageId.'&system='.$systemId,
|
|
$langs->trans('DeleteElement'),
|
|
$langs->trans('ConfirmDeleteElement'),
|
|
'confirm_delete',
|
|
'',
|
|
'yes',
|
|
1
|
|
);
|
|
}
|
|
|
|
if ($action == 'remove_system') {
|
|
$removeSystemId = GETPOSTINT('remove_system_id');
|
|
$sysLabel = isset($customerSystems[$removeSystemId]) ? $customerSystems[$removeSystemId]->label : '';
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?id='.$id.'&remove_system_id='.$removeSystemId,
|
|
$langs->trans('RemoveSystem'),
|
|
$langs->trans('ConfirmRemoveSystem', $sysLabel),
|
|
'confirm_remove_system',
|
|
'',
|
|
'yes',
|
|
1
|
|
);
|
|
}
|
|
|
|
if ($action == 'askdeletefile') {
|
|
$fileId = GETPOSTINT('fileid');
|
|
print $form->formconfirm(
|
|
$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&anlage_id='.$anlageId.'&fileid='.$fileId,
|
|
$langs->trans('Delete'),
|
|
$langs->trans('ConfirmDeleteFile'),
|
|
'confirm_deletefile',
|
|
'',
|
|
'yes',
|
|
1
|
|
);
|
|
}
|
|
|
|
// System tabs (only show enabled systems for this contact)
|
|
print '<div class="kundenkarte-system-tabs-wrapper">';
|
|
print '<div class="kundenkarte-system-tabs">';
|
|
foreach ($customerSystems as $sysId => $sys) {
|
|
$activeClass = ($sysId == $systemId) ? ' active' : '';
|
|
print '<div class="kundenkarte-system-tab'.$activeClass.'" data-system="'.$sysId.'">';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$sysId.'" style="text-decoration:none;color:inherit;display:flex;align-items:center;gap:8px;">';
|
|
if ($sys->picto) {
|
|
print '<span class="kundenkarte-system-tab-icon" style="color:'.$sys->color.';">'.kundenkarte_render_icon($sys->picto).'</span>';
|
|
}
|
|
print '<span>'.dol_escape_htmltag($sys->label).'</span>';
|
|
print '</a>';
|
|
// Remove button (only if no elements)
|
|
if ($permissiontodelete && $sysId == $systemId) {
|
|
print ' <a href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&action=remove_system&remove_system_id='.$sysId.'" class="kundenkarte-system-remove" title="'.$langs->trans('RemoveSystem').'"><i class="fa fa-times"></i></a>';
|
|
}
|
|
print '</div>';
|
|
}
|
|
|
|
// Add system button (always on the right)
|
|
if ($permissiontoadd) {
|
|
// Get systems not yet enabled for this contact
|
|
$availableSystems = array_diff_key($allSystems, $customerSystems);
|
|
if (!empty($availableSystems)) {
|
|
print '<button type="button" class="button small" style="margin-left:auto;" onclick="document.getElementById(\'add-system-form\').style.display=\'block\';">';
|
|
print '<i class="fa fa-plus"></i> '.$langs->trans('AddSystem');
|
|
print '</button>';
|
|
}
|
|
}
|
|
print '</div>';
|
|
|
|
// Expand/Collapse buttons (only in tree view, not in create/edit/view/copy)
|
|
$isTreeView = !in_array($action, array('create', 'edit', 'view', 'copy'));
|
|
if ($isTreeView) {
|
|
print '<div class="kundenkarte-tree-controls">';
|
|
print '<button type="button" class="button small" id="btn-expand-all" title="'.$langs->trans('ExpandAll').'">';
|
|
print '<i class="fa fa-expand"></i> '.$langs->trans('ExpandAll');
|
|
print '</button>';
|
|
print '<button type="button" class="button small" id="btn-collapse-all" title="'.$langs->trans('CollapseAll').'">';
|
|
print '<i class="fa fa-compress"></i> '.$langs->trans('CollapseAll');
|
|
print '</button>';
|
|
if ($systemId > 0) {
|
|
$exportUrl = dol_buildpath('/kundenkarte/ajax/export_tree_pdf.php', 1).'?socid='.$object->socid.'&contactid='.$id.'&system='.$systemId;
|
|
print '<a class="button small" href="'.$exportUrl.'" title="'.$langs->trans('ExportPDF').'" target="_blank">';
|
|
print '<i class="fa fa-file-pdf-o"></i> PDF Export';
|
|
print '</a>';
|
|
}
|
|
print '</div>';
|
|
}
|
|
|
|
print '</div>'; // End kundenkarte-system-tabs-wrapper
|
|
|
|
// Add system form (hidden by default)
|
|
if ($permissiontoadd && !empty($availableSystems)) {
|
|
print '<div id="add-system-form" class="kundenkarte-add-system-form" style="display:none;margin-bottom:15px;">';
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?id='.$id.'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="add_system">';
|
|
print '<strong>'.$langs->trans('SelectSystemToAdd').':</strong> ';
|
|
print '<select name="new_system_id" class="flat">';
|
|
print '<option value="">'.$langs->trans('Select').'</option>';
|
|
foreach ($availableSystems as $avSys) {
|
|
print '<option value="'.$avSys->rowid.'">'.dol_escape_htmltag($avSys->label).'</option>';
|
|
}
|
|
print '</select>';
|
|
print ' <button type="submit" class="button small">'.$langs->trans('Add').'</button>';
|
|
print ' <button type="button" class="button small" onclick="document.getElementById(\'add-system-form\').style.display=\'none\';">'.$langs->trans('Cancel').'</button>';
|
|
print '</form>';
|
|
print '</div>';
|
|
}
|
|
|
|
// Check if contact has any systems
|
|
if (empty($customerSystems)) {
|
|
print '<div class="opacitymedium" style="padding:20px;text-align:center;">';
|
|
print '<i class="fa fa-info-circle" style="font-size:24px;margin-bottom:10px;"></i><br>';
|
|
print $langs->trans('NoSystemsConfigured').'<br><br>';
|
|
if ($permissiontoadd && !empty($allSystems)) {
|
|
print $langs->trans('ClickAddSystemToStart');
|
|
} else {
|
|
print $langs->trans('ContactAdminToAddSystems');
|
|
}
|
|
print '</div>';
|
|
} elseif ($systemId > 0) {
|
|
// Show form or tree for selected system
|
|
if (in_array($action, array('create', 'edit', 'view', 'copy'))) {
|
|
// Load element for edit/view/copy
|
|
if ($action != 'create' && $anlageId > 0) {
|
|
$anlage->fetch($anlageId);
|
|
$type = new AnlageType($db);
|
|
$type->fetch($anlage->fk_anlage_type);
|
|
$type->fetchFields();
|
|
}
|
|
|
|
// Load types for select
|
|
$types = $anlageType->fetchAllBySystem($systemId);
|
|
|
|
print '<div class="kundenkarte-element-form">';
|
|
|
|
if ($action == 'view') {
|
|
// View mode
|
|
print '<h3>'.dol_escape_htmltag($anlage->label).'</h3>';
|
|
|
|
print '<table class="border centpercent">';
|
|
|
|
print '<tr><td class="titlefield">'.$langs->trans('Type').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->type_label).'</td></tr>';
|
|
|
|
if ($anlage->manufacturer) {
|
|
print '<tr><td>'.$langs->trans('FieldManufacturer').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->manufacturer).'</td></tr>';
|
|
}
|
|
if ($anlage->model) {
|
|
print '<tr><td>'.$langs->trans('FieldModel').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->model).'</td></tr>';
|
|
}
|
|
if ($anlage->serial_number) {
|
|
print '<tr><td>'.$langs->trans('FieldSerialNumber').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->serial_number).'</td></tr>';
|
|
}
|
|
if ($anlage->power_rating) {
|
|
print '<tr><td>'.$langs->trans('FieldPowerRating').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->power_rating).'</td></tr>';
|
|
}
|
|
if ($anlage->location) {
|
|
print '<tr><td>'.$langs->trans('FieldLocation').'</td>';
|
|
print '<td>'.dol_escape_htmltag($anlage->location).'</td></tr>';
|
|
}
|
|
if ($anlage->installation_date) {
|
|
print '<tr><td>'.$langs->trans('FieldInstallationDate').'</td>';
|
|
print '<td>'.dol_print_date($anlage->installation_date, 'day').'</td></tr>';
|
|
}
|
|
|
|
// Dynamic fields
|
|
$fieldValues = $anlage->getFieldValues();
|
|
foreach ($type->fields as $field) {
|
|
if (isset($fieldValues[$field->field_code]) && $fieldValues[$field->field_code] !== '') {
|
|
print '<tr><td>'.dol_escape_htmltag($field->field_label).'</td>';
|
|
$value = $fieldValues[$field->field_code];
|
|
print '<td>'.dol_escape_htmltag($value).'</td></tr>';
|
|
}
|
|
}
|
|
|
|
if ($anlage->note_private) {
|
|
print '<tr><td>'.$langs->trans('FieldNotes').'</td>';
|
|
print '<td>'.dol_htmlentitiesbr($anlage->note_private).'</td></tr>';
|
|
}
|
|
|
|
// Creation date
|
|
if ($anlage->date_creation) {
|
|
print '<tr><td>'.$langs->trans('DateCreation').'</td>';
|
|
print '<td>'.dol_print_date($anlage->date_creation, 'dayhour').'</td></tr>';
|
|
}
|
|
|
|
// Last modification date
|
|
if ($anlage->tms && $anlage->tms != $anlage->date_creation) {
|
|
print '<tr><td>'.$langs->trans('DateLastModification').'</td>';
|
|
print '<td>'.dol_print_date($anlage->tms, 'dayhour').'</td></tr>';
|
|
}
|
|
|
|
print '</table>';
|
|
|
|
// Files section
|
|
$anlagefile = new AnlageFile($db);
|
|
$files = $anlagefile->fetchAllByAnlage($anlageId);
|
|
|
|
print '<br><h4>'.$langs->trans('AttachedFiles').'</h4>';
|
|
|
|
if ($permissiontoadd) {
|
|
print '<form method="POST" enctype="multipart/form-data" action="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=uploadfile&anlage_id='.$anlageId.'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="file" name="userfile" accept="image/*,.pdf,.doc,.docx">';
|
|
print ' <button type="submit" class="button">'.$langs->trans('Upload').'</button>';
|
|
print '</form><br>';
|
|
}
|
|
|
|
if (!empty($files)) {
|
|
print '<div class="kundenkarte-files-grid">';
|
|
foreach ($files as $file) {
|
|
print '<div class="kundenkarte-file-item">';
|
|
print '<div class="kundenkarte-file-preview">';
|
|
if ($file->file_type == 'image') {
|
|
$thumbUrl = $file->getThumbUrl();
|
|
if ($thumbUrl) {
|
|
print '<img src="'.$thumbUrl.'" alt="">';
|
|
} else {
|
|
print '<img src="'.$file->getUrl().'" alt="" style="max-width:100%;max-height:100%;">';
|
|
}
|
|
} elseif ($file->file_type == 'pdf') {
|
|
// PDF preview using iframe - 50% smaller, no toolbar
|
|
print '<div class="kundenkarte-pdf-preview-wrapper">';
|
|
print '<iframe src="'.$file->getUrl().'#page=1&toolbar=0&navpanes=0&statusbar=0&view=FitH" class="kundenkarte-pdf-preview-frame"></iframe>';
|
|
print '</div>';
|
|
} else {
|
|
print '<i class="fa fa-file-o" style="font-size:48px;color:#999;"></i>';
|
|
}
|
|
print '</div>';
|
|
print '<div class="kundenkarte-file-info">';
|
|
print '<div class="kundenkarte-file-name" title="'.dol_escape_htmltag($file->filename).'">'.dol_escape_htmltag(dol_trunc($file->filename, 20)).'</div>';
|
|
print '<div class="kundenkarte-file-size">'.dol_print_size($file->filesize).'</div>';
|
|
print '<div class="kundenkarte-file-actions">';
|
|
print '<a href="'.$file->getUrl().'" target="_blank" class="kundenkarte-file-btn" title="'.$langs->trans('View').'"><i class="fa fa-eye"></i></a>';
|
|
if ($permissiontodelete) {
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=askdeletefile&anlage_id='.$anlageId.'&fileid='.$file->id.'" class="kundenkarte-file-btn kundenkarte-file-btn-delete" title="'.$langs->trans('Delete').'"><i class="fa fa-trash"></i></a>';
|
|
}
|
|
print '</div>';
|
|
print '</div>';
|
|
print '</div>';
|
|
}
|
|
print '</div>';
|
|
} else {
|
|
print '<p class="opacitymedium">'.$langs->trans('NoFiles').'</p>';
|
|
}
|
|
|
|
// Action buttons
|
|
print '<div class="tabsAction">';
|
|
if ($permissiontoadd) {
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=edit&anlage_id='.$anlageId.'">'.$langs->trans('Modify').'</a>';
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=copy&anlage_id='.$anlageId.'">'.$langs->trans('Copy').'</a>';
|
|
}
|
|
if ($permissiontodelete) {
|
|
print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=delete&anlage_id='.$anlageId.'">'.$langs->trans('Delete').'</a>';
|
|
}
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'">'.$langs->trans('Back').'</a>';
|
|
print '</div>';
|
|
|
|
} else {
|
|
// Create/Edit/Copy form
|
|
$isEdit = ($action == 'edit');
|
|
$isCopy = ($action == 'copy');
|
|
$formAction = $isEdit ? 'update' : 'add';
|
|
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="'.$formAction.'">';
|
|
if ($isEdit) {
|
|
print '<input type="hidden" name="anlage_id" value="'.$anlageId.'">';
|
|
}
|
|
if ($isCopy) {
|
|
print '<input type="hidden" name="copy_from" value="'.$anlageId.'">';
|
|
}
|
|
|
|
print '<table class="border centpercent" id="element_form_table">';
|
|
|
|
// Label
|
|
$labelValue = '';
|
|
if ($isEdit) {
|
|
$labelValue = $anlage->label;
|
|
} elseif ($isCopy) {
|
|
$labelValue = $anlage->label.' (Kopie)';
|
|
} else {
|
|
$labelValue = GETPOST('label');
|
|
}
|
|
print '<tr><td class="titlefield fieldrequired">'.$langs->trans('Label').'</td>';
|
|
print '<td><input type="text" name="label" class="flat minwidth300" value="'.dol_escape_htmltag($labelValue).'" required></td></tr>';
|
|
|
|
// Type
|
|
print '<tr><td class="fieldrequired">'.$langs->trans('Type').'</td>';
|
|
print '<td><select name="fk_anlage_type" class="flat minwidth200" id="select_type" required>';
|
|
print '<option value="">'.$langs->trans('SelectType').'</option>';
|
|
foreach ($types as $t) {
|
|
$selected = (($isEdit || $isCopy) && $anlage->fk_anlage_type == $t->id) ? ' selected' : '';
|
|
$icon = !empty($t->picto) ? $t->picto : 'fa-cube';
|
|
$color = !empty($t->color) ? $t->color : '#888';
|
|
print '<option value="'.$t->id.'"'.$selected.' data-icon="'.$icon.'" data-color="'.$color.'">'.dol_escape_htmltag($t->label).'</option>';
|
|
}
|
|
print '</select>';
|
|
if (empty($types)) {
|
|
print '<br><span class="warning">'.$langs->trans('NoTypesDefinedForSystem').'</span>';
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Parent (uses contact-specific tree)
|
|
$tree = $anlage->fetchTreeByContact($object->socid, $id, $systemId);
|
|
$selectedParent = ($isEdit || $isCopy) ? $anlage->fk_parent : $parentId;
|
|
$excludeId = $isEdit ? $anlageId : 0;
|
|
print '<tr><td>'.$langs->trans('SelectParent').'</td>';
|
|
print '<td><select name="fk_parent" class="flat minwidth200">';
|
|
print '<option value="0">('.$langs->trans('Root').')</option>';
|
|
printTreeOptions($tree, $selectedParent, $excludeId);
|
|
print '</select></td></tr>';
|
|
|
|
// Dynamic fields will be inserted here via JavaScript
|
|
print '<tbody id="dynamic_fields"></tbody>';
|
|
|
|
// Notes (always at the end)
|
|
print '<tr class="notes-row"><td>'.$langs->trans('FieldNotes').'</td>';
|
|
$noteValue = ($isEdit || $isCopy) ? $anlage->note_private : (isset($_POST['note_private']) ? $_POST['note_private'] : '');
|
|
print '<td><textarea name="note_private" class="flat minwidth300" rows="3">'.htmlspecialchars($noteValue, ENT_QUOTES, 'UTF-8').'</textarea></td></tr>';
|
|
|
|
print '</table>';
|
|
|
|
print '<div class="center" style="margin-top:20px;">';
|
|
print '<button type="submit" class="button button-save">'.$langs->trans('Save').'</button>';
|
|
print ' <a class="button button-cancel" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'">'.$langs->trans('Cancel').'</a>';
|
|
print '</div>';
|
|
|
|
print '</form>';
|
|
|
|
// JavaScript: Select2 mit Icons für Type und Parent
|
|
print '<script>
|
|
$(document).ready(function() {
|
|
// Select2 Template-Funktion mit Icons
|
|
function formatTypeOption(option) {
|
|
if (!option.id) return option.text;
|
|
var $opt = $(option.element);
|
|
var icon = $opt.data("icon");
|
|
var color = $opt.data("color") || "#666";
|
|
if (icon) {
|
|
return $("<span><i class=\"fa " + icon + "\" style=\"color:" + color + ";width:20px;margin-right:8px;text-align:center;\"></i>" + option.text + "</span>");
|
|
}
|
|
return option.text;
|
|
}
|
|
|
|
// Select2 für Type
|
|
var $typeSelect = $("#select_type");
|
|
if ($typeSelect.length) {
|
|
$typeSelect.select2({
|
|
templateResult: formatTypeOption,
|
|
templateSelection: formatTypeOption,
|
|
placeholder: "'.dol_escape_js($langs->trans('SelectType')).'",
|
|
allowClear: true,
|
|
width: "300px",
|
|
dropdownAutoWidth: true
|
|
});
|
|
}
|
|
|
|
// Select2 für übergeordnetes Element
|
|
var $parentSelect = $("select[name=\'fk_parent\']");
|
|
if ($parentSelect.length) {
|
|
$parentSelect.select2({
|
|
templateResult: formatTypeOption,
|
|
templateSelection: formatTypeOption,
|
|
placeholder: "'.dol_escape_js($langs->trans('SelectParent')).'",
|
|
allowClear: true,
|
|
width: "300px",
|
|
dropdownAutoWidth: true
|
|
});
|
|
}
|
|
});
|
|
</script>';
|
|
}
|
|
|
|
print '</div>';
|
|
|
|
} else {
|
|
// Tree view
|
|
if ($permissiontoadd) {
|
|
print '<div style="margin-bottom:15px;">';
|
|
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$id.'&system='.$systemId.'&action=create">';
|
|
print '<i class="fa fa-plus"></i> '.$langs->trans('AddElement');
|
|
print '</a>';
|
|
print '</div>';
|
|
}
|
|
|
|
// Load tree for this contact
|
|
$tree = $anlage->fetchTreeByContact($object->socid, $id, $systemId);
|
|
|
|
// Pre-load all type fields for tooltip and tree display
|
|
$typeFieldsMap = array();
|
|
$sql = "SELECT f.*, f.fk_anlage_type FROM ".MAIN_DB_PREFIX."kundenkarte_anlage_type_field f WHERE f.active = 1 ORDER BY f.position ASC";
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
while ($obj = $db->fetch_object($resql)) {
|
|
if (!isset($typeFieldsMap[$obj->fk_anlage_type])) {
|
|
$typeFieldsMap[$obj->fk_anlage_type] = array();
|
|
}
|
|
$typeFieldsMap[$obj->fk_anlage_type][] = $obj;
|
|
}
|
|
$db->free($resql);
|
|
}
|
|
|
|
if (!empty($tree)) {
|
|
print '<div class="kundenkarte-tree" data-system="'.$systemId.'">';
|
|
printTree($tree, $id, $systemId, $permissiontoadd, $permissiontodelete, $langs, 0, $typeFieldsMap);
|
|
print '</div>';
|
|
} else {
|
|
print '<div class="opacitymedium">'.$langs->trans('NoInstallations').'</div>';
|
|
}
|
|
}
|
|
}
|
|
|
|
print '</div>';
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
// Tooltip container
|
|
print '<div id="kundenkarte-tooltip" class="kundenkarte-tooltip"></div>';
|
|
|
|
llxFooter();
|
|
$db->close();
|
|
|
|
/**
|
|
* Print tree recursively
|
|
*/
|
|
function printTree($nodes, $contactid, $systemId, $canEdit, $canDelete, $langs, $level = 0, $typeFieldsMap = array())
|
|
{
|
|
foreach ($nodes as $node) {
|
|
$hasChildren = !empty($node->children);
|
|
|
|
// Build tooltip data for hover on icon (only dynamic fields now)
|
|
$tooltipData = array(
|
|
'label' => $node->label,
|
|
'type' => $node->type_label,
|
|
'note_html' => $node->note_private ? nl2br(htmlspecialchars($node->note_private, ENT_QUOTES, 'UTF-8')) : '',
|
|
'fields' => array()
|
|
);
|
|
|
|
// Collect dynamic fields for tooltip (show_in_hover) and tree label (show_in_tree)
|
|
$treeInfoParts = array();
|
|
if (!empty($typeFieldsMap[$node->fk_anlage_type])) {
|
|
$fieldValues = $node->getFieldValues();
|
|
foreach ($typeFieldsMap[$node->fk_anlage_type] as $fieldDef) {
|
|
// Handle header fields
|
|
if ($fieldDef->field_type === 'header') {
|
|
if ($fieldDef->show_in_hover) {
|
|
$tooltipData['fields'][$fieldDef->field_code] = array(
|
|
'label' => $fieldDef->field_label,
|
|
'value' => '',
|
|
'type' => 'header'
|
|
);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$value = isset($fieldValues[$fieldDef->field_code]) ? $fieldValues[$fieldDef->field_code] : '';
|
|
|
|
// Add to tooltip if show_in_hover
|
|
if ($fieldDef->show_in_hover && $value !== '') {
|
|
// Format date values
|
|
$displayValue = $value;
|
|
if ($fieldDef->field_type === 'date' && $value) {
|
|
$displayValue = dol_print_date(strtotime($value), 'day');
|
|
}
|
|
$tooltipData['fields'][$fieldDef->field_code] = array(
|
|
'label' => $fieldDef->field_label,
|
|
'value' => $displayValue,
|
|
'type' => $fieldDef->field_type
|
|
);
|
|
}
|
|
|
|
// Add to tree label info if show_in_tree
|
|
if ($fieldDef->show_in_tree && $value !== '') {
|
|
// Format date for tree info too
|
|
$displayVal = $value;
|
|
if ($fieldDef->field_type === 'date' && $value) {
|
|
$displayVal = dol_print_date(strtotime($value), 'day');
|
|
}
|
|
$treeInfoParts[] = array(
|
|
'label' => $fieldDef->field_label,
|
|
'value' => $displayVal,
|
|
'code' => $fieldDef->field_code,
|
|
'type' => $fieldDef->field_type
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
print '<div class="kundenkarte-tree-node" style="margin-left:'.($level * 20).'px;">';
|
|
print '<div class="kundenkarte-tree-item" data-anlage-id="'.$node->id.'">';
|
|
|
|
// Toggle
|
|
if ($hasChildren) {
|
|
print '<span class="kundenkarte-tree-toggle"><i class="fa fa-chevron-down"></i></span>';
|
|
} else {
|
|
print '<span class="kundenkarte-tree-toggle" style="visibility:hidden;"><i class="fa fa-chevron-down"></i></span>';
|
|
}
|
|
|
|
// Icon with tooltip data
|
|
$picto = $node->type_picto ? $node->type_picto : 'fa-cube';
|
|
print '<span class="kundenkarte-tree-icon kundenkarte-tooltip-trigger" data-tooltip="'.htmlspecialchars(json_encode($tooltipData), ENT_QUOTES, 'UTF-8').'" data-anlage-id="'.$node->id.'">'.kundenkarte_render_icon($picto).'</span>';
|
|
|
|
// Label with tree info badges + file indicators
|
|
$viewUrl = $_SERVER['PHP_SELF'].'?id='.$contactid.'&system='.$systemId.'&action=view&anlage_id='.$node->id;
|
|
print '<span class="kundenkarte-tree-label">'.dol_escape_htmltag($node->label).'</span>';
|
|
|
|
// Tree info display based on settings
|
|
$treeInfoDisplay = getDolGlobalString('KUNDENKARTE_TREE_INFO_DISPLAY', 'badge');
|
|
$badgeColor = getDolGlobalString('KUNDENKARTE_TREE_BADGE_COLOR', '#2a4a5e');
|
|
|
|
if (!empty($treeInfoParts) && $treeInfoDisplay !== 'none') {
|
|
if ($treeInfoDisplay === 'badge') {
|
|
// Display as badges with icons
|
|
print '<span class="kundenkarte-tree-badges">';
|
|
foreach ($treeInfoParts as $info) {
|
|
$badgeIcon = kundenkarte_get_field_icon($info['code'], $info['type']);
|
|
print '<span class="kundenkarte-tree-badge" title="'.dol_escape_htmltag($info['label']).'" style="background:linear-gradient(135deg, '.$badgeColor.' 0%, '.kundenkarte_adjust_color($badgeColor, -20).' 100%);">';
|
|
print '<i class="fa '.$badgeIcon.'"></i> '.dol_escape_htmltag($info['value']);
|
|
print '</span>';
|
|
}
|
|
print '</span>';
|
|
} else {
|
|
// Display in parentheses (old style)
|
|
print '<span class="kundenkarte-tree-label-info"> (';
|
|
$infoTexts = array();
|
|
foreach ($treeInfoParts as $info) {
|
|
$infoTexts[] = dol_escape_htmltag($info['label']).': '.dol_escape_htmltag($info['value']);
|
|
}
|
|
print implode(', ', $infoTexts);
|
|
print ')</span>';
|
|
}
|
|
}
|
|
|
|
// File indicators
|
|
if ($node->image_count > 0 || $node->doc_count > 0) {
|
|
$totalFiles = $node->image_count + $node->doc_count;
|
|
print ' <span class="kundenkarte-tree-files">';
|
|
// Combined file badge with file icon
|
|
print '<a href="'.$viewUrl.'#files" class="kundenkarte-tree-file-badge kundenkarte-tree-file-all" data-anlage-id="'.$node->id.'" title="'.$totalFiles.' '.($totalFiles == 1 ? 'Datei' : 'Dateien').'">';
|
|
print '<i class="fa fa-paperclip"></i> '.$totalFiles;
|
|
print '</a>';
|
|
print '</span>';
|
|
}
|
|
print '</span>';
|
|
|
|
// Type badge
|
|
if ($node->type_short || $node->type_label) {
|
|
$typeDisplay = $node->type_short ? $node->type_short : $node->type_label;
|
|
print '<span class="kundenkarte-tree-type badge badge-secondary">'.dol_escape_htmltag($typeDisplay).'</span>';
|
|
}
|
|
|
|
// Actions
|
|
print '<span class="kundenkarte-tree-actions">';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$contactid.'&system='.$systemId.'&action=view&anlage_id='.$node->id.'" title="'.$langs->trans('View').'"><i class="fa fa-eye"></i></a>';
|
|
if ($canEdit) {
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$contactid.'&system='.$systemId.'&action=create&parent_id='.$node->id.'" title="'.$langs->trans('AddChild').'"><i class="fa fa-plus"></i></a>';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$contactid.'&system='.$systemId.'&action=edit&anlage_id='.$node->id.'" title="'.$langs->trans('Edit').'"><i class="fa fa-edit"></i></a>';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$contactid.'&system='.$systemId.'&action=copy&anlage_id='.$node->id.'" title="'.$langs->trans('Copy').'"><i class="fa fa-copy"></i></a>';
|
|
}
|
|
if ($canDelete) {
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?id='.$contactid.'&system='.$systemId.'&action=delete&anlage_id='.$node->id.'" title="'.$langs->trans('Delete').'" class="deletelink"><i class="fa fa-trash"></i></a>';
|
|
}
|
|
print '</span>';
|
|
|
|
print '</div>';
|
|
|
|
// Children
|
|
if ($hasChildren) {
|
|
print '<div class="kundenkarte-tree-children">';
|
|
printTree($node->children, $contactid, $systemId, $canEdit, $canDelete, $langs, $level + 1, $typeFieldsMap);
|
|
print '</div>';
|
|
}
|
|
|
|
print '</div>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Print tree options for select
|
|
*/
|
|
function printTreeOptions($nodes, $selected = 0, $excludeId = 0, $prefix = '', $level = 0)
|
|
{
|
|
foreach ($nodes as $node) {
|
|
if ($node->id == $excludeId) continue;
|
|
|
|
$sel = ($node->id == $selected) ? ' selected' : '';
|
|
$icon = !empty($node->type_picto) ? $node->type_picto : 'fa-cube';
|
|
$color = !empty($node->type_color) ? $node->type_color : '#888';
|
|
print '<option value="'.$node->id.'"'.$sel.' data-icon="'.$icon.'" data-color="'.$color.'">'.$prefix.dol_escape_htmltag($node->label).'</option>';
|
|
|
|
if (!empty($node->children)) {
|
|
printTreeOptions($node->children, $selected, $excludeId, $prefix.'── ', $level + 1);
|
|
}
|
|
}
|
|
}
|