Files
breadcrumb-the-shire/modules/helpdesk/templates/aside-helpdesk-panel.phtml
fs ef4473de64 feat(helpdesk): add Software Products page with BC contract type sync
Add a new Software-Produkte feature to the helpdesk module that syncs
contract types (Create_SaaS_License=true) from BC OData into a local
database table with a nightly scheduler job, providing a Grid.js list
page and detail/edit page for managing custom product names.

- DB migration 003: helpdesk_software_products table (code UNIQUE key)
- BcODataGateway: FS_Contract_Types entity with SaaS filter + fallback
- SoftwareProductRepository: upsert, listPaged, softDelete, updateName
- SoftwareProductSyncService: fetch → upsert → soft-delete lifecycle
- SoftwareProductSyncJobHandler: daily at 02:00 via scheduler platform
- SoftwareProductService: web UI business logic with validation
- Permission: helpdesk.software-products.manage (nav-gated)
- List page: Grid.js with Code, BC Description, Name, Status columns
- Detail page: Code/BC Description read-only, Name editable, PRG pattern
- i18n: de + en translation keys

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:16:21 +02:00

115 lines
4.2 KiB
PHTML

<?php
$layoutNav = is_array($layoutNav ?? null) ? $layoutNav : [];
$helpdeskNav = is_array($layoutNav['helpdesk.nav'] ?? null) ? $layoutNav['helpdesk.nav'] : [];
$canManageSettings = !empty($helpdeskNav['can_manage_settings']);
$canViewTeam = !empty($helpdeskNav['can_view_team']);
$canViewRiskRadar = !empty($helpdeskNav['can_view_risk_radar']);
$canManageSoftwareProducts = !empty($helpdeskNav['can_manage_software_products']);
$settingsActive = navActive('helpdesk/settings', true);
$teamActive = navActive('helpdesk/team', true);
$riskRadarActive = navActive('helpdesk/risk-radar', true);
$domainsActive = navActive('helpdesk/domains', true);
$softwareProductsActive = navActive('helpdesk/software-products', true);
$customersActive = navActive('helpdesk', true);
if ($settingsActive['isActive'] || $teamActive['isActive'] || $riskRadarActive['isActive'] || $domainsActive['isActive'] || $softwareProductsActive['isActive']) {
$customersActive = ['class' => '', 'aria' => '', 'isActive' => false];
}
$helpdeskNavGroups = [
[
'key' => 'helpdesk-lookup',
'label' => t('Lookup'),
'icon' => 'bi-search',
'items' => [
[
'label' => t('Customers'),
'path' => 'helpdesk',
'active' => $customersActive,
'visible' => true,
],
[
'label' => t('Domains'),
'path' => 'helpdesk/domains',
'active' => $domainsActive,
'visible' => true,
],
],
],
[
'key' => 'helpdesk-monitoring',
'label' => t('Monitoring'),
'icon' => 'bi-bar-chart-line',
'items' => [
[
'label' => t('Team workload'),
'path' => 'helpdesk/team',
'active' => $teamActive,
'visible' => $canViewTeam,
],
[
'label' => t('Risk radar'),
'path' => 'helpdesk/risk-radar',
'active' => $riskRadarActive,
'visible' => $canViewRiskRadar,
],
],
],
[
'key' => 'helpdesk-administration',
'label' => t('Administration'),
'icon' => 'bi-sliders',
'items' => [
[
'label' => t('Software products'),
'path' => 'helpdesk/software-products',
'active' => $softwareProductsActive,
'visible' => $canManageSoftwareProducts,
],
[
'label' => t('Settings'),
'path' => 'helpdesk/settings',
'active' => $settingsActive,
'visible' => $canManageSettings,
],
],
],
];
?>
<ul>
<?php foreach ($helpdeskNavGroups as $group):
$visibleItems = array_values(array_filter($group['items'], static fn (array $item): bool => !empty($item['visible'])));
if (!$visibleItems) {
continue;
}
$groupIsActive = false;
foreach ($visibleItems as $item) {
if (!empty(($item['active'] ?? [])['isActive'])) {
$groupIsActive = true;
break;
}
}
?>
<li class="app-sidebar-group app-sidebar-admin-group">
<details data-details-key="<?php e($group['key']); ?>"<?php if ($groupIsActive): ?> open<?php endif; ?>>
<summary>
<i class="bi <?php e($group['icon']); ?>"></i>
<span><?php e($group['label']); ?></span>
</summary>
<ul>
<?php foreach ($visibleItems as $item):
$active = $item['active'] ?? ['class' => '', 'aria' => ''];
?>
<li>
<a href="<?php e(lurl($item['path'])); ?>" class="<?php e($active['class'] ?? ''); ?>" <?php echo $active['aria'] ?? ''; // raw-html-ok: pre-built ARIA attribute from navActive() ?>>
<?php e($item['label']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</details>
</li>
<?php endforeach; ?>
</ul>