TenantAtlas/apps/platform/app/Livewire/BulkOperationProgress.php
ahmido 6fdd45fb02
Some checks failed
Main Confidence / confidence (push) Failing after 53s
feat: surface stale active operation runs (#269)
## Summary
- keep stale active operation runs visible in the tenant progress overlay and polling state
- align tenant and canonical operation surfaces around the shared stale-active presentation contract
- add Spec 233 artifacts and clean the promoted-candidate backlog entries

## Validation
- browser smoke: `/admin/t/18000000-0000-4000-8000-000000000180` -> stale dashboard CTA -> `/admin/operations?tenant_id=7&activeTab=active_stale_attention&problemClass=active_stale_attention` -> `/admin/operations/15`
- verified healthy vs likely-stale tenant cards, canonical stale list row, and canonical run detail consistency

## Notes
- local smoke fixture seeded with one fresh and one stale running `baseline_compare` operation for browser validation
- Pest suite was not re-run in this session before opening this PR

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #269
2026-04-23 15:10:06 +00:00

105 lines
2.6 KiB
PHP

<?php
namespace App\Livewire;
use App\Models\OperationRun;
use App\Models\Tenant;
use App\Support\OpsUx\ActiveRuns;
use App\Support\OpsUx\OpsUxBrowserEvents;
use Filament\Facades\Filament;
use Illuminate\Support\Collection;
use Livewire\Attributes\Computed;
use Livewire\Attributes\On;
use Livewire\Component;
class BulkOperationProgress extends Component
{
/**
* @var Collection<int, OperationRun>
*/
public Collection $runs;
public int $overflowCount = 0;
public bool $disabled = false;
public bool $hasActiveRuns = false;
public ?int $tenantId = null;
public function mount(): void
{
$this->runs = collect();
$tenant = Filament::getTenant();
$this->tenantId = $tenant instanceof Tenant ? (int) $tenant->id : null;
$this->refreshRuns();
}
#[On(OpsUxBrowserEvents::RunEnqueued)]
public function onRunEnqueued(?int $tenantId = null): void
{
if ($tenantId !== null) {
$this->tenantId = $tenantId;
}
$this->refreshRuns();
}
#[Computed]
public function activeRuns()
{
return $this->runs;
}
public function refreshRuns(): void
{
$tenantId = $this->tenantId;
// Best-effort: if we're mounted on a tenant page, capture it once.
if ($tenantId === null) {
$tenant = Filament::getTenant();
$tenantId = $tenant instanceof Tenant ? (int) $tenant->id : null;
$this->tenantId = $tenantId;
}
if ($tenantId === null) {
$this->disabled = true;
$this->runs = collect();
$this->overflowCount = 0;
$this->hasActiveRuns = false;
return;
}
if (! auth()->user()?->can('viewAny', OperationRun::class)) {
$this->disabled = true;
$this->runs = collect();
$this->overflowCount = 0;
$this->hasActiveRuns = false;
return;
}
$this->disabled = false;
$query = OperationRun::query()
->where('tenant_id', $tenantId)
->active()
->orderByDesc('created_at');
$activeCount = (clone $query)->count();
$this->runs = (clone $query)->limit(6)->get();
$this->overflowCount = max(0, $activeCount - 5);
$this->hasActiveRuns = ActiveRuns::existForTenantId($tenantId);
}
public function render(): \Illuminate\Contracts\View\View
{
return view('livewire.bulk-operation-progress', [
'tenant' => Filament::getTenant(),
]);
}
}