Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m0s
Implemented the output contract and readiness semantics for review packs. Also added spec 348. Includes changes to ChooseEnvironment, CustomerReviewWorkspace, GenerateReviewPackJob and related blade views. Added comprehensive tests.
191 lines
5.7 KiB
PHP
191 lines
5.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\Pages;
|
|
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\User;
|
|
use App\Models\UserTenantPreference;
|
|
use App\Services\Tenants\TenantOperabilityService;
|
|
use App\Support\ManagedEnvironmentLinks;
|
|
use App\Support\Tenants\TenantInteractionLane;
|
|
use App\Support\Tenants\TenantLifecyclePresentation;
|
|
use App\Support\Tenants\TenantOperabilityQuestion;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Filament\Facades\Filament;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Str;
|
|
|
|
class ChooseEnvironment extends Page
|
|
{
|
|
protected static string $layout = 'filament-panels::components.layout.simple';
|
|
|
|
protected static bool $shouldRegisterNavigation = false;
|
|
|
|
protected static bool $isDiscovered = false;
|
|
|
|
protected static ?string $slug = 'choose-environment';
|
|
|
|
protected string $view = 'filament.pages.choose-environment';
|
|
|
|
public string $search = '';
|
|
|
|
public function getTitle(): string
|
|
{
|
|
return __('localization.shell.choose_environment');
|
|
}
|
|
|
|
/**
|
|
* Disable the simple-layout topbar to prevent lazy-loaded
|
|
* DatabaseNotifications from triggering Livewire update 404s.
|
|
*/
|
|
protected function getLayoutData(): array
|
|
{
|
|
return [
|
|
'hasTopbar' => false,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, ManagedEnvironment>
|
|
*/
|
|
public function getTenants(): Collection
|
|
{
|
|
$user = auth()->user();
|
|
|
|
if (! $user instanceof User) {
|
|
return ManagedEnvironment::query()->whereRaw('1 = 0')->get();
|
|
}
|
|
|
|
$tenants = $user->getTenants(Filament::getCurrentOrDefaultPanel());
|
|
|
|
if ($tenants instanceof Collection) {
|
|
return app(TenantOperabilityService::class)->filterSelectable($tenants);
|
|
}
|
|
|
|
return app(TenantOperabilityService::class)->filterSelectable(collect($tenants));
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, ManagedEnvironment>
|
|
*/
|
|
public function getVisibleTenants(?Collection $tenants = null): Collection
|
|
{
|
|
$tenants ??= $this->getTenants();
|
|
$search = Str::of($this->search)->trim()->lower()->toString();
|
|
|
|
if ($search === '') {
|
|
return $tenants;
|
|
}
|
|
|
|
return $tenants
|
|
->filter(function (ManagedEnvironment $tenant) use ($search): bool {
|
|
$presentation = $this->tenantLifecyclePresentation($tenant);
|
|
|
|
return collect([
|
|
$tenant->name,
|
|
$tenant->domain,
|
|
$tenant->environment,
|
|
$presentation->label,
|
|
$presentation->shortDescription,
|
|
])
|
|
->filter(fn (mixed $value): bool => is_string($value) && $value !== '')
|
|
->contains(fn (string $value): bool => Str::contains(Str::lower($value), $search));
|
|
})
|
|
->values();
|
|
}
|
|
|
|
public function selectEnvironment(int $tenantId): void
|
|
{
|
|
$user = auth()->user();
|
|
|
|
if (! $user instanceof User) {
|
|
abort(403);
|
|
}
|
|
|
|
$workspaceContext = app(WorkspaceContext::class);
|
|
$workspaceId = $workspaceContext->currentWorkspaceId(request());
|
|
$tenant = null;
|
|
|
|
if ($workspaceId === null) {
|
|
$tenant = ManagedEnvironment::query()->whereKey($tenantId)->first();
|
|
|
|
if ($tenant instanceof ManagedEnvironment) {
|
|
$workspace = $tenant->workspace;
|
|
|
|
if ($workspace !== null && $user->canAccessTenant($tenant)) {
|
|
$workspaceContext->setCurrentWorkspace($workspace, $user, request());
|
|
$workspaceId = (int) $workspace->getKey();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($workspaceId === null) {
|
|
$this->redirect(route('filament.admin.pages.choose-workspace'));
|
|
|
|
return;
|
|
}
|
|
|
|
if (! $tenant instanceof ManagedEnvironment || (int) $tenant->workspace_id !== $workspaceId) {
|
|
$tenant = ManagedEnvironment::query()
|
|
->where('workspace_id', $workspaceId)
|
|
->whereKey($tenantId)
|
|
->first();
|
|
}
|
|
|
|
if (! $tenant instanceof ManagedEnvironment) {
|
|
abort(404);
|
|
}
|
|
|
|
if (! $user->canAccessTenant($tenant)) {
|
|
abort(404);
|
|
}
|
|
|
|
$outcome = app(TenantOperabilityService::class)->outcomeFor(
|
|
tenant: $tenant,
|
|
question: TenantOperabilityQuestion::SelectorEligibility,
|
|
actor: $user,
|
|
workspaceId: $workspaceId,
|
|
lane: TenantInteractionLane::StandardActiveOperating,
|
|
);
|
|
|
|
if (! $outcome->allowed) {
|
|
abort(404);
|
|
}
|
|
|
|
$this->persistLastTenant($user, $tenant);
|
|
|
|
if (! $workspaceContext->rememberEnvironmentContext($tenant, request())) {
|
|
abort(404);
|
|
}
|
|
|
|
$this->redirect(ManagedEnvironmentLinks::viewUrl($tenant));
|
|
}
|
|
|
|
public function tenantLifecyclePresentation(ManagedEnvironment $tenant): TenantLifecyclePresentation
|
|
{
|
|
return TenantLifecyclePresentation::fromTenant($tenant);
|
|
}
|
|
|
|
private function persistLastTenant(User $user, ManagedEnvironment $tenant): void
|
|
{
|
|
if (Schema::hasColumn('users', 'last_tenant_id')) {
|
|
$user->forceFill(['last_tenant_id' => $tenant->getKey()])->save();
|
|
|
|
return;
|
|
}
|
|
|
|
if (! Schema::hasTable('user_managed_environment_preferences')) {
|
|
return;
|
|
}
|
|
|
|
UserTenantPreference::query()->updateOrCreate(
|
|
['user_id' => $user->getKey(), 'managed_environment_id' => $tenant->getKey()],
|
|
['last_used_at' => now()]
|
|
);
|
|
}
|
|
}
|