## Summary - add a shared cross-resource navigation layer with canonical navigation context and related-context rendering - wire findings, policy versions, baseline snapshots, backup sets, and canonical operations surfaces into consistent drill-down flows - extend focused Pest coverage for canonical operations links, related navigation, and tenant-context preservation ## Testing - focused Pest coverage for spec 131 was added and the task list marks the implementation verification and Pint steps as completed ## Follow-up - manual QA checklist item `T036` in `specs/131-cross-resource-navigation/tasks.md` is still open and should be completed during review Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #160
109 lines
3.0 KiB
PHP
109 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support\Navigation;
|
|
|
|
final readonly class RelatedContextEntry
|
|
{
|
|
public function __construct(
|
|
public string $key,
|
|
public string $label,
|
|
public string $value,
|
|
public ?string $secondaryValue,
|
|
public ?string $targetUrl,
|
|
public string $targetKind,
|
|
public string $availability,
|
|
public ?string $unavailableReason,
|
|
public ?string $contextBadge,
|
|
public int $priority,
|
|
public string $actionLabel,
|
|
) {}
|
|
|
|
public static function available(
|
|
string $key,
|
|
string $label,
|
|
string $value,
|
|
?string $secondaryValue,
|
|
string $targetUrl,
|
|
string $targetKind,
|
|
int $priority,
|
|
string $actionLabel,
|
|
?string $contextBadge = null,
|
|
): self {
|
|
return new self(
|
|
key: $key,
|
|
label: $label,
|
|
value: $value,
|
|
secondaryValue: $secondaryValue,
|
|
targetUrl: $targetUrl,
|
|
targetKind: $targetKind,
|
|
availability: 'available',
|
|
unavailableReason: null,
|
|
contextBadge: $contextBadge,
|
|
priority: $priority,
|
|
actionLabel: $actionLabel,
|
|
);
|
|
}
|
|
|
|
public static function unavailable(
|
|
string $key,
|
|
string $label,
|
|
UnavailableRelationState $state,
|
|
string $targetKind,
|
|
int $priority,
|
|
string $actionLabel,
|
|
): self {
|
|
return new self(
|
|
key: $key,
|
|
label: $label,
|
|
value: 'Unavailable',
|
|
secondaryValue: $state->showReference ? $state->referenceValue : null,
|
|
targetUrl: null,
|
|
targetKind: $targetKind,
|
|
availability: $state->reason,
|
|
unavailableReason: $state->message,
|
|
contextBadge: null,
|
|
priority: $priority,
|
|
actionLabel: $actionLabel,
|
|
);
|
|
}
|
|
|
|
public function isAvailable(): bool
|
|
{
|
|
return $this->availability === 'available' && is_string($this->targetUrl) && $this->targetUrl !== '';
|
|
}
|
|
|
|
/**
|
|
* @return array{
|
|
* key: string,
|
|
* label: string,
|
|
* value: string,
|
|
* secondaryValue: ?string,
|
|
* targetUrl: ?string,
|
|
* targetKind: string,
|
|
* availability: string,
|
|
* unavailableReason: ?string,
|
|
* contextBadge: ?string,
|
|
* priority: int,
|
|
* actionLabel: string
|
|
* }
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'key' => $this->key,
|
|
'label' => $this->label,
|
|
'value' => $this->value,
|
|
'secondaryValue' => $this->secondaryValue,
|
|
'targetUrl' => $this->targetUrl,
|
|
'targetKind' => $this->targetKind,
|
|
'availability' => $this->availability,
|
|
'unavailableReason' => $this->unavailableReason,
|
|
'contextBadge' => $this->contextBadge,
|
|
'priority' => $this->priority,
|
|
'actionLabel' => $this->actionLabel,
|
|
];
|
|
}
|
|
}
|