magic search bar

This commit is contained in:
Andras Bacsai 2023-05-11 15:20:02 +02:00
parent 8e1c6d2bd2
commit 70d032ff23
17 changed files with 686 additions and 481 deletions

View File

@ -19,7 +19,7 @@ public function environments()
return view('project.environments', ['project' => $project]); return view('project.environments', ['project' => $project]);
} }
public function resources_new() public function new()
{ {
$project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); $project = session('currentTeam')->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) { if (!$project) {
@ -29,7 +29,12 @@ public function resources_new()
if (!$environment) { if (!$environment) {
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
return view('project.new', ['project' => $project, 'environment' => $environment, 'type' => 'resource']);
$type = request()->query('type');
return view('project.new', [
'type' => $type
]);
} }
public function resources() public function resources()
{ {

View File

@ -6,6 +6,8 @@
use App\Models\GithubApp; use App\Models\GithubApp;
use App\Models\Project; use App\Models\Project;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker;
use App\Models\SwarmDocker;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@ -16,6 +18,7 @@ class GithubPrivateRepository extends Component
public $github_apps; public $github_apps;
public GithubApp $github_app; public GithubApp $github_app;
public $parameters; public $parameters;
public $query;
public $type; public $type;
public int $selected_repository_id; public int $selected_repository_id;
@ -24,16 +27,10 @@ class GithubPrivateRepository extends Component
public string $selected_branch_name = 'main'; public string $selected_branch_name = 'main';
public int $selected_server_id;
public int $selected_destination_id;
public string $selected_destination_class;
public string $token; public string $token;
protected int $page = 1; protected int $page = 1;
public $servers;
public $destinations;
public $repositories; public $repositories;
public int $total_repositories_count = 0; public int $total_repositories_count = 0;
@ -42,7 +39,6 @@ class GithubPrivateRepository extends Component
protected function loadRepositoryByPage() protected function loadRepositoryByPage()
{ {
Log::info('Loading page ' . $this->page);
$response = Http::withToken($this->token)->get("{$this->github_app->api_url}/installation/repositories?per_page=100&page={$this->page}"); $response = Http::withToken($this->token)->get("{$this->github_app->api_url}/installation/repositories?per_page=100&page={$this->page}");
$json = $response->json(); $json = $response->json();
if ($response->status() !== 200) { if ($response->status() !== 200) {
@ -96,55 +92,37 @@ public function loadBranches()
} }
} }
} }
public function loadServers()
{
try {
$this->servers = Server::validated();
$this->selected_server_id = $this->servers[0]['id'];
} catch (\Exception $e) {
return generalErrorHandler($e);
}
}
public function loadDestinations()
{
try {
$server = $this->servers->where('id', $this->selected_server_id)->first();
if ($server->standaloneDockers->count() === 0 && $server->swarmDockers->count() === 0) {
$this->destinations = 0;
}
$this->destinations = $server->standaloneDockers->merge($server->swarmDockers);
$this->selected_destination_id = $this->destinations[0]['id'];
$this->selected_destination_class = $this->destinations[0]->getMorphClass();
} catch (\Exception $e) {
return generalErrorHandler($e);
}
}
public function submit() public function submit()
{ {
try { try {
if ($this->type === 'project') { $destination_uuid = $this->query['destination'];
$project = Project::create([ $destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
'name' => generateRandomName(), if (!$destination) {
'team_id' => session('currentTeam')->id $destination = SwarmDocker::where('uuid', $destination_uuid)->first();
]);
$environment = $project->load(['environments'])->environments->first();
} else {
$project = Project::where('uuid', $this->parameters['project_uuid'])->first();
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
} }
if (!$destination) {
throw new \Exception('Destination not found. What?!');
}
$destination_class = $destination->getMorphClass();
$project = Project::where('uuid', $this->parameters['project_uuid'])->first();
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
$application = Application::create([ $application = Application::create([
'name' => generateRandomName() . "-{$this->selected_repository_owner}/{$this->selected_repository_repo}:{$this->selected_branch_name}", 'name' => generateRandomName() . "-{$this->selected_repository_owner}/{$this->selected_repository_repo}:{$this->selected_branch_name}",
'project_id' => $this->selected_repository_id, 'repository_project_id' => $this->selected_repository_id,
'git_repository' => "{$this->selected_repository_owner}/{$this->selected_repository_repo}", 'git_repository' => "{$this->selected_repository_owner}/{$this->selected_repository_repo}",
'git_branch' => $this->selected_branch_name, 'git_branch' => $this->selected_branch_name,
'build_pack' => 'nixpacks', 'build_pack' => 'nixpacks',
'ports_exposes' => '3000', 'ports_exposes' => '3000',
'environment_id' => $environment->id, 'environment_id' => $environment->id,
'destination_id' => $this->selected_destination_id, 'destination_id' => $destination->id,
'destination_type' => $this->selected_destination_class, 'destination_type' => $destination_class,
'source_id' => $this->github_app->id, 'source_id' => $this->github_app->id,
'source_type' => GithubApp::class, 'source_type' => GithubApp::class,
]); ]);
redirect()->route('project.application.configuration', [ redirect()->route('project.application.configuration', [
'application_uuid' => $application->uuid, 'application_uuid' => $application->uuid,
'project_uuid' => $project->uuid, 'project_uuid' => $project->uuid,
@ -157,7 +135,8 @@ public function submit()
public function mount() public function mount()
{ {
$this->parameters = getParameters(); $this->parameters = getParameters();
$this->repositories = $this->branches = $this->servers = $this->destinations = collect(); $this->query = request()->query();
$this->repositories = $this->branches = collect();
$this->github_apps = GithubApp::private(); $this->github_apps = GithubApp::private();
} }
} }

View File

@ -13,16 +13,11 @@
class GithubPrivateRepositoryDeployKey extends Component class GithubPrivateRepositoryDeployKey extends Component
{ {
public $parameters; public $parameters;
public $query;
public $private_keys; public $private_keys;
public int $private_key_id; public int $private_key_id;
public string $repository_url; public string $repository_url;
public $servers;
public $standalone_docker;
public $swarm_docker;
public $chosenServer;
public $chosenDestination;
public int $port = 3000; public int $port = 3000;
public string $type; public string $type;
@ -40,20 +35,8 @@ public function mount()
$this->repository_url = 'https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify'; $this->repository_url = 'https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify';
} }
$this->parameters = getParameters(); $this->parameters = getParameters();
$this->query = request()->query();
$this->private_keys = PrivateKey::where('team_id', session('currentTeam')->id)->get(); $this->private_keys = PrivateKey::where('team_id', session('currentTeam')->id)->get();
$this->servers = session('currentTeam')->load(['servers'])->servers;
}
public function chooseServer($server)
{
$this->chosenServer = $server;
$this->standalone_docker = StandaloneDocker::where('server_id', $server['id'])->get();
$this->swarm_docker = SwarmDocker::where('server_id', $server['id'])->get();
}
public function setDestination($destination_uuid, $destination_type)
{
$class = "App\Models\\{$destination_type}";
$instance = new $class;
$this->chosenDestination = $instance::where('uuid', $destination_uuid)->first();
} }
public function instantSave() public function instantSave()
{ {
@ -71,43 +54,49 @@ public function setPrivateKey($private_key_id)
} }
public function submit() public function submit()
{ {
$this->validate(); try {
$url = Url::fromString($this->repository_url); $this->validate();
$git_host = $url->getHost(); $url = Url::fromString($this->repository_url);
$git_repository = $url->getSegment(1) . '/' . $url->getSegment(2); $git_host = $url->getHost();
$git_branch = $url->getSegment(4) ?? 'main'; $git_repository = $url->getSegment(1) . '/' . $url->getSegment(2);
$git_branch = $url->getSegment(4) ?? 'main';
if ($this->type === 'project') { $destination_uuid = $this->query['destination'];
$project = Project::create([ $destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
'name' => generateRandomName(), if (!$destination) {
'team_id' => session('currentTeam')->id, $destination = SwarmDocker::where('uuid', $destination_uuid)->first();
}
if (!$destination) {
throw new \Exception('Destination not found. What?!');
}
$destination_class = $destination->getMorphClass();
$project = Project::where('uuid', $this->parameters['project_uuid'])->first();
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
$application_init = [
'name' => generateRandomName() . "-{$git_repository}:{$git_branch}",
'git_repository' => $git_repository,
'git_branch' => $git_branch,
'git_full_url' => "git@$git_host:$git_repository.git",
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
'destination_id' => $destination->id,
'destination_type' => $destination_class,
'private_key_id' => $this->private_key_id,
];
$application = Application::create($application_init);
$application->settings->is_static = $this->is_static;
$application->settings->save();
return redirect()->route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_name' => $environment->name,
'application_uuid' => $application->uuid,
]); ]);
$environment = $project->environments->first(); } catch (\Exception $e) {
} else { return generalErrorHandler($e, $this);
$project = Project::where('uuid', $this->parameters['project_uuid'])->firstOrFail();
$environment = $project->environments->where('name', $this->parameters['environment_name'])->firstOrFail();
} }
$application_init = [
'name' => generateRandomName() . "-{$git_repository}:{$git_branch}",
'git_repository' => $git_repository,
'git_branch' => $git_branch,
'git_full_url' => "git@$git_host:$git_repository.git",
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
'destination_id' => $this->chosenDestination->id,
'destination_type' => $this->chosenDestination->getMorphClass(),
'private_key_id' => $this->private_key_id,
];
$application = Application::create($application_init);
$application->settings->is_static = $this->is_static;
$application->settings->save();
return redirect()->route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_name' => $environment->name,
'application_uuid' => $application->uuid,
]);
} }
} }

View File

@ -8,7 +8,6 @@
use App\Models\Project; use App\Models\Project;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use App\Models\SwarmDocker; use App\Models\SwarmDocker;
use Illuminate\Support\Facades\Route;
use Livewire\Component; use Livewire\Component;
use Spatie\Url\Url; use Spatie\Url\Url;
@ -18,12 +17,8 @@ class PublicGitRepository extends Component
public int $port = 3000; public int $port = 3000;
public string $type; public string $type;
public $parameters; public $parameters;
public $query;
public $servers;
public $standalone_docker;
public $swarm_docker;
public $chosenServer;
public $chosenDestination;
public $github_apps; public $github_apps;
public $gitlab_apps; public $gitlab_apps;
@ -43,19 +38,7 @@ public function mount()
$this->port = 3000; $this->port = 3000;
} }
$this->parameters = getParameters(); $this->parameters = getParameters();
$this->servers = session('currentTeam')->load(['servers'])->servers; $this->query = request()->query();
}
public function chooseServer($server)
{
$this->chosenServer = $server;
$this->standalone_docker = StandaloneDocker::where('server_id', $server['id'])->get();
$this->swarm_docker = SwarmDocker::where('server_id', $server['id'])->get();
}
public function setDestination($destination_uuid, $destination_type)
{
$class = "App\Models\\{$destination_type}";
$instance = new $class;
$this->chosenDestination = $instance::where('uuid', $destination_uuid)->first();
} }
public function instantSave() public function instantSave()
@ -72,49 +55,58 @@ public function instantSave()
public function submit() public function submit()
{ {
$this->validate(); try {
$url = Url::fromString($this->repository_url); $this->validate();
$git_host = $url->getHost();
$git_repository = $url->getSegment(1) . '/' . $url->getSegment(2);
$git_branch = $url->getSegment(4) ?? 'main';
if ($this->type === 'project') { $url = Url::fromString($this->repository_url);
$project = Project::create([ $git_host = $url->getHost();
'name' => generateRandomName(), $git_repository = $url->getSegment(1) . '/' . $url->getSegment(2);
'team_id' => session('currentTeam')->id, $git_branch = $url->getSegment(4) ?? 'main';
$destination_uuid = $this->query['destination'];
$destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
if (!$destination) {
$destination = SwarmDocker::where('uuid', $destination_uuid)->first();
}
if (!$destination) {
throw new \Exception('Destination not found. What?!');
}
$destination_class = $destination->getMorphClass();
$project = Project::where('uuid', $this->parameters['project_uuid'])->first();
$environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first();
$application_init = [
'name' => generateRandomName() . "-{$git_repository}:{$git_branch}",
'git_repository' => $git_repository,
'git_branch' => $git_branch,
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
'destination_id' => $destination->id,
'destination_type' => $destination_class,
];
if ($git_host == 'github.com') {
$application_init['source_id'] = GithubApp::where('name', 'Public GitHub')->first()->id;
$application_init['source_type'] = GithubApp::class;
} elseif ($git_host == 'gitlab.com') {
$application_init['source_id'] = GitlabApp::where('name', 'Public GitLab')->first()->id;
$application_init['source_type'] = GitlabApp::class;
} elseif ($git_host == 'bitbucket.org') {
}
$application = Application::create($application_init);
$application->settings->is_static = $this->is_static;
$application->settings->save();
return redirect()->route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_name' => $environment->name,
'application_uuid' => $application->uuid,
]); ]);
$environment = $project->environments->first(); } catch (\Exception $e) {
} else { return generalErrorHandler($e);
$project = Project::where('uuid', $this->parameters['project_uuid'])->firstOrFail();
$environment = $project->environments->where('name', $this->parameters['environment_name'])->firstOrFail();
} }
$application_init = [
'name' => generateRandomName() . "-{$git_repository}:{$git_branch}",
'git_repository' => $git_repository,
'git_branch' => $git_branch,
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
'destination_id' => $this->chosenDestination->id,
'destination_type' => $this->chosenDestination->getMorphClass(),
];
if ($git_host == 'github.com') {
$application_init['source_id'] = GithubApp::where('name', 'Public GitHub')->first()->id;
$application_init['source_type'] = GithubApp::class;
} elseif ($git_host == 'gitlab.com') {
$application_init['source_id'] = GitlabApp::where('name', 'Public GitLab')->first()->id;
$application_init['source_type'] = GitlabApp::class;
} elseif ($git_host == 'bitbucket.org') {
}
$application = Application::create($application_init);
$application->settings->is_static = $this->is_static;
$application->settings->save();
return redirect()->route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_name' => $environment->name,
'application_uuid' => $application->uuid,
]);
} }
} }

View File

@ -28,6 +28,7 @@ protected static function booted()
'extra_attributes' => SchemalessAttributes::class, 'extra_attributes' => SchemalessAttributes::class,
]; ];
public function standaloneDockers() public function standaloneDockers()
{ {
return $this->hasMany(StandaloneDocker::class); return $this->hasMany(StandaloneDocker::class);
@ -57,4 +58,11 @@ static public function validated()
{ {
return Server::where('team_id', session('currentTeam')->id)->whereRelation('settings', 'is_validated', true)->get(); return Server::where('team_id', session('currentTeam')->id)->whereRelation('settings', 'is_validated', true)->get();
} }
static public function destinations($server_uuid)
{
$server = Server::where('team_id', session('currentTeam')->id)->where('uuid', $server_uuid)->firstOrFail();
$standaloneDocker = collect($server->standaloneDockers->all());
$swarmDocker = collect($server->swarmDockers->all());
return $standaloneDocker->concat($swarmDocker);
}
} }

View File

@ -17,22 +17,31 @@
if (!function_exists('generalErrorHandler')) { if (!function_exists('generalErrorHandler')) {
function generalErrorHandler(\Throwable $e, $that = null) function generalErrorHandler(\Throwable $e, $that = null, $isJson = false)
{ {
if ($that) { try {
if ($e instanceof QueryException) { if ($e instanceof QueryException) {
if ($e->errorInfo[0] === '23505') { if ($e->errorInfo[0] === '23505') {
$that->emit('error', 'Duplicate entry found.'); throw new \Exception('Duplicate entry found.', '23505');
} else if (count($e->errorInfo) === 4) { } else if (count($e->errorInfo) === 4) {
$that->emit('error', $e->errorInfo[3]); throw new \Exception($e->errorInfo[3]);
} else { } else {
$that->emit('error', $e->errorInfo[2]); throw new \Exception($e->errorInfo[2]);
} }
} else { } else {
$that->emit('error', $e->getMessage()); throw new \Exception($e->getMessage());
}
} catch (\Throwable $error) {
if ($that) {
$that->emit('error', $error);
} elseif ($isJson) {
return response()->json([
'code' => $error->getCode(),
'error' => $error->getMessage(),
]);
} else {
dump('Duplicate entry found.');
} }
} else {
dump($e);
} }
} }
} }

178
composer.lock generated
View File

@ -1422,16 +1422,16 @@
}, },
{ {
"name": "laravel/fortify", "name": "laravel/fortify",
"version": "v1.17.1", "version": "v1.17.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/fortify.git", "url": "https://github.com/laravel/fortify.git",
"reference": "76908639d6c58a4996ce8bbacea9ec7f610b2ec6" "reference": "fc4b9b00b0d657dd035751b286f412976596ba32"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/fortify/zipball/76908639d6c58a4996ce8bbacea9ec7f610b2ec6", "url": "https://api.github.com/repos/laravel/fortify/zipball/fc4b9b00b0d657dd035751b286f412976596ba32",
"reference": "76908639d6c58a4996ce8bbacea9ec7f610b2ec6", "reference": "fc4b9b00b0d657dd035751b286f412976596ba32",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1482,20 +1482,20 @@
"issues": "https://github.com/laravel/fortify/issues", "issues": "https://github.com/laravel/fortify/issues",
"source": "https://github.com/laravel/fortify" "source": "https://github.com/laravel/fortify"
}, },
"time": "2023-04-19T15:48:59+00:00" "time": "2023-04-26T13:35:07+00:00"
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v10.9.0", "version": "v10.10.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "35078125f61ef0b125edf524de934f108d4b47fd" "reference": "0da22a8d179f79b49d4e71f4822f759651f35012"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/35078125f61ef0b125edf524de934f108d4b47fd", "url": "https://api.github.com/repos/laravel/framework/zipball/0da22a8d179f79b49d4e71f4822f759651f35012",
"reference": "35078125f61ef0b125edf524de934f108d4b47fd", "reference": "0da22a8d179f79b49d4e71f4822f759651f35012",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1682,7 +1682,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2023-04-25T13:47:18+00:00" "time": "2023-05-09T13:08:05+00:00"
}, },
{ {
"name": "laravel/horizon", "name": "laravel/horizon",
@ -2283,19 +2283,20 @@
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "3.14.0", "version": "3.15.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem.git", "url": "https://github.com/thephpleague/flysystem.git",
"reference": "e2a279d7f47d9098e479e8b21f7fb8b8de230158" "reference": "a141d430414fcb8bf797a18716b09f759a385bed"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e2a279d7f47d9098e479e8b21f7fb8b8de230158", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a141d430414fcb8bf797a18716b09f759a385bed",
"reference": "e2a279d7f47d9098e479e8b21f7fb8b8de230158", "reference": "a141d430414fcb8bf797a18716b09f759a385bed",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"league/flysystem-local": "^3.0.0",
"league/mime-type-detection": "^1.0.0", "league/mime-type-detection": "^1.0.0",
"php": "^8.0.2" "php": "^8.0.2"
}, },
@ -2354,7 +2355,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem/issues", "issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.14.0" "source": "https://github.com/thephpleague/flysystem/tree/3.15.1"
}, },
"funding": [ "funding": [
{ {
@ -2366,7 +2367,67 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-04-11T18:11:47+00:00" "time": "2023-05-04T09:04:26+00:00"
},
{
"name": "league/flysystem-local",
"version": "3.15.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-local.git",
"reference": "543f64c397fefdf9cfeac443ffb6beff602796b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/543f64c397fefdf9cfeac443ffb6beff602796b3",
"reference": "543f64c397fefdf9cfeac443ffb6beff602796b3",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"league/flysystem": "^3.0.0",
"league/mime-type-detection": "^1.0.0",
"php": "^8.0.2"
},
"type": "library",
"autoload": {
"psr-4": {
"League\\Flysystem\\Local\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frank de Jonge",
"email": "info@frankdejonge.nl"
}
],
"description": "Local filesystem adapter for Flysystem.",
"keywords": [
"Flysystem",
"file",
"files",
"filesystem",
"local"
],
"support": {
"issues": "https://github.com/thephpleague/flysystem-local/issues",
"source": "https://github.com/thephpleague/flysystem-local/tree/3.15.0"
},
"funding": [
{
"url": "https://ecologi.com/frankdejonge",
"type": "custom"
},
{
"url": "https://github.com/frankdejonge",
"type": "github"
}
],
"time": "2023-05-02T20:02:14+00:00"
}, },
{ {
"name": "league/mime-type-detection", "name": "league/mime-type-detection",
@ -3910,16 +3971,16 @@
}, },
{ {
"name": "psy/psysh", "name": "psy/psysh",
"version": "v0.11.16", "version": "v0.11.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/bobthecow/psysh.git", "url": "https://github.com/bobthecow/psysh.git",
"reference": "151b145906804eea8e5d71fea23bfb470c904bfb" "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/151b145906804eea8e5d71fea23bfb470c904bfb", "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3dc5d4018dabd80bceb8fe1e3191ba8460569f0a",
"reference": "151b145906804eea8e5d71fea23bfb470c904bfb", "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3980,9 +4041,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/bobthecow/psysh/issues", "issues": "https://github.com/bobthecow/psysh/issues",
"source": "https://github.com/bobthecow/psysh/tree/v0.11.16" "source": "https://github.com/bobthecow/psysh/tree/v0.11.17"
}, },
"time": "2023-04-26T12:53:57+00:00" "time": "2023-05-05T20:02:42+00:00"
}, },
{ {
"name": "ralouphie/getallheaders", "name": "ralouphie/getallheaders",
@ -4364,16 +4425,16 @@
}, },
{ {
"name": "spatie/laravel-data", "name": "spatie/laravel-data",
"version": "3.4.4", "version": "3.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/laravel-data.git", "url": "https://github.com/spatie/laravel-data.git",
"reference": "d0208dbc6d49ca44ef3ba0dd542cd83ba15bcbc4" "reference": "4c3c31d7d9a515125bfa219099c4df563e4422a8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-data/zipball/d0208dbc6d49ca44ef3ba0dd542cd83ba15bcbc4", "url": "https://api.github.com/repos/spatie/laravel-data/zipball/4c3c31d7d9a515125bfa219099c4df563e4422a8",
"reference": "d0208dbc6d49ca44ef3ba0dd542cd83ba15bcbc4", "reference": "4c3c31d7d9a515125bfa219099c4df563e4422a8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4435,7 +4496,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/spatie/laravel-data/issues", "issues": "https://github.com/spatie/laravel-data/issues",
"source": "https://github.com/spatie/laravel-data/tree/3.4.4" "source": "https://github.com/spatie/laravel-data/tree/3.5.0"
}, },
"funding": [ "funding": [
{ {
@ -4443,7 +4504,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-04-14T08:24:46+00:00" "time": "2023-05-05T15:24:41+00:00"
}, },
{ {
"name": "spatie/laravel-package-tools", "name": "spatie/laravel-package-tools",
@ -7807,16 +7868,16 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "brianium/paratest", "name": "brianium/paratest",
"version": "v7.1.3", "version": "v7.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/paratestphp/paratest.git", "url": "https://github.com/paratestphp/paratest.git",
"reference": "f394bb33b2bb7a4120b531e8991409b7aa62fc43" "reference": "153e68eb9e697baa3acf1db1d8ae1d1eb19fb816"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/f394bb33b2bb7a4120b531e8991409b7aa62fc43", "url": "https://api.github.com/repos/paratestphp/paratest/zipball/153e68eb9e697baa3acf1db1d8ae1d1eb19fb816",
"reference": "f394bb33b2bb7a4120b531e8991409b7aa62fc43", "reference": "153e68eb9e697baa3acf1db1d8ae1d1eb19fb816",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7827,25 +7888,25 @@
"fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1",
"jean85/pretty-package-versions": "^2.0.5", "jean85/pretty-package-versions": "^2.0.5",
"php": "~8.1.0 || ~8.2.0", "php": "~8.1.0 || ~8.2.0",
"phpunit/php-code-coverage": "^10.1.0", "phpunit/php-code-coverage": "^10.1.1",
"phpunit/php-file-iterator": "^4.0.1", "phpunit/php-file-iterator": "^4.0.1",
"phpunit/php-timer": "^6.0", "phpunit/php-timer": "^6.0",
"phpunit/phpunit": "^10.1.0", "phpunit/phpunit": "^10.1.2",
"sebastian/environment": "^6.0.1", "sebastian/environment": "^6.0.1",
"symfony/console": "^6.2.8", "symfony/console": "^6.2.10",
"symfony/process": "^6.2.8" "symfony/process": "^6.2.10"
}, },
"require-dev": { "require-dev": {
"doctrine/coding-standard": "^11.1.0", "doctrine/coding-standard": "^12.0.0",
"ext-pcov": "*", "ext-pcov": "*",
"ext-posix": "*", "ext-posix": "*",
"infection/infection": "^0.26.19", "infection/infection": "^0.26.21",
"phpstan/phpstan": "^1.10.13", "phpstan/phpstan": "^1.10.14",
"phpstan/phpstan-deprecation-rules": "^1.1.3", "phpstan/phpstan-deprecation-rules": "^1.1.3",
"phpstan/phpstan-phpunit": "^1.3.11", "phpstan/phpstan-phpunit": "^1.3.11",
"phpstan/phpstan-strict-rules": "^1.5.1", "phpstan/phpstan-strict-rules": "^1.5.1",
"squizlabs/php_codesniffer": "^3.7.2", "squizlabs/php_codesniffer": "^3.7.2",
"symfony/filesystem": "^6.2.7" "symfony/filesystem": "^6.2.10"
}, },
"bin": [ "bin": [
"bin/paratest", "bin/paratest",
@ -7886,7 +7947,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/paratestphp/paratest/issues", "issues": "https://github.com/paratestphp/paratest/issues",
"source": "https://github.com/paratestphp/paratest/tree/v7.1.3" "source": "https://github.com/paratestphp/paratest/tree/v7.1.4"
}, },
"funding": [ "funding": [
{ {
@ -7898,7 +7959,7 @@
"type": "paypal" "type": "paypal"
} }
], ],
"time": "2023-04-14T06:17:37+00:00" "time": "2023-05-05T09:09:30+00:00"
}, },
{ {
"name": "fakerphp/faker", "name": "fakerphp/faker",
@ -9202,16 +9263,16 @@
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
"version": "4.0.1", "version": "4.0.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "fd9329ab3368f59fe1fe808a189c51086bd4b6bd" "reference": "5647d65443818959172645e7ed999217360654b6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/fd9329ab3368f59fe1fe808a189c51086bd4b6bd", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6",
"reference": "fd9329ab3368f59fe1fe808a189c51086bd4b6bd", "reference": "5647d65443818959172645e7ed999217360654b6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9250,7 +9311,8 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.1" "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2"
}, },
"funding": [ "funding": [
{ {
@ -9258,7 +9320,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-02-10T16:53:14+00:00" "time": "2023-05-07T09:13:23+00:00"
}, },
{ {
"name": "phpunit/php-invoker", "name": "phpunit/php-invoker",
@ -10568,16 +10630,16 @@
}, },
{ {
"name": "spatie/ignition", "name": "spatie/ignition",
"version": "1.6.0", "version": "1.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/ignition.git", "url": "https://github.com/spatie/ignition.git",
"reference": "fbcfcabc44e506e40c4d72fd4ddf465e272a600e" "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/ignition/zipball/fbcfcabc44e506e40c4d72fd4ddf465e272a600e", "url": "https://api.github.com/repos/spatie/ignition/zipball/f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78",
"reference": "fbcfcabc44e506e40c4d72fd4ddf465e272a600e", "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10647,20 +10709,20 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-04-27T08:40:07+00:00" "time": "2023-05-04T13:20:26+00:00"
}, },
{ {
"name": "spatie/laravel-ignition", "name": "spatie/laravel-ignition",
"version": "2.1.0", "version": "2.1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/laravel-ignition.git", "url": "https://github.com/spatie/laravel-ignition.git",
"reference": "3718dfb91bc5aff340af26507a61f0f9605f81e8" "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/3718dfb91bc5aff340af26507a61f0f9605f81e8", "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2f99fa6b732a6049e78ed34e4608ce589605ae54",
"reference": "3718dfb91bc5aff340af26507a61f0f9605f81e8", "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10739,7 +10801,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-04-12T09:26:00+00:00" "time": "2023-05-09T07:19:31+00:00"
}, },
{ {
"name": "symfony/http-client", "name": "symfony/http-client",

View File

@ -13,7 +13,7 @@ public function up(): void
{ {
Schema::create('applications', function (Blueprint $table) { Schema::create('applications', function (Blueprint $table) {
$table->id(); $table->id();
$table->integer('project_id')->nullable(); $table->integer('repository_project_id')->nullable();
$table->string('uuid')->unique(); $table->string('uuid')->unique();
$table->string('name'); $table->string('name');

View File

@ -25,7 +25,7 @@ public function run(): void
Application::create([ Application::create([
'name' => 'coollabsio/coolify-examples:nodejs-fastify', 'name' => 'coollabsio/coolify-examples:nodejs-fastify',
'project_id' => 603035348, 'repository_project_id' => 603035348,
'git_repository' => 'coollabsio/coolify-examples', 'git_repository' => 'coollabsio/coolify-examples',
'git_branch' => 'nodejs-fastify', 'git_branch' => 'nodejs-fastify',
'build_pack' => 'nixpacks', 'build_pack' => 'nixpacks',

View File

@ -1,68 +1,339 @@
@props(['data' => []])
<div x-data="magicsearchbar"> <div x-data="magicsearchbar">
<input x-model="search" class="w-96" x-on:click="open = true" x-on:click.outside="close" {{-- Main --}}
placeholder="🪄 Add / find anything" /> <input x-ref="mainSearch" x-cloak x-show="!serverMenu && !destinationMenu && !projectMenu && !environmentMenu"
<div x-cloak x-show="open" class="absolute text-sm top-11 w-[25rem] bg-neutral-800"> x-model="mainSearch" class="w-96" x-on:click="checkMainMenu" x-on:click.outside="closeMainMenu"
placeholder="🪄 Search for anything... magically..." />
<div x-cloak x-show="mainMenu" class="absolute text-sm top-11 w-[25rem] bg-neutral-800">
<template x-for="item in filteredItems" :key="item.name"> <template x-for="item in filteredItems" :key="item.name">
<div x-on:click="execute(item.action)" class="py-2 pl-4 cursor-pointer hover:bg-neutral-700"> <div x-on:click="await next('server',item.name, item.disabled ?? false)"
<span class="px-2 mr-1 text-xs bg-purple-700 rounded" x-show="item.type" x-text="item.type"></span> :class="item.disabled && 'text-neutral-500 bg-neutral-900 hover:bg-neutral-900 cursor-not-allowed opacity-60'"
class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span class="px-2 mr-1 text-xs bg-green-600 rounded" x-show="item.type === 'Add'"
x-text="item.type"></span>
<span class="px-2 mr-1 text-xs bg-purple-600 rounded" x-show="item.type === 'Jump'"
x-text="item.type"></span>
<span x-text="item.name"></span> <span x-text="item.name"></span>
</div> </div>
</template> </template>
</div> </div>
{{-- Servers --}}
<div x-cloak x-show="serverMenu" x-on:click.outside="closeServerMenu">
<input x-ref="serverSearch" x-model="serverSearch" class="w-96" placeholder="Select a server" />
<div class="absolute text-sm top-11 w-[25rem] bg-neutral-800">
<template x-for="server in filteredServers" :key="server.name ?? server">
<div x-on:click="await next('destination',server.uuid)"
class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span class="px-2 mr-1 text-xs bg-purple-600 rounded">Server</span>
<span x-text="server.name"></span>
</div>
</template>
</div>
</div>
{{-- Destinations --}}
<div x-cloak x-show="destinationMenu" x-on:click.outside="closeDestinationMenu">
<input x-ref="destinationSearch" x-model="destinationSearch" class="w-96"
placeholder="Select a destination" />
<div class="absolute text-sm top-11 w-[25rem] bg-neutral-800">
<template x-for="destination in filteredDestinations" :key="destination.name ?? destination">
<div x-on:click="await next('project',destination.uuid)"
class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span class="px-2 mr-1 text-xs bg-purple-700 rounded">Destination</span>
<span x-text="destination.name"></span>
</div>
</template>
</div>
</div>
{{-- Projects --}}
<div x-cloak x-show="projectMenu" x-on:click.outside="closeProjectMenu">
<input x-ref="projectSearch" x-model="projectSearch" class="w-96" placeholder="Type your project name..." />
<div class="absolute text-sm top-11 w-[25rem] bg-neutral-800">
<div x-on:click="await newProject" class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span>New Project</span>
<span x-text="projectSearch"></span>
</div>
<template x-for="project in filteredProjects" :key="project.name ?? project">
<div x-on:click="await next('environment',project.uuid)"
class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span class="px-2 mr-1 text-xs bg-purple-700 rounded">Project</span>
<span x-text="project.name"></span>
</div>
</template>
</div>
</div>
{{-- Environments --}}
<div x-cloak x-show="environmentMenu" x-on:click.outside="closeEnvironmentMenu">
<input x-ref="environmentSearch" x-model="environmentSearch" class="w-96"
placeholder="Select a environment" />
<div class="absolute text-sm top-11 w-[25rem] bg-neutral-800">
<div x-on:click="await newEnvironment" class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span>New Environment</span>
<span x-text="environmentSearch"></span>
</div>
<template x-for="environment in filteredEnvironments" :key="environment.name ?? environment">
<div x-on:click="await next('jump',environment.name)"
class="py-2 pl-4 cursor-pointer hover:bg-neutral-700">
<span class="px-2 mr-1 text-xs bg-purple-700 rounded">Env</span>
<span x-text="environment.name"></span>
</div>
</template>
</div>
</div>
</div> </div>
<script> <script>
document.addEventListener('alpine:init', () => { document.addEventListener('alpine:init', () => {
const data = @js($data);
console.log(data)
Alpine.data('magicsearchbar', () => ({ Alpine.data('magicsearchbar', () => ({
open: false, init() {
search: '', this.$watch('mainMenu', (value) => {
items: [{ if (value) this.$refs.mainSearch.focus()
name: 'Public Repository', })
type: 'add', this.$watch('serverMenu', (value) => {
tags: 'application,public,repository', this.$nextTick(() => {
action: 'public-repo', this.$refs.serverSearch.focus()
}, { })
name: 'Private Repository (with GitHub App)', })
type: 'add', this.$watch('destinationMenu', (value) => {
tags: 'application,private,repository', this.$nextTick(() => {
action: 'github-private-repo-app' this.$refs.destinationSearch.focus()
}, { })
name: 'Private Repository (with Deploy Key)', })
type: 'add', this.$watch('projectMenu', (value) => {
tags: 'application,private,repository', this.$nextTick(() => {
action: 'github-private-repo-deploy-key' this.$refs.projectSearch.focus()
}, { })
name: 'Database', })
type: 'add', this.$watch('environmentMenu', (value) => {
tags: 'data,database,mysql,postgres,sql,sqlite,redis,mongodb,maria,percona', this.$nextTick(() => {
action: 'database' this.$refs.environmentSearch.focus()
}], })
close() {
this.open = false
this.search = ''
},
filteredItems() {
if (this.search === '') return this.items
return this.items.filter(item => {
return item.name.toLowerCase().includes(this.search.toLowerCase())
}) })
}, },
execute(action) { mainMenu: false,
serverMenu: false,
destinationMenu: false,
projectMenu: false,
environmentMenu: false,
mainSearch: '',
serverSearch: '',
destinationSearch: '',
projectSearch: '',
environmentSearch: '',
selectedAction: '',
selectedServer: '',
selectedDestination: '',
selectedProject: '',
selectedEnvironment: '',
servers: ['Loading...'],
destinations: ['Loading...'],
projects: ['Loading...'],
environments: ['Loading...'],
items: [{
name: 'Public Repository',
type: 'Add',
tags: 'application,public,repository',
},
{
name: 'Private Repository (with GitHub App)',
type: 'Add',
tags: 'application,private,repository',
},
{
name: 'Private Repository (with Deploy Key)',
type: 'Add',
tags: 'application,private,repository',
},
{
name: 'Database',
type: 'Add',
tags: 'data,database,mysql,postgres,sql,sqlite,redis,mongodb,maria,percona',
disabled: true,
},
{
name: 'Servers',
type: 'Jump',
}
],
checkMainMenu() {
if (this.serverMenu) return
this.mainMenu = true
},
closeMainMenu() {
this.mainMenu = false
this.mainSearch = ''
},
closeServerMenu() {
this.serverMenu = false
this.serverSearch = ''
},
closeDestinationMenu() {
this.destinationMenu = false
this.destinationSearch = ''
},
closeProjectMenu() {
this.projectMenu = false
this.projectSearch = ''
},
closeEnvironmentMenu() {
this.environmentMenu = false
this.environmentSearch = ''
},
filteredItems() {
if (this.mainSearch === '') return this.items
return this.items.filter(item => {
return item.name.toLowerCase().includes(this.mainSearch.toLowerCase())
})
},
filteredServers() {
if (this.serverSearch === '') return this.servers
return this.servers.filter(server => {
return server.name.toLowerCase().includes(this.serverSearch
.toLowerCase())
})
},
filteredDestinations() {
if (this.destinationSearch === '') return this.destinations
return this.destinations.filter(destination => {
return destination.name.toLowerCase().includes(this.destinationSearch
.toLowerCase())
})
},
filteredProjects() {
if (this.projectSearch === '') return this.projects
return this.projects.filter(project => {
return project.name.toLowerCase().includes(this.projectSearch
.toLowerCase())
})
},
filteredEnvironments() {
if (this.environmentSearch === '') return this.environments
return this.environments.filter(environment => {
return environment.name.toLowerCase().includes(this.environmentSearch
.toLowerCase())
})
},
async newProject() {
const response = await fetch('/magic?server=' + this.selectedServer +
'&destination=' + this.selectedDestination +
'&project=new&name=' + this.projectSearch);
if (response.ok) {
const {
project_uuid
} = await response.json();
this.next('environment', project_uuid)
this.next('jump', 'production')
}
},
async newEnvironment() {
const response = await fetch('/magic?server=' + this.selectedServer +
'&destination=' + this.selectedDestination +
'&project=' + this.selectedProject + '&environment=new&name=' + this
.environmentSearch);
if (response.ok) {
this.next('jump', this.environmentSearch)
}
},
async next(action, id, isDisabled) {
if (isDisabled) return
let response = null
switch (action) { switch (action) {
case 'public-repo': case 'server':
window.location.href = '/project/new/public-repository' this.mainMenu = false
this.serverMenu = true
this.items.find((item, index) => {
if (item.name.toLowerCase() === id
.toLowerCase()) {
return this.selectedAction = index
}
})
response = await fetch('/magic?servers=true');
if (response.ok) {
const {
servers
} = await response.json();
this.servers = servers;
}
break break
case 'github-private-repo-app': case 'destination':
window.location.href = '/project/new/github-private-repository' if (this.items[this.selectedAction].type === "Jump") {
return window.location = '/server/' + id
}
this.mainMenu = false
this.serverMenu = false
this.destinationMenu = true
this.selectedServer = id
response = await fetch('/magic?server=' + this
.selectedServer +
'&destinations=true');
if (response.ok) {
const {
destinations
} = await response.json();
this.destinations = destinations;
}
break break
case 'github-private-repo-deploy-key': case 'project':
window.location.href = '/project/new/github-private-repository-deploy-key' this.mainMenu = false
this.serverMenu = false
this.destinationMenu = false
this.projectMenu = true
this.selectedDestination = id
response = await fetch('/magic?server=' + this
.selectedServer +
'&destination=' + this.selectedDestination +
'&projects=true');
if (response.ok) {
const {
projects
} = await response.json();
this.projects = projects;
}
break break
case 'database': case 'environment':
window.location.href = '/database/new' this.mainMenu = false
this.serverMenu = false
this.destinationMenu = false
this.projectMenu = false
this.environmentMenu = true
this.selectedProject = id
response = await fetch('/magic?server=' + this
.selectedServer +
'&destination=' + this.selectedDestination +
'&project=' + this
.selectedProject + '&environments=true');
if (response.ok) {
const {
environments
} = await response.json();
this.environments = environments;
}
break
case 'jump':
this.mainMenu = false
this.serverMenu = false
this.destinationMenu = false
this.projectMenu = false
this.environmentMenu = false
this.selectedEnvironment = id
if (this.selectedAction === 0) {
window.location =
`/project/${this.selectedProject}/${this.selectedEnvironment}/new?type=public&destination=${this.selectedDestination}`
} else if (this.selectedAction === 1) {
window.location =
`/project/${this.selectedProject}/${this.selectedEnvironment}/new?type=private-gh-app&destination=${this.selectedDestination}`
} else if (this.selectedAction === 2) {
window.location =
`/project/${this.selectedProject}/${this.selectedEnvironment}/new?type=private-deploy-key&destination=${this.selectedDestination}`
} else if (this.selectedAction === 3) {
console.log('new Database')
}
break break
} }
} }

View File

@ -1,7 +1,5 @@
<x-layout> <x-layout>
<h1>Projects <a href="{{ route('project.new') }}"> <h1>Projects </h1>
<x-inputs.button>New</x-inputs.button>
</a></h1>
@forelse ($projects as $project) @forelse ($projects as $project)
<a href="{{ route('project.environments', [$project->uuid]) }}">{{ data_get($project, 'name') }}</a> <a href="{{ route('project.environments', [$project->uuid]) }}">{{ data_get($project, 'name') }}</a>
@empty @empty

View File

@ -1,58 +1,17 @@
<div> <div>
@if ($servers->count() > 0) <div>
<h1>Choose a server</h1> <h1>Select a private key</h1>
@endif @foreach ($private_keys as $key)
@forelse ($servers as $server) @if ($private_key_id == $key->id)
@if ($chosenServer && $chosenServer['id'] === $server->id) <x-inputs.button class="bg-blue-500" wire:click.defer="setPrivateKey('{{ $key->id }}')">
<x-inputs.button class="bg-blue-500" wire:click="chooseServer({{ $server }})">{{ $server->name }} {{ $key->name }}</x-inputs.button>
</x-inputs.button> @else
@else <x-inputs.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
<x-inputs.button wire:click="chooseServer({{ $server }})">{{ $server->name }}</x-inputs.button> </x-inputs.button>
@endif @endif
@empty @endforeach
No servers found. </div>
<p>Did you forget to add a destination on the server?</p> @isset($private_key_id)
@endforelse
@isset($chosenServer)
@if ($standalone_docker->count() > 0 || $swarm_docker->count() > 0)
<h1>Choose a destination</h1>
<div>
@foreach ($standalone_docker as $standalone)
@if ($chosenDestination?->uuid == $standalone->uuid)
<x-inputs.button class="bg-blue-500"
wire:click="setDestination('{{ $standalone->uuid }}','StandaloneDocker')">
{{ $standalone->network }}</x-inputs.button>
@else
<x-inputs.button wire:click="setDestination('{{ $standalone->uuid }}','StandaloneDocker')">
{{ $standalone->network }}</x-inputs.button>
@endif
@endforeach
@foreach ($swarm_docker as $standalone)
@if ($chosenDestination?->uuid == $standalone->uuid)
<x-inputs.button class="bg-blue-500"
wire:click="setDestination('{{ $standalone->uuid }}','SwarmDocker')">
{{ $standalone->network }}</x-inputs.button>
@else
<x-inputs.button wire:click="setDestination('{{ $standalone->uuid }}','SwarmDocker')">
{{ $standalone->uuid }}</x-inputs.button>
@endif
@endforeach
</div>
<div>
<a href="{{ route('destination.new', ['server_id' => $chosenServer['id']]) }}">Add
a new
destination</a>
</div>
@else
<h1>No destinations found on this server.</h1>
<a href="{{ route('destination.new', ['server_id' => $chosenServer['id']]) }}">Add
a
destination</a>
@endif
@endisset
@isset($chosenDestination)
<h1>Choose a repository</h1> <h1>Choose a repository</h1>
<form wire:submit.prevent='submit'> <form wire:submit.prevent='submit'>
<div class="flex items-end gap-2 pb-2"> <div class="flex items-end gap-2 pb-2">
@ -68,17 +27,5 @@
Submit Submit
</x-inputs.button> </x-inputs.button>
</form> </form>
<div>
<h1>Select a private key</h1>
@foreach ($private_keys as $key)
@if ($private_key_id == $key->id)
<x-inputs.button class="bg-blue-500" wire:click.defer="setPrivateKey('{{ $key->id }}')">
{{ $key->name }}</x-inputs.button>
@else
<x-inputs.button wire:click.defer="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
</x-inputs.button>
@endif
@endforeach
</div>
@endisset @endisset
</div> </div>

View File

@ -35,48 +35,7 @@
@endif @endif
@endforeach @endforeach
</select> </select>
<x-inputs.button wire:click="loadServers">Select Branch</x-inputs.button> <x-inputs.button wire:click="submit">Save</x-inputs.button>
@endif
</div>
<div>
@if ($servers->count() > 0)
<h3>Choose a Server</h3>
<select wire:model.defer="selected_server_id">
<option disabled>Choose a server</option>
@foreach ($servers as $server)
@if ($loop->first)
<option selected value="{{ data_get($server, 'id') }}">{{ data_get($server, 'name') }}
</option>
@else
<option value="{{ data_get($server, 'id') }}">{{ data_get($server, 'name') }}</option>
@endif
@endforeach
</select>
<x-inputs.button wire:click="loadDestinations">Select Server</x-inputs.button>
@endif
</div>
<div>
@if ($destinations->count() > 0)
<h3>Choose a Destination</h3>
<select wire:model.defer="selected_destination_id">
<option disabled>Choose a destination</option>
@foreach ($destinations as $destination)
@if ($loop->first)
<option selected value="{{ data_get($destination, 'id') }}">
{{ data_get($destination, 'network') }}</option>
@else
<option value="{{ data_get($destination, 'id') }}">{{ data_get($destination, 'network') }}
</option>
@endif
@endforeach
</select>
<x-inputs.button wire:click="submit">Select Destination</x-inputs.button>
@else
<h1>No destinations found on this server.</h1>
<a href="{{ route('destination.new', ['server_id' => $selected_server_id]) }}">Add
a
destination</a>
@endif @endif
</div> </div>
@else @else

View File

@ -1,72 +1,17 @@
<div> <div>
@if ($servers->count() > 0) <h1>Choose a public repository</h1>
<h1>Choose a server</h1> <form class="flex flex-col gap-2 w-96" wire:submit.prevent='submit'>
@endif <x-inputs.input instantSave type="checkbox" id="is_static" label="Is it a static site?" />
@forelse ($servers as $server) <div class="flex gap-2">
@if ($chosenServer && $chosenServer['id'] === $server->id)
<x-inputs.button class="bg-blue-500" wire:click="chooseServer({{ $server }})">{{ $server->name }}
</x-inputs.button>
@else
<x-inputs.button wire:click="chooseServer({{ $server }})">{{ $server->name }}</x-inputs.button>
@endif
@empty
No servers found.
<p>Did you forget to add a destination on the server?</p>
@endforelse
@isset($chosenServer)
@if ($standalone_docker->count() > 0 || $swarm_docker->count() > 0)
<h1>Choose a destination</h1>
<div>
@foreach ($standalone_docker as $standalone)
@if ($chosenDestination?->uuid == $standalone->uuid)
<x-inputs.button class="bg-blue-500"
wire:click="setDestination('{{ $standalone->uuid }}','StandaloneDocker')">
{{ $standalone->network }}</x-inputs.button>
@else
<x-inputs.button wire:click="setDestination('{{ $standalone->uuid }}','StandaloneDocker')">
{{ $standalone->network }}</x-inputs.button>
@endif
@endforeach
@foreach ($swarm_docker as $standalone)
@if ($chosenDestination?->uuid == $standalone->uuid)
<x-inputs.button class="bg-blue-500"
wire:click="setDestination('{{ $standalone->uuid }}','SwarmDocker')">
{{ $standalone->network }}</x-inputs.button>
@else
<x-inputs.button wire:click="setDestination('{{ $standalone->uuid }}','SwarmDocker')">
{{ $standalone->uuid }}</x-inputs.button>
@endif
@endforeach
</div>
<div>
<a href="{{ route('destination.new', ['server_id' => $chosenServer['id']]) }}">Add
a new
destination</a>
</div>
@else
<h1>No destinations found on this server.</h1>
<a href="{{ route('destination.new', ['server_id' => $chosenServer['id']]) }}">Add
a
destination</a>
@endif
@endisset
@isset($chosenDestination)
<h1>Choose a repository</h1>
<form class="flex flex-col gap-2 w-96" wire:submit.prevent='submit'>
<x-inputs.input class="w-96" id="repository_url" label="Repository URL" /> <x-inputs.input class="w-96" id="repository_url" label="Repository URL" />
<x-inputs.input instantSave type="checkbox" id="is_static" label="Static Site?" />
@if ($is_static) @if ($is_static)
<x-inputs.input id="publish_directory" label="Publish Directory" /> <x-inputs.input id="publish_directory" label="Publish Directory" />
@else @else
<x-inputs.input type="number" id="port" label="Port" :readonly="$is_static" /> <x-inputs.input type="number" id="port" label="Port" :readonly="$is_static" />
@endif @endif
<x-inputs.button type="submit"> </div>
Submit <x-inputs.button type="submit">
</x-inputs.button> Submit
</form> </x-inputs.button>
@endisset </form>
</div> </div>

View File

@ -1,30 +1,9 @@
<x-layout> <x-layout>
@if ($type === 'project') @if ($type === 'public')
<h1>New Project</h1> <livewire:project.new.public-git-repository :type="$type" />
@elseif ($type === 'resource') @elseif ($type === 'private-gh-app')
<h1>New Resource</h1> <livewire:project.new.github-private-repository :type="$type" />
@elseif ($type === 'private-deploy-key')
<livewire:project.new.github-private-repository-deploy-key :type="$type" />
@endif @endif
<div x-data="{ activeTab: 'choose' }">
<div class="flex flex-col w-64 gap-2 mb-10">
<x-inputs.button @click.prevent="activeTab = 'public-repo'">Public Repository</x-inputs.button>
<x-inputs.button @click.prevent="activeTab = 'github-private-repo'">Private Repository (with GitHub App)
</x-inputs.button>
<x-inputs.button @click.prevent="activeTab = 'github-private-repo-deploy-key'">Private Repository (with
Deploy Key)
</x-inputs.button>
@if ($type === 'project')
<livewire:project.new.empty-project />
@endif
</div>
<div x-cloak x-show="activeTab === 'public-repo'">
<livewire:project.new.public-git-repository :type="$type" />
</div>
<div x-cloak x-show="activeTab === 'github-private-repo'">
<livewire:project.new.github-private-repository :type="$type" />
</div>
<div x-cloak x-show="activeTab === 'github-private-repo-deploy-key'">
<livewire:project.new.github-private-repository-deploy-key :type="$type" />
</div>
</div>
</x-layout> </x-layout>

View File

@ -1,13 +1,12 @@
<?php <?php
use App\Http\Controllers\ApplicationController; use App\Http\Controllers\ApplicationController;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\ProjectController; use App\Http\Controllers\ProjectController;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use App\Models\PrivateKey; use App\Models\PrivateKey;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use App\Models\SwarmDocker; use App\Models\SwarmDocker;
use App\Http\Controllers\ServerController; use App\Models\Environment;
use App\Models\GithubApp; use App\Models\GithubApp;
use App\Models\Project; use App\Models\Project;
use App\Models\Server; use App\Models\Server;
@ -29,6 +28,69 @@
Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function () {
Route::get('/magic', function () {
try {
$is_new_project = request()->query('project') === 'new';
$is_new_environment = request()->query('environment') === 'new';
// Get servers
if (request()->query('servers') === 'true') {
$servers = Server::where('team_id', session('currentTeam')->id)->get();
return response()->json([
'servers' => $servers,
]);
}
// Get destinations
if (request()->query('server') && request()->query('destinations') === 'true') {
$destinations = Server::destinations(request()->query('server'));
return response()->json([
'destinations' => $destinations->toArray(),
]);
}
// Get projects
if (request()->query('server') && request()->query('destination') && request()->query('projects') === 'true') {
$projects = Project::where('team_id', session('currentTeam')->id)->get();
return response()->json([
'projects' => $projects->toArray(),
]);
}
// Get environments
if (request()->query('server') && request()->query('destination') && request()->query('project') && request()->query('environments') === 'true') {
$environments = Project::where('team_id', session('currentTeam')->id)->where('uuid', request()->query('project'))->first()->environments;
return response()->json([
'environments' => $environments->toArray(),
]);
}
if ($is_new_project) {
$project = Project::create([
'name' => request()->query('name') ?? generateRandomName(),
'team_id' => session('currentTeam')->id,
]);
return response()->json([
'project_uuid' => $project->uuid
]);
}
if ($is_new_environment) {
$environment = Project::where('uuid', request()->query('project'))->first()->environments->where('name', request()->query('name'))->first();
if (!$environment) {
$environment = Environment::create([
'name' => request()->query('name') ?? generateRandomName(),
'project_id' => Project::where('uuid', request()->query('project'))->first()->id,
]);
}
return response()->json([
'environment' => $environment->name
]);
}
return response()->json([
'magic' => true,
]);
} catch (\Throwable $e) {
return generalErrorHandler($e, isJson: true);
}
});
Route::get('/', function () { Route::get('/', function () {
$id = session('currentTeam')->id; $id = session('currentTeam')->id;
$projects = Project::where('team_id', $id)->get(); $projects = Project::where('team_id', $id)->get();
@ -146,7 +208,7 @@
Route::get( Route::get(
'/project/{project_uuid}/{environment_name}/new', '/project/{project_uuid}/{environment_name}/new',
[ProjectController::class, 'resources_new'] [ProjectController::class, 'new']
)->name('project.resources.new'); )->name('project.resources.new');
Route::get( Route::get(

View File

@ -93,7 +93,7 @@
if (!$id || !$branch) { if (!$id || !$branch) {
return response('not cool'); return response('not cool');
} }
$applications = Application::where('project_id', $id)->where('git_branch', $branch)->get(); $applications = Application::where('repository_project_id', $id)->where('git_branch', $branch)->get();
foreach ($applications as $application) { foreach ($applications as $application) {
if ($application->isDeployable()) { if ($application->isDeployable()) {
$deployment_uuid = new Cuid2(7); $deployment_uuid = new Cuid2(7);