better boarding flow

This commit is contained in:
Andras Bacsai 2023-08-30 14:46:51 +02:00
parent 248863cf16
commit 6f00740f67
13 changed files with 153 additions and 80 deletions

View File

@ -7,15 +7,19 @@
use App\Models\Project;
use App\Models\StandaloneDocker;
use App\Models\SwarmDocker;
use App\Traits\SaveFromRedirect;
use Illuminate\Support\Facades\Http;
use Livewire\Component;
use Route;
class GithubPrivateRepository extends Component
{
use SaveFromRedirect;
public $current_step = 'github_apps';
public $github_apps;
public GithubApp $github_app;
public $parameters;
public $currentRoute;
public $query;
public $type;
@ -36,14 +40,30 @@ class GithubPrivateRepository extends Component
public string|null $publish_directory = null;
protected int $page = 1;
// public function saveFromRedirect(string $route, ?Collection $parameters = null){
// session()->forget('from');
// if (!$parameters || $parameters->count() === 0) {
// $parameters = $this->parameters;
// }
// $parameters = collect($parameters) ?? collect([]);
// $queries = collect($this->query) ?? collect([]);
// $parameters = $parameters->merge($queries);
// session(['from'=> [
// 'back'=> $this->currentRoute,
// 'route' => $route,
// 'parameters' => $parameters
// ]]);
// return redirect()->route($route);
// }
public function mount()
{
$this->currentRoute = Route::currentRouteName();
$this->parameters = get_route_parameters();
$this->query = request()->query();
$this->repositories = $this->branches = collect();
$this->github_apps = GithubApp::private();
}
public function loadRepositories($github_app_id)
{
$this->repositories = collect();

View File

@ -39,7 +39,6 @@ public function mount()
{
if (is_cloud() && !isDev()) {
$this->webhook_endpoint = config('app.url');
ray($this->webhook_endpoint);
} else {
$this->webhook_endpoint = $this->ipv4;
$this->is_system_wide = $this->github_app->is_system_wide;

View File

@ -42,6 +42,9 @@ public function createGitHubApp()
'is_system_wide' => $this->is_system_wide,
'team_id' => currentTeam()->id,
]);
if (session('from')) {
session(['from' => session('from') + ['source_id' => $github_app->id]]);
}
redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
} catch (\Exception $e) {
return general_error_handler(err: $e, that: $this);

View File

@ -0,0 +1,25 @@
<?php
namespace App\Traits;
use Illuminate\Support\Collection;
trait SaveFromRedirect
{
public function saveFromRedirect(string $route, ?Collection $parameters = null)
{
session()->forget('from');
if (!$parameters || $parameters->count() === 0) {
$parameters = $this->parameters;
}
$parameters = collect($parameters) ?? collect([]);
$queries = collect($this->query) ?? collect([]);
$parameters = $parameters->merge($queries);
session(['from' => [
'back' => $this->currentRoute,
'route' => $route,
'parameters' => $parameters
]]);
return redirect()->route($route);
}
}

View File

@ -15,7 +15,7 @@ public function __construct(
public bool $disabled = false,
public bool $isModal = false,
public bool $noStyle = false,
public string|null $modalId = null,
public ?string $modalId = null,
public string $defaultClass = "btn btn-primary btn-sm font-normal text-white normal-case no-animation rounded border-none"
) {
if ($this->noStyle) {
@ -23,9 +23,6 @@ public function __construct(
}
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.forms.button');

View File

@ -7,6 +7,7 @@
use Illuminate\Database\QueryException;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Route;
@ -52,8 +53,7 @@ function showBoarding(): bool
}
function refreshSession(): void
{
$team = currentTeam();
session(['currentTeam' => $team]);
session(['currentTeam' => currentTeam()]);
}
function general_error_handler(Throwable | null $err = null, $that = null, $isJson = false, $customErrorMessage = null): mixed
{
@ -259,3 +259,4 @@ function send_user_an_email(MailMessage $mail, string $email): void
->html((string) $mail->render())
);
}

View File

@ -408,6 +408,12 @@ const magicActions = [{
name: 'Goto: Switch Teams',
icon: 'goto',
sequence: ['main', 'redirect']
},
{
id: 23,
name: 'Goto: Boarding process',
icon: 'goto',
sequence: ['main', 'redirect']
}
]
const initialState = {
@ -635,6 +641,9 @@ async function redirect() {
case 22:
targetUrl.pathname = `/team`
break;
case 23:
targetUrl.pathname = `/boarding`
break;
}
window.location.href = targetUrl;
}

View File

@ -5,8 +5,8 @@
<h1 class="text-5xl font-bold">Welcome to Coolify</h1>
<p class="py-6 text-xl text-center">Let me help you to set the basics.</p>
<div class="flex justify-center ">
<div class="justify-center box" wire:click="$set('currentState', 'select-server-type')">Get Started
</div>
<x-forms.button class="justify-center box" wire:click="$set('currentState', 'select-server-type')">Get Started
</x-forms.button>
</div>
@endif
</div>
@ -18,10 +18,10 @@
or on a <x-highlighted text="Remote Server" />?
</x-slot:question>
<x-slot:actions>
<div class="justify-center box" wire:click="setServerType('localhost')">Localhost
</div>
<div class="justify-center box" wire:click="setServerType('remote')">Remote Server
</div>
<x-forms.button class="justify-center box" wire:target="setServerType('localhost')" wire:click="setServerType('localhost')">Localhost
</x-forms.button>
<x-forms.button class="justify-center box" wire:target="setServerType('remote')" wire:click="setServerType('remote')">Remote Server
</x-forms.button>
</x-slot:actions>
<x-slot:explanation>
<p>Servers are the main building blocks, as they will host your applications, databases,
@ -42,10 +42,10 @@
Do you have your own SSH Private Key?
</x-slot:question>
<x-slot:actions>
<div class="justify-center box" wire:click="setPrivateKey('own')">Yes
</div>
<div class="justify-center box" wire:click="setPrivateKey('create')">No (create one for me)
</div>
<x-forms.button class="justify-center box" wire:target="setPrivateKey('own')" wire:click="setPrivateKey('own')">Yes
</x-forms.button>
<x-forms.button class="justify-center box" wire:target="setPrivateKey('create')" wire:click="setPrivateKey('create')">No (create one for me)
</x-forms.button>
@if (count($privateKeys) > 0)
<form wire:submit.prevent='selectExistingPrivateKey' class="flex flex-col w-full gap-4 pr-10">
<x-forms.select label="Existing SSH Keys" id='selectedExistingPrivateKey'>
@ -76,8 +76,8 @@
There are already servers available for your Team. Do you want to use one of them?
</x-slot:question>
<x-slot:actions>
<div class="justify-center box" wire:click="createNewServer">No (create a new one)
</div>
<x-forms.button class="justify-center box" wire:click="createNewServer">No (create one for me)
</x-forms.button>
<div>
<form wire:submit.prevent='selectExistingServer' class="flex flex-col w-full gap-4 lg:w-96">
<x-forms.select label="Existing servers" class="w-96" id='selectedExistingServer'>
@ -182,9 +182,9 @@
Could not find Docker Engine on your server. Do you want me to install it for you?
</x-slot:question>
<x-slot:actions>
<div class="justify-center box" wire:click="installDocker" onclick="installDocker.showModal()">
<x-forms.button class="justify-center box" wire:click="installDocker" onclick="installDocker.showModal()">
Let's do
it!</div>
it!</x-forms.button>
</x-slot:actions>
<x-slot:explanation>
<p>This will install the latest Docker Engine on your server, configure a few things to be able
@ -233,7 +233,7 @@
@endif
</x-slot:question>
<x-slot:actions>
<div class="justify-center box" wire:click="createNewProject">Let's create a new one!</div>
<x-forms.button class="justify-center box" wire:click="createNewProject">Let's create a new one!</x-forms.button>
<div>
@if (count($projects) > 0)
<form wire:submit.prevent='selectExistingProject'

View File

@ -1,10 +1,9 @@
<div>
<div class="flex items-end gap-2">
<h1>Create a new Application</h1>
<a href="{{ route('source.new') }}"><x-forms.button class="group-hover:text-white">
+ Add New GitHub App
</x-forms.button>
</a>
<x-forms.button wire:click="saveFromRedirect('source.new')" class="group-hover:text-white">
+ Add New GitHub App
</x-forms.button>
</div>
<div class="pb-4 ">Deploy any public or private git repositories through a GitHub App.</div>
@if ($github_apps->count() !== 0)
@ -25,7 +24,7 @@
{{ $ghapp->name }}
</div>
<div>{{ $ghapp->http_url }}</div>
<span wire:target="loadRepositories" wire:loading.delay
<span wire:target="loadRepositories({{ $ghapp->id }})" wire:loading.delay
class="loading loading-xs text-warning loading-spinner"></span>
</div>
</div>
@ -39,7 +38,7 @@ class="loading loading-xs text-warning loading-spinner"></span>
</div>
<div class="text-xs text-gray-400 group-hover:text-white">
{{ data_get($ghapp, 'html_url') }}</div>
<span wire:target="loadRepositories" wire:loading.delay
<span wire:target="loadRepositories({{ $ghapp->id }})" wire:loading.delay
class="">Loading...</span>
</div>
</div>

View File

@ -70,7 +70,6 @@
</div>
</div>
</div>
</div>
@endif
@if ($current_step === 'servers')
@ -79,7 +78,7 @@
<li class="step step-secondary">Select a Server</li>
<li class="step">Select a Destination</li>
</ul>
<div class="grid grid-cols-3 gap-2 text-left ">
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
@forelse($servers as $server)
<div class="box group"
wire:click="set_server({{ $server }})">
@ -108,7 +107,7 @@
<li class="step step-secondary">Select a Server</li>
<li class="step step-secondary">Select a Destination</li>
</ul>
<div class="grid grid-cols-3 gap-2 text-left ">
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row">
@foreach ($standaloneDockers as $standaloneDocker)
<div class="box group"
wire:click="set_destination('{{ $standaloneDocker->uuid }}')">

View File

@ -11,17 +11,15 @@
@if ($github_app->app_id)
<x-forms.button type="submit">Save</x-forms.button>
<a href="{{ get_installation_path($github_app) }}">
<x-forms.button>
@if ($github_app->installation_id)
@if (data_get($github_app, 'installation_id'))
<a href="{{ get_installation_path($github_app) }}">
<x-forms.button>
Update Repositories
<x-external-link />
@else
Install Repositories
<x-external-link />
@endif
</x-forms.button>
</a>
</x-forms.button>
</a>
@endif
@else
<x-forms.button disabled type="submit">Save</x-forms.button>
@endif
@ -30,8 +28,21 @@
</x-forms.button>
</div>
</div>
<div class="subtitle ">Your Private GitHub App for private repositories.</div>
@if ($github_app->app_id)
<div class="subtitle">Your Private GitHub App for private repositories.</div>
@if (data_get($github_app, 'app_id'))
@if (!data_get($github_app, 'installation_id'))
<div class="mb-10 rounded alert alert-warning">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<span>You must complete this step before you can use this source!</span>
</div>
<a class="justify-center box" href="{{ get_installation_path($github_app) }}">
Install Repositories on GitHub
</a>
@else
<div class="w-48">
<x-forms.checkbox label="System Wide?"
helper="If checked, this GitHub App will be available for everyone in this Coolify instance."
@ -64,17 +75,19 @@
<x-forms.input id="github_app.client_secret" label="Client Secret" type="password" />
<x-forms.input id="github_app.webhook_secret" label="Webhook Secret" type="password" />
</div>
@endif
@else
<div class="mb-10 rounded alert alert-warning">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 stroke-current shrink-0" fill="none"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<span>You must complete this step before you can use this source!</span>
</div>
<form class="flex gap-4">
<div class="flex items-end gap-2">
<h3>Register a GitHub App</h3>
<x-forms.button
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}')">
Register a
GitHub
Application
</x-forms.button>
</div>
<h2>Register a GitHub App</h2>
<div class="pt-1 pb-2 ">You need to register a GitHub App before using this source.</div>
<div class="pt-2 pb-10">
@if (!is_cloud() || isDev())
@ -90,8 +103,20 @@
@if ($fqdn)
<option value="{{ $fqdn }}">Use {{ $fqdn }}</option>
@endif
@if (config('app.url'))
<option value="{{ config('app.url') }}">Use {{ config('app.url') }}</option>
@endif
</x-forms.select>
<x-forms.button
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}')">
Register
</x-forms.button>
</div>
@else
<x-forms.button
x-on:click.prevent="createGithubApp('{{ $webhook_endpoint }}','{{ $preview_deployment_permissions }}')">
Register Now
</x-forms.button>
@endif
<div class="flex flex-col gap-2 pt-4">
<x-forms.checkbox disabled instantSave id="default_permissions" label="Default Permissions"
@ -102,29 +127,6 @@
</div>
</div>
</form>
<div class="flex gap-2">
<x-forms.input id="github_app.name" label="App Name" disabled />
<x-forms.input id="github_app.organization" label="Organization"
placeholder="If empty, personal user will be used" disabled />
</div>
<div class="flex gap-2">
<x-forms.input id="github_app.html_url" label="HTML Url" disabled />
<x-forms.input id="github_app.api_url" label="API Url" disabled />
</div>
<div class="flex gap-2">
@if ($github_app->html_url === 'https://github.com')
<x-forms.input id="github_app.custom_user" label="User" disabled />
<x-forms.input type="number" id="github_app.custom_port" label="Port" disabled />
@else
<x-forms.input id="github_app.custom_user" label="User" required />
<x-forms.input type="number" id="github_app.custom_port" label="Port" required />
@endif
</div>
@if (!is_cloud() || isDev())
<x-forms.checkbox
helper="If checked, this GitHub App will be available for everyone in this Coolify instance."
label="System Wide?" disabled id="is_system_wide" />
@endif
<script>
function createGithubApp(webhook_endpoint, preview_deployment_permissions) {
const {

View File

@ -7,23 +7,22 @@
<a class="flex gap-4 text-center hover:no-underline box group"
href="{{ route('source.github.show', ['github_app_uuid' => data_get($source, 'uuid')]) }}">
<x-git-icon class="text-white w-9 h-9" git="{{ $source->getMorphClass() }}" />
<div class="group-hover:text-white">
<div class="text-left group-hover:text-white">
<div>{{ $source->name }}</div>
@if (is_null($source->app_id))
<span class="text-error">Not registered</span>
<span class="text-error">Configuration is not finished</span>
@endif
</div>
</a>
@endif
@if ($source->getMorphClass() === 'App\Models\GitlabApp')
<a class="flex gap-4 text-center hover:no-underline box group"
href="{{ route('source.gitlab.show', ['gitlab_app_uuid' => data_get($source, 'uuid')]) }}">
<x-git-icon class="text-white w-9 h-9" git="{{ $source->getMorphClass() }}" />
<div class="group-hover:text-white">
<div class="text-left group-hover:text-white">
<div>{{ $source->name }}</div>
@if (is_null($source->app_id))
<span class="text-error">Not registered</span>
<span class="text-error">Configuration is not finished</span>
@endif
</div>
</a>

View File

@ -145,6 +145,26 @@
if ($settings->public_ipv6) {
$ipv6 = 'http://' . $settings->public_ipv6 . ':' . config('app.port');
}
if ($github_app->installation_id && session('from')) {
$source_id = data_get(session('from'), 'source_id');
if (!$source_id || $github_app->id !== $source_id) {
session()->forget('from');
} else {
$parameters = data_get(session('from'), 'parameters');
$back = data_get(session('from'), 'back');
$environment_name = data_get($parameters, 'environment_name');
$project_uuid = data_get($parameters, 'project_uuid');
$type = data_get($parameters, 'type');
$destination = data_get($parameters, 'destination');
session()->forget('from');
return redirect()->route($back, [
'environment_name' => $environment_name,
'project_uuid' => $project_uuid,
'type' => $type,
'destination' => $destination,
]);
}
}
return view('source.github.show', [
'github_app' => $github_app,
'name' => $name,