fix(portal): scope the per-instance maintenance badge to that instance's host
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/portal-design
parent
a321d963d7
commit
ac3b3a4e11
|
|
@ -18,10 +18,14 @@ class Cloud extends Component
|
|||
$locale = app()->getLocale();
|
||||
$growth = [180, 188, 195, 199, 204, 210, 214, 219, 223, 228, 231, 235];
|
||||
|
||||
// Maintenance affecting THIS customer's instance host — shown as a badge
|
||||
// on the instance itself, not just as a global banner.
|
||||
// Maintenance affecting THE DISPLAYED instance's host — scoped to that one
|
||||
// instance so a customer with several instances never sees another
|
||||
// instance's window on this card.
|
||||
$customer = $this->customer();
|
||||
$maintenance = $customer ? MaintenanceWindow::bannerFor($customer)->first() : null;
|
||||
$shown = $customer?->instances()
|
||||
->whereIn('status', ['active', 'provisioning', 'cancellation_scheduled'])
|
||||
->latest('id')->first();
|
||||
$maintenance = MaintenanceWindow::forInstance($shown)->first();
|
||||
|
||||
return view('livewire.cloud', [
|
||||
'instance' => [
|
||||
|
|
|
|||
|
|
@ -82,6 +82,26 @@ class MaintenanceWindow extends Model
|
|||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scheduled windows within the display horizon that affect ONE instance's
|
||||
* host — for a per-instance badge, so a customer with several instances
|
||||
* never sees another instance's maintenance on this card.
|
||||
*/
|
||||
public static function forInstance(?Instance $instance): Collection
|
||||
{
|
||||
if ($instance === null || $instance->host_id === null) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return self::query()
|
||||
->where('state', 'scheduled')
|
||||
->where('ends_at', '>=', now())
|
||||
->where('starts_at', '<=', now()->addHours(self::DISPLAY_HOURS))
|
||||
->whereHas('hosts', fn (Builder $q) => $q->whereKey($instance->host_id))
|
||||
->orderBy('starts_at')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scheduled windows to show a given customer right now: within the display
|
||||
* horizon (72 h before start until the end) and touching one of the
|
||||
|
|
|
|||
|
|
@ -65,6 +65,22 @@ it('emails a cancellation to customers who were announced', function () {
|
|||
Mail::assertQueued(\App\Mail\MaintenanceCancelledMail::class, 1);
|
||||
});
|
||||
|
||||
it('scopes the per-instance badge to that instance host', function () {
|
||||
$hostA = Host::factory()->active()->create();
|
||||
$hostB = Host::factory()->active()->create();
|
||||
$customer = Customer::factory()->create();
|
||||
$instA = Instance::factory()->create(['customer_id' => $customer->id, 'host_id' => $hostA->id, 'status' => 'active']);
|
||||
$instB = Instance::factory()->create(['customer_id' => $customer->id, 'host_id' => $hostB->id, 'status' => 'active']);
|
||||
|
||||
// A window on host A only.
|
||||
$window = MaintenanceWindow::factory()->scheduled()->create();
|
||||
$window->hosts()->attach($hostA->id);
|
||||
|
||||
expect(MaintenanceWindow::forInstance($instA))->toHaveCount(1)
|
||||
->and(MaintenanceWindow::forInstance($instB))->toHaveCount(0) // not another instance's window
|
||||
->and(MaintenanceWindow::bannerFor($customer))->toHaveCount(1); // customer-level banner still shows
|
||||
});
|
||||
|
||||
it('requires a host to publish', function () {
|
||||
Livewire::actingAs(operator('Owner'))->test(Maintenance::class)
|
||||
->set('title', 'X')
|
||||
|
|
|
|||
Loading…
Reference in New Issue