better boarding flow
This commit is contained in:
parent
248863cf16
commit
6f00740f67
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
25
app/Traits/SaveFromRedirect.php
Normal file
25
app/Traits/SaveFromRedirect.php
Normal 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);
|
||||
}
|
||||
}
|
@ -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');
|
||||
|
@ -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())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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'
|
||||
|
@ -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>
|
||||
|
@ -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 }}')">
|
||||
|
@ -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 {
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user