mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-01 14:06:15 +00:00
#591 - source-controls
This commit is contained in:
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\ServerProvider;
|
use App\Models\ServerProvider;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class EditServerProvider
|
class EditServerProvider
|
||||||
{
|
{
|
||||||
@ -12,6 +13,8 @@ class EditServerProvider
|
|||||||
*/
|
*/
|
||||||
public function edit(ServerProvider $serverProvider, Project $project, array $input): ServerProvider
|
public function edit(ServerProvider $serverProvider, Project $project, array $input): ServerProvider
|
||||||
{
|
{
|
||||||
|
Validator::make($input, self::rules())->validate();
|
||||||
|
|
||||||
$serverProvider->profile = $input['name'];
|
$serverProvider->profile = $input['name'];
|
||||||
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
|
$serverProvider->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
@ -17,10 +17,12 @@ class ConnectSourceControl
|
|||||||
*/
|
*/
|
||||||
public function connect(Project $project, array $input): SourceControl
|
public function connect(Project $project, array $input): SourceControl
|
||||||
{
|
{
|
||||||
|
Validator::make($input, self::rules($input))->validate();
|
||||||
|
|
||||||
$sourceControl = new SourceControl([
|
$sourceControl = new SourceControl([
|
||||||
'provider' => $input['provider'],
|
'provider' => $input['provider'],
|
||||||
'profile' => $input['name'],
|
'profile' => $input['name'],
|
||||||
'url' => Arr::has($input, 'url') ? $input['url'] : null,
|
'url' => isset($input['url']) && $input['url'] ? $input['url'] : null,
|
||||||
'project_id' => isset($input['global']) && $input['global'] ? null : $project->id,
|
'project_id' => isset($input['global']) && $input['global'] ? null : $project->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -28,8 +30,7 @@ public function connect(Project $project, array $input): SourceControl
|
|||||||
|
|
||||||
if (! $sourceControl->provider()->connect()) {
|
if (! $sourceControl->provider()->connect()) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'token' => __('Cannot connect to :provider or invalid token!', ['provider' => $sourceControl->provider]
|
'token' => __('Cannot connect to :provider or invalid token!', ['provider' => $sourceControl->provider]),
|
||||||
),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class EditSourceControl
|
class EditSourceControl
|
||||||
@ -15,46 +16,25 @@ class EditSourceControl
|
|||||||
*/
|
*/
|
||||||
public function edit(SourceControl $sourceControl, Project $project, array $input): SourceControl
|
public function edit(SourceControl $sourceControl, Project $project, array $input): SourceControl
|
||||||
{
|
{
|
||||||
|
Validator::make($input, self::rules())->validate();
|
||||||
|
|
||||||
$sourceControl->profile = $input['name'];
|
$sourceControl->profile = $input['name'];
|
||||||
$sourceControl->url = $input['url'] ?? null;
|
|
||||||
$sourceControl->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
|
$sourceControl->project_id = isset($input['global']) && $input['global'] ? null : $project->id;
|
||||||
|
|
||||||
$sourceControl->provider_data = $sourceControl->provider()->editData($input);
|
|
||||||
|
|
||||||
if (! $sourceControl->provider()->connect()) {
|
|
||||||
throw ValidationException::withMessages([
|
|
||||||
'token' => __('Cannot connect to :provider or invalid token!', ['provider' => $sourceControl->provider]),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$sourceControl->save();
|
$sourceControl->save();
|
||||||
|
|
||||||
return $sourceControl;
|
return $sourceControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $input
|
|
||||||
* @return array<string, array<int, mixed>>
|
* @return array<string, array<int, mixed>>
|
||||||
*/
|
*/
|
||||||
public static function rules(SourceControl $sourceControl, array $input): array
|
public static function rules(): array
|
||||||
{
|
{
|
||||||
$rules = [
|
return [
|
||||||
'name' => [
|
'name' => [
|
||||||
'required',
|
'required',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
return array_merge($rules, self::providerRules($sourceControl, $input));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $input
|
|
||||||
* @return array<string, array<int, mixed>>
|
|
||||||
*
|
|
||||||
* @throws ValidationException
|
|
||||||
*/
|
|
||||||
private static function providerRules(SourceControl $sourceControl, array $input): array
|
|
||||||
{
|
|
||||||
return $sourceControl->provider()->editRules($input);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,6 @@ public function create(Request $request, Project $project): ServerProviderResour
|
|||||||
{
|
{
|
||||||
$this->authorize('create', ServerProvider::class);
|
$this->authorize('create', ServerProvider::class);
|
||||||
|
|
||||||
$this->validate($request, CreateServerProvider::rules($request->all()));
|
|
||||||
|
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$serverProvider = app(CreateServerProvider::class)->create($user, $project, $request->all());
|
$serverProvider = app(CreateServerProvider::class)->create($user, $project, $request->all());
|
||||||
@ -85,8 +83,6 @@ public function update(Request $request, Project $project, ServerProvider $serve
|
|||||||
|
|
||||||
$this->validateRoute($project, $serverProvider);
|
$this->validateRoute($project, $serverProvider);
|
||||||
|
|
||||||
$this->validate($request, EditServerProvider::rules());
|
|
||||||
|
|
||||||
$serverProvider = app(EditServerProvider::class)->edit($serverProvider, $project, $request->all());
|
$serverProvider = app(EditServerProvider::class)->edit($serverProvider, $project, $request->all());
|
||||||
|
|
||||||
return new ServerProviderResource($serverProvider);
|
return new ServerProviderResource($serverProvider);
|
||||||
|
@ -53,8 +53,6 @@ public function create(Request $request, Project $project): SourceControlResourc
|
|||||||
{
|
{
|
||||||
$this->authorize('create', SourceControl::class);
|
$this->authorize('create', SourceControl::class);
|
||||||
|
|
||||||
$this->validate($request, ConnectSourceControl::rules($request->all()));
|
|
||||||
|
|
||||||
$sourceControl = app(ConnectSourceControl::class)->connect($project, $request->all());
|
$sourceControl = app(ConnectSourceControl::class)->connect($project, $request->all());
|
||||||
|
|
||||||
return new SourceControlResource($sourceControl);
|
return new SourceControlResource($sourceControl);
|
||||||
@ -87,8 +85,6 @@ public function update(Request $request, Project $project, SourceControl $source
|
|||||||
|
|
||||||
$this->validateRoute($project, $sourceControl);
|
$this->validateRoute($project, $sourceControl);
|
||||||
|
|
||||||
$this->validate($request, EditSourceControl::rules($sourceControl, $request->all()));
|
|
||||||
|
|
||||||
$sourceControl = app(EditSourceControl::class)->edit($sourceControl, $project, $request->all());
|
$sourceControl = app(EditSourceControl::class)->edit($sourceControl, $project, $request->all());
|
||||||
|
|
||||||
return new SourceControlResource($sourceControl);
|
return new SourceControlResource($sourceControl);
|
||||||
|
73
app/Http/Controllers/SourceControlController.php
Normal file
73
app/Http/Controllers/SourceControlController.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Actions\SourceControl\ConnectSourceControl;
|
||||||
|
use App\Actions\SourceControl\DeleteSourceControl;
|
||||||
|
use App\Actions\SourceControl\EditSourceControl;
|
||||||
|
use App\Http\Resources\SourceControlResource;
|
||||||
|
use App\Models\SourceControl;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
use Inertia\Inertia;
|
||||||
|
use Inertia\Response;
|
||||||
|
use Spatie\RouteAttributes\Attributes\Delete;
|
||||||
|
use Spatie\RouteAttributes\Attributes\Get;
|
||||||
|
use Spatie\RouteAttributes\Attributes\Middleware;
|
||||||
|
use Spatie\RouteAttributes\Attributes\Patch;
|
||||||
|
use Spatie\RouteAttributes\Attributes\Post;
|
||||||
|
use Spatie\RouteAttributes\Attributes\Prefix;
|
||||||
|
|
||||||
|
#[Prefix('settings/source-controls')]
|
||||||
|
#[Middleware(['auth'])]
|
||||||
|
class SourceControlController extends Controller
|
||||||
|
{
|
||||||
|
#[Get('/', name: 'source-controls')]
|
||||||
|
public function index(): Response
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', SourceControl::class);
|
||||||
|
|
||||||
|
return Inertia::render('source-controls/index', [
|
||||||
|
'sourceControls' => SourceControlResource::collection(SourceControl::getByProjectId(user()->current_project_id)->simplePaginate(config('web.pagination_size'))),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Get('/json', name: 'source-controls.json')]
|
||||||
|
public function json(): ResourceCollection
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', SourceControl::class);
|
||||||
|
|
||||||
|
return SourceControlResource::collection(SourceControl::getByProjectId(user()->current_project_id)->get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Post('/', name: 'source-controls.store')]
|
||||||
|
public function store(Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$this->authorize('create', SourceControl::class);
|
||||||
|
|
||||||
|
app(ConnectSourceControl::class)->connect(user()->currentProject, $request->all());
|
||||||
|
|
||||||
|
return back()->with('success', 'Source control created.');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Patch('/{sourceControl}', name: 'source-controls.update')]
|
||||||
|
public function update(Request $request, SourceControl $sourceControl): RedirectResponse
|
||||||
|
{
|
||||||
|
$this->authorize('update', $sourceControl);
|
||||||
|
|
||||||
|
app(EditSourceControl::class)->edit($sourceControl, user()->currentProject, $request->all());
|
||||||
|
|
||||||
|
return back()->with('success', 'Source control updated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Delete('{sourceControl}', name: 'source-controls.destroy')]
|
||||||
|
public function destroy(SourceControl $sourceControl): RedirectResponse
|
||||||
|
{
|
||||||
|
$this->authorize('delete', $sourceControl);
|
||||||
|
|
||||||
|
app(DeleteSourceControl::class)->delete($sourceControl);
|
||||||
|
|
||||||
|
return to_route('source-controls')->with('success', 'Source control deleted.');
|
||||||
|
}
|
||||||
|
}
|
@ -26,16 +26,6 @@ public function createData(array $input): array
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function editRules(array $input): array
|
|
||||||
{
|
|
||||||
return $this->createRules($input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function editData(array $input): array
|
|
||||||
{
|
|
||||||
return $this->createData($input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function data(): array
|
public function data(): array
|
||||||
{
|
{
|
||||||
// support for older data
|
// support for older data
|
||||||
|
@ -29,12 +29,15 @@ public function createRules(array $input): array
|
|||||||
public function connect(): bool
|
public function connect(): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
ds($this->getApiUrl());
|
||||||
$res = Http::withToken($this->data()['token'])
|
$res = Http::withToken($this->data()['token'])
|
||||||
->get($this->getApiUrl().'/projects');
|
->get($this->getApiUrl().'/version');
|
||||||
} catch (Exception) {
|
} catch (Exception) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ds($res->status());
|
||||||
|
|
||||||
return $res->successful();
|
return $res->successful();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\SourceControlProviders;
|
namespace App\SourceControlProviders;
|
||||||
|
|
||||||
|
use App\Exceptions\FailedToDeployGitHook;
|
||||||
use App\Exceptions\FailedToDeployGitKey;
|
use App\Exceptions\FailedToDeployGitKey;
|
||||||
use App\Exceptions\FailedToDestroyGitHook;
|
use App\Exceptions\FailedToDestroyGitHook;
|
||||||
|
|
||||||
@ -19,18 +20,6 @@ public function createRules(array $input): array;
|
|||||||
*/
|
*/
|
||||||
public function createData(array $input): array;
|
public function createData(array $input): array;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $input
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function editRules(array $input): array;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array<string, mixed> $input
|
|
||||||
* @return array<string, mixed>
|
|
||||||
*/
|
|
||||||
public function editData(array $input): array;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
@ -43,10 +32,10 @@ public function getRepo(string $repo): mixed;
|
|||||||
public function fullRepoUrl(string $repo, string $key): string;
|
public function fullRepoUrl(string $repo, string $key): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<mixed> $events
|
* @param array<int, mixed> $events
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*
|
*
|
||||||
* @throws \App\Exceptions\FailedToDeployGitHook
|
* @throws FailedToDeployGitHook
|
||||||
*/
|
*/
|
||||||
public function deployHook(string $repo, array $events, string $secret): array;
|
public function deployHook(string $repo, array $events, string $secret): array;
|
||||||
|
|
||||||
@ -56,7 +45,7 @@ public function deployHook(string $repo, array $events, string $secret): array;
|
|||||||
public function destroyHook(string $repo, string $hookId): void;
|
public function destroyHook(string $repo, string $hookId): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>|null
|
||||||
*/
|
*/
|
||||||
public function getLastCommit(string $repo, string $branch): ?array;
|
public function getLastCommit(string $repo, string $branch): ?array;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"ext-intl": "*",
|
"ext-intl": "*",
|
||||||
"aws/aws-sdk-php": "^3.158",
|
"aws/aws-sdk-php": "^3.158",
|
||||||
"inertiajs/inertia-laravel": "^2.0",
|
"inertiajs/inertia-laravel": "^2.0",
|
||||||
|
"laradumps/laradumps": "^4.2",
|
||||||
"laravel/fortify": "^1.17",
|
"laravel/fortify": "^1.17",
|
||||||
"laravel/framework": "^12.0",
|
"laravel/framework": "^12.0",
|
||||||
"laravel/sanctum": "^4.0",
|
"laravel/sanctum": "^4.0",
|
||||||
@ -25,7 +26,6 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"knuckleswtf/scribe": "^5.0",
|
"knuckleswtf/scribe": "^5.0",
|
||||||
"laradumps/laradumps": "^3.0",
|
|
||||||
"larastan/larastan": "^3.1",
|
"larastan/larastan": "^3.1",
|
||||||
"laravel/pint": "^1.10",
|
"laravel/pint": "^1.10",
|
||||||
"laravel/sail": "^1.18",
|
"laravel/sail": "^1.18",
|
||||||
|
553
composer.lock
generated
553
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "31d55d02539efe95d4e3447b817fcb00",
|
"content-hash": "436252e5b1fca532bfad2c3eb094374c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
@ -1377,6 +1377,147 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-04-10T15:08:36+00:00"
|
"time": "2025-04-10T15:08:36+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "laradumps/laradumps",
|
||||||
|
"version": "v4.2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/laradumps/laradumps.git",
|
||||||
|
"reference": "aca61f1088d30b2e879551343b34e2a788735fdf"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/laradumps/laradumps/zipball/aca61f1088d30b2e879551343b34e2a788735fdf",
|
||||||
|
"reference": "aca61f1088d30b2e879551343b34e2a788735fdf",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/mail": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||||
|
"laradumps/laradumps-core": "^3.2.2",
|
||||||
|
"nunomaduro/termwind": "^1.15.1|^2.0.1",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"larastan/larastan": "^2.0|^3.0",
|
||||||
|
"laravel/framework": "^10.0|^11.0|^12.0",
|
||||||
|
"laravel/pint": "^1.17.2",
|
||||||
|
"livewire/livewire": "^3.5.6",
|
||||||
|
"mockery/mockery": "^1.6.12",
|
||||||
|
"orchestra/testbench-core": "^8.0|^9.4|^10.0",
|
||||||
|
"pestphp/pest": "^2.35.1|^3.7.0",
|
||||||
|
"symfony/var-dumper": "^6.4.0|^7.1.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"LaraDumps\\LaraDumps\\LaraDumpsServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"LaraDumps\\LaraDumps\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Luan Freitas",
|
||||||
|
"email": "luanfreitas10@protonmail.com",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "LaraDumps is a friendly app designed to boost your Laravel PHP coding and debugging experience.",
|
||||||
|
"homepage": "https://github.com/laradumps/laradumps",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/laradumps/laradumps/issues",
|
||||||
|
"source": "https://github.com/laradumps/laradumps/tree/v4.2.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/luanfreitasdev",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-04-26T13:47:50+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laradumps/laradumps-core",
|
||||||
|
"version": "v3.2.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/laradumps/laradumps-core.git",
|
||||||
|
"reference": "eb0e15805ac4061a524c43ed7c1e7796ef3326d8"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/laradumps/laradumps-core/zipball/eb0e15805ac4061a524c43ed7c1e7796ef3326d8",
|
||||||
|
"reference": "eb0e15805ac4061a524c43ed7c1e7796ef3326d8",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-curl": "*",
|
||||||
|
"nunomaduro/termwind": "^1.15|^2.0",
|
||||||
|
"php": "^8.1",
|
||||||
|
"ramsey/uuid": "^4.7.5",
|
||||||
|
"spatie/backtrace": "^1.5",
|
||||||
|
"symfony/console": "^5.4|^6.4|^7.0",
|
||||||
|
"symfony/finder": "^5.4|^6.4|^7.0",
|
||||||
|
"symfony/process": "^5.4|^6.4|^7.0",
|
||||||
|
"symfony/var-dumper": "^5.4|^6.4|^7.0",
|
||||||
|
"symfony/yaml": "^5.4|^6.4|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"illuminate/support": "^10.46",
|
||||||
|
"laravel/pint": "^1.13.7",
|
||||||
|
"pestphp/pest": "^2.0|^3.0",
|
||||||
|
"phpstan/phpstan": "^1.10.50"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/laradumps"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"LaraDumps\\LaraDumpsCore\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Luan Freitas",
|
||||||
|
"email": "luanfreitas10@protonmail.com",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "LaraDumps is a friendly app designed to boost your Laravel / PHP coding and debugging experience.",
|
||||||
|
"homepage": "https://github.com/laradumps/laradumps-core",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/laradumps/laradumps-core/issues",
|
||||||
|
"source": "https://github.com/laradumps/laradumps-core/tree/v3.2.4"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/luanfreitasdev",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-05-16T14:48:30+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/fortify",
|
"name": "laravel/fortify",
|
||||||
"version": "v1.25.4",
|
"version": "v1.25.4",
|
||||||
@ -4197,6 +4338,69 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-04-27T21:32:50+00:00"
|
"time": "2024-04-27T21:32:50+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/backtrace",
|
||||||
|
"version": "1.7.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/backtrace.git",
|
||||||
|
"reference": "9807de6b8fecfaa5b3d10650985f0348b02862b2"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/backtrace/zipball/9807de6b8fecfaa5b3d10650985f0348b02862b2",
|
||||||
|
"reference": "9807de6b8fecfaa5b3d10650985f0348b02862b2",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.3 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"laravel/serializable-closure": "^1.3 || ^2.0",
|
||||||
|
"phpunit/phpunit": "^9.3 || ^11.4.3",
|
||||||
|
"spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1.6",
|
||||||
|
"symfony/var-dumper": "^5.1 || ^6.0 || ^7.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\Backtrace\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van de Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A better backtrace",
|
||||||
|
"homepage": "https://github.com/spatie/backtrace",
|
||||||
|
"keywords": [
|
||||||
|
"Backtrace",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/spatie/backtrace/tree/1.7.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/sponsors/spatie",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "other"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-04-28T14:55:53+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/laravel-route-attributes",
|
"name": "spatie/laravel-route-attributes",
|
||||||
"version": "1.25.2",
|
"version": "1.25.2",
|
||||||
@ -6497,6 +6701,78 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-04-09T08:14:01+00:00"
|
"time": "2025-04-09T08:14:01+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/yaml",
|
||||||
|
"version": "v7.2.6",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
|
"reference": "0feafffb843860624ddfd13478f481f4c3cd8b23"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/0feafffb843860624ddfd13478f481f4c3cd8b23",
|
||||||
|
"reference": "0feafffb843860624ddfd13478f481f4c3cd8b23",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3.0",
|
||||||
|
"symfony/polyfill-ctype": "^1.8"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/console": "<6.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/console": "^6.4|^7.0"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"Resources/bin/yaml-lint"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Yaml\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Loads and dumps YAML files",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/yaml/tree/v7.2.6"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-04-04T10:10:11+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "tightenco/ziggy",
|
"name": "tightenco/ziggy",
|
||||||
"version": "v2.5.2",
|
"version": "v2.5.2",
|
||||||
@ -7210,146 +7486,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-05-01T01:14:54+00:00"
|
"time": "2025-05-01T01:14:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "laradumps/laradumps",
|
|
||||||
"version": "v3.5.3",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/laradumps/laradumps.git",
|
|
||||||
"reference": "bbea350754afdf29dc375e1ffa798120238b1cda"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/laradumps/laradumps/zipball/bbea350754afdf29dc375e1ffa798120238b1cda",
|
|
||||||
"reference": "bbea350754afdf29dc375e1ffa798120238b1cda",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"illuminate/mail": "^10.0|^11.0|^12.0",
|
|
||||||
"illuminate/support": "^10.0|^11.0|^12.0",
|
|
||||||
"laradumps/laradumps-core": ">2.4 <3.0",
|
|
||||||
"nunomaduro/termwind": "^1.15.1|^2.0.1",
|
|
||||||
"php": "^8.1"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"laravel/framework": "^12.0",
|
|
||||||
"laravel/pint": "^1.17.2",
|
|
||||||
"livewire/livewire": "^3.5.6",
|
|
||||||
"mockery/mockery": "^1.6.12",
|
|
||||||
"orchestra/testbench-core": "10.0",
|
|
||||||
"pestphp/pest": "^2.35.1|^3.0",
|
|
||||||
"symfony/var-dumper": "^6.4.0|^7.1.3"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"providers": [
|
|
||||||
"LaraDumps\\LaraDumps\\LaraDumpsServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/functions.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"LaraDumps\\LaraDumps\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Luan Freitas",
|
|
||||||
"email": "luanfreitas10@protonmail.com",
|
|
||||||
"role": "Developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "LaraDumps is a friendly app designed to boost your Laravel PHP coding and debugging experience.",
|
|
||||||
"homepage": "https://github.com/laradumps/laradumps",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/laradumps/laradumps/issues",
|
|
||||||
"source": "https://github.com/laradumps/laradumps/tree/v3.5.3"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/luanfreitasdev",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-03-27T16:43:05+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "laradumps/laradumps-core",
|
|
||||||
"version": "v2.4.5",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/laradumps/laradumps-core.git",
|
|
||||||
"reference": "b1f083e84e9275026a21ca6effa219dd16cce20a"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/laradumps/laradumps-core/zipball/b1f083e84e9275026a21ca6effa219dd16cce20a",
|
|
||||||
"reference": "b1f083e84e9275026a21ca6effa219dd16cce20a",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-curl": "*",
|
|
||||||
"nunomaduro/termwind": "^1.15|^2.0",
|
|
||||||
"php": "^8.1",
|
|
||||||
"ramsey/uuid": "^4.7.5",
|
|
||||||
"spatie/backtrace": "^1.5",
|
|
||||||
"symfony/console": "^5.4|^6.4|^7.0",
|
|
||||||
"symfony/finder": "^5.4|^6.4|^7.0",
|
|
||||||
"symfony/process": "^5.4|^6.4|^7.0",
|
|
||||||
"symfony/var-dumper": "^5.4|^6.4|^7.0",
|
|
||||||
"symfony/yaml": "^5.4|^6.4|^7.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"illuminate/support": "^10.43",
|
|
||||||
"laravel/pint": "^1.13.7",
|
|
||||||
"pestphp/pest": "^2.28.1",
|
|
||||||
"phpstan/phpstan": "^1.10.50"
|
|
||||||
},
|
|
||||||
"bin": [
|
|
||||||
"bin/laradumps"
|
|
||||||
],
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"src/functions.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
|
||||||
"LaraDumps\\LaraDumpsCore\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Luan Freitas",
|
|
||||||
"email": "luanfreitas10@protonmail.com",
|
|
||||||
"role": "Developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "LaraDumps is a friendly app designed to boost your Laravel / PHP coding and debugging experience.",
|
|
||||||
"homepage": "https://github.com/laradumps/laradumps-core",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/laradumps/laradumps-core/issues",
|
|
||||||
"source": "https://github.com/laradumps/laradumps-core/tree/v2.4.5"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/luanfreitasdev",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-01-16T16:25:50+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "larastan/larastan",
|
"name": "larastan/larastan",
|
||||||
"version": "v3.4.0",
|
"version": "v3.4.0",
|
||||||
@ -9561,69 +9697,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-20T11:51:46+00:00"
|
"time": "2024-02-20T11:51:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "spatie/backtrace",
|
|
||||||
"version": "1.7.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/spatie/backtrace.git",
|
|
||||||
"reference": "9807de6b8fecfaa5b3d10650985f0348b02862b2"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/spatie/backtrace/zipball/9807de6b8fecfaa5b3d10650985f0348b02862b2",
|
|
||||||
"reference": "9807de6b8fecfaa5b3d10650985f0348b02862b2",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.3 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"ext-json": "*",
|
|
||||||
"laravel/serializable-closure": "^1.3 || ^2.0",
|
|
||||||
"phpunit/phpunit": "^9.3 || ^11.4.3",
|
|
||||||
"spatie/phpunit-snapshot-assertions": "^4.2 || ^5.1.6",
|
|
||||||
"symfony/var-dumper": "^5.1 || ^6.0 || ^7.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Spatie\\Backtrace\\": "src"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Freek Van de Herten",
|
|
||||||
"email": "freek@spatie.be",
|
|
||||||
"homepage": "https://spatie.be",
|
|
||||||
"role": "Developer"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "A better backtrace",
|
|
||||||
"homepage": "https://github.com/spatie/backtrace",
|
|
||||||
"keywords": [
|
|
||||||
"Backtrace",
|
|
||||||
"spatie"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/spatie/backtrace/tree/1.7.2"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/sponsors/spatie",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://spatie.be/open-source/support-us",
|
|
||||||
"type": "other"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-04-28T14:55:53+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "spatie/data-transfer-object",
|
"name": "spatie/data-transfer-object",
|
||||||
"version": "3.9.1",
|
"version": "3.9.1",
|
||||||
@ -10133,78 +10206,6 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-05-02T08:36:00+00:00"
|
"time": "2025-05-02T08:36:00+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "symfony/yaml",
|
|
||||||
"version": "v7.2.6",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
|
||||||
"reference": "0feafffb843860624ddfd13478f481f4c3cd8b23"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/0feafffb843860624ddfd13478f481f4c3cd8b23",
|
|
||||||
"reference": "0feafffb843860624ddfd13478f481f4c3cd8b23",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=8.2",
|
|
||||||
"symfony/deprecation-contracts": "^2.5|^3.0",
|
|
||||||
"symfony/polyfill-ctype": "^1.8"
|
|
||||||
},
|
|
||||||
"conflict": {
|
|
||||||
"symfony/console": "<6.4"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"symfony/console": "^6.4|^7.0"
|
|
||||||
},
|
|
||||||
"bin": [
|
|
||||||
"Resources/bin/yaml-lint"
|
|
||||||
],
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Symfony\\Component\\Yaml\\": ""
|
|
||||||
},
|
|
||||||
"exclude-from-classmap": [
|
|
||||||
"/Tests/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Symfony Community",
|
|
||||||
"homepage": "https://symfony.com/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Loads and dumps YAML files",
|
|
||||||
"homepage": "https://symfony.com",
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/symfony/yaml/tree/v7.2.6"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://symfony.com/sponsor",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/fabpot",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2025-04-04T10:10:11+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
|
@ -462,6 +462,11 @@
|
|||||||
'gitlab' => \App\SourceControlProviders\Gitlab::class,
|
'gitlab' => \App\SourceControlProviders\Gitlab::class,
|
||||||
'bitbucket' => \App\SourceControlProviders\Bitbucket::class,
|
'bitbucket' => \App\SourceControlProviders\Bitbucket::class,
|
||||||
],
|
],
|
||||||
|
'source_control_providers_custom_fields' => [
|
||||||
|
\App\Enums\SourceControl::GITHUB => ['token'],
|
||||||
|
\App\Enums\SourceControl::GITLAB => ['token', 'url'],
|
||||||
|
\App\Enums\SourceControl::BITBUCKET => ['username', 'password'],
|
||||||
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* available php extensions
|
* available php extensions
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { type BreadcrumbItem, type NavItem } from '@/types';
|
import { type BreadcrumbItem, type NavItem } from '@/types';
|
||||||
import { CloudIcon, ListIcon, UserIcon, UsersIcon } from 'lucide-react';
|
import { CloudIcon, CodeIcon, ListIcon, UserIcon, UsersIcon } from 'lucide-react';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import Layout from '@/layouts/app/layout';
|
import Layout from '@/layouts/app/layout';
|
||||||
|
|
||||||
@ -24,6 +24,11 @@ const sidebarNavItems: NavItem[] = [
|
|||||||
href: route('server-providers'),
|
href: route('server-providers'),
|
||||||
icon: CloudIcon,
|
icon: CloudIcon,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Source Controls',
|
||||||
|
href: route('source-controls'),
|
||||||
|
icon: CodeIcon,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function SettingsLayout({ children, breadcrumbs }: { children: ReactNode; breadcrumbs?: BreadcrumbItem[] }) {
|
export default function SettingsLayout({ children, breadcrumbs }: { children: ReactNode; breadcrumbs?: BreadcrumbItem[] }) {
|
||||||
|
185
resources/js/pages/source-controls/components/columns.tsx
Normal file
185
resources/js/pages/source-controls/components/columns.tsx
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
import DateTime from '@/components/date-time';
|
||||||
|
import { SourceControl } from '@/types/source-control';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { useForm } from '@inertiajs/react';
|
||||||
|
import { LoaderCircleIcon, MoreVerticalIcon } from 'lucide-react';
|
||||||
|
import FormSuccessful from '@/components/form-successful';
|
||||||
|
import { FormEvent, useState } from 'react';
|
||||||
|
import InputError from '@/components/ui/input-error';
|
||||||
|
import { Form, FormField, FormFields } from '@/components/ui/form';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
|
|
||||||
|
function Edit({ sourceControl }: { sourceControl: SourceControl }) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const form = useForm({
|
||||||
|
name: sourceControl.name,
|
||||||
|
global: sourceControl.global,
|
||||||
|
});
|
||||||
|
|
||||||
|
const submit = (e: FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
form.patch(route('source-controls.update', sourceControl.id));
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<DropdownMenuItem onSelect={(e) => e.preventDefault()}>Edit</DropdownMenuItem>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Edit {sourceControl.name}</DialogTitle>
|
||||||
|
<DialogDescription className="sr-only">Edit source control</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Form id="edit-source-control-form" className="p-4" onSubmit={submit}>
|
||||||
|
<FormFields>
|
||||||
|
<FormField>
|
||||||
|
<Label htmlFor="name">Name</Label>
|
||||||
|
<Input type="text" id="name" name="name" value={form.data.name} onChange={(e) => form.setData('name', e.target.value)} />
|
||||||
|
<InputError message={form.errors.name} />
|
||||||
|
</FormField>
|
||||||
|
<FormField>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<Checkbox id="global" name="global" checked={form.data.global} onClick={() => form.setData('global', !form.data.global)} />
|
||||||
|
<Label htmlFor="global">Is global (accessible in all projects)</Label>
|
||||||
|
</div>
|
||||||
|
<InputError message={form.errors.global} />
|
||||||
|
</FormField>
|
||||||
|
</FormFields>
|
||||||
|
</Form>
|
||||||
|
<DialogFooter>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button variant="outline">Cancel</Button>
|
||||||
|
</DialogClose>
|
||||||
|
<Button form="edit-source-control-form" disabled={form.processing} onClick={submit}>
|
||||||
|
{form.processing && <LoaderCircleIcon className="animate-spin" />}
|
||||||
|
<FormSuccessful successful={form.recentlySuccessful} />
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Delete({ sourceControl }: { sourceControl: SourceControl }) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const form = useForm();
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
form.delete(route('source-controls.destroy', sourceControl.id), {
|
||||||
|
onSuccess: () => {
|
||||||
|
setOpen(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<DropdownMenuItem variant="destructive" onSelect={(e) => e.preventDefault()}>
|
||||||
|
Delete
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Delete {sourceControl.name}</DialogTitle>
|
||||||
|
<DialogDescription className="sr-only">Delete source control</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="space-y-2 p-4">
|
||||||
|
<p>
|
||||||
|
Are you sure you want to delete <strong>{sourceControl.name}</strong>?
|
||||||
|
</p>
|
||||||
|
<InputError message={form.errors.provider} />
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button variant="outline">Cancel</Button>
|
||||||
|
</DialogClose>
|
||||||
|
<Button variant="destructive" disabled={form.processing} onClick={submit}>
|
||||||
|
{form.processing && <LoaderCircleIcon className="animate-spin" />}
|
||||||
|
<FormSuccessful successful={form.recentlySuccessful} />
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const columns: ColumnDef<SourceControl>[] = [
|
||||||
|
{
|
||||||
|
accessorKey: 'id',
|
||||||
|
header: 'ID',
|
||||||
|
enableColumnFilter: true,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'provider',
|
||||||
|
header: 'Provider',
|
||||||
|
enableColumnFilter: true,
|
||||||
|
enableSorting: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'name',
|
||||||
|
header: 'Name',
|
||||||
|
enableColumnFilter: true,
|
||||||
|
enableSorting: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'global',
|
||||||
|
header: 'Global',
|
||||||
|
enableColumnFilter: true,
|
||||||
|
enableSorting: true,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return <div>{row.original.global ? <Badge variant="success">yes</Badge> : <Badge variant="danger">no</Badge>}</div>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'created_at',
|
||||||
|
header: 'Created at',
|
||||||
|
enableColumnFilter: true,
|
||||||
|
enableSorting: true,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return <DateTime date={row.original.created_at} />;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-end">
|
||||||
|
<DropdownMenu modal={false}>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||||
|
<span className="sr-only">Open menu</span>
|
||||||
|
<MoreVerticalIcon />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<Edit sourceControl={row.original} />
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<Delete sourceControl={row.original} />
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -0,0 +1,150 @@
|
|||||||
|
import { LoaderCircle } from 'lucide-react';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { useForm, usePage } from '@inertiajs/react';
|
||||||
|
import { FormEventHandler, ReactNode, useEffect, useState } from 'react';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
|
import InputError from '@/components/ui/input-error';
|
||||||
|
import { Form, FormField, FormFields } from '@/components/ui/form';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { SharedData } from '@/types';
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
|
|
||||||
|
type SourceControlForm = {
|
||||||
|
provider: string;
|
||||||
|
name: string;
|
||||||
|
global: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ConnectSourceControl({
|
||||||
|
providers,
|
||||||
|
defaultProvider,
|
||||||
|
onProviderAdded,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
providers: string[];
|
||||||
|
defaultProvider?: string;
|
||||||
|
onProviderAdded?: () => void;
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const page = usePage<SharedData>();
|
||||||
|
|
||||||
|
const form = useForm<Required<SourceControlForm>>({
|
||||||
|
provider: 'github',
|
||||||
|
name: '',
|
||||||
|
global: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const submit: FormEventHandler = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
form.post(route('source-controls.store'), {
|
||||||
|
onSuccess: () => {
|
||||||
|
setOpen(false);
|
||||||
|
if (onProviderAdded) {
|
||||||
|
onProviderAdded();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.setData('provider', defaultProvider ?? 'github');
|
||||||
|
}, [defaultProvider]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Connect to source control</DialogTitle>
|
||||||
|
<DialogDescription className="sr-only">Connect to a new source control</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<Form id="create-source-control-form" onSubmit={submit} className="p-4">
|
||||||
|
<FormFields>
|
||||||
|
<FormField>
|
||||||
|
<Label htmlFor="provider">Provider</Label>
|
||||||
|
<Select
|
||||||
|
value={form.data.provider}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
form.setData('provider', value);
|
||||||
|
form.clearErrors();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger id="provider">
|
||||||
|
<SelectValue placeholder="Select a provider" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
{providers.map((provider) => (
|
||||||
|
<SelectItem key={provider} value={provider}>
|
||||||
|
{provider}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<InputError message={form.errors.provider} />
|
||||||
|
</FormField>
|
||||||
|
<FormField>
|
||||||
|
<Label htmlFor="name">Name</Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
id="name"
|
||||||
|
placeholder="Name"
|
||||||
|
value={form.data.name}
|
||||||
|
onChange={(e) => form.setData('name', e.target.value)}
|
||||||
|
/>
|
||||||
|
<InputError message={form.errors.name} />
|
||||||
|
</FormField>
|
||||||
|
{page.props.configs.source_control_providers_custom_fields[form.data.provider]?.map((item: string) => (
|
||||||
|
<FormField key={item}>
|
||||||
|
<Label htmlFor={item} className="capitalize">
|
||||||
|
{item}
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
name={item}
|
||||||
|
id={item}
|
||||||
|
value={(form.data[item as keyof SourceControlForm] as string) ?? ''}
|
||||||
|
onChange={(e) => form.setData(item as keyof SourceControlForm, e.target.value)}
|
||||||
|
/>
|
||||||
|
<InputError message={form.errors[item as keyof SourceControlForm]} />
|
||||||
|
</FormField>
|
||||||
|
))}
|
||||||
|
<FormField>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<Checkbox id="global" name="global" checked={form.data.global} onClick={() => form.setData('global', !form.data.global)} />
|
||||||
|
<Label htmlFor="global">Is global (accessible in all projects)</Label>
|
||||||
|
</div>
|
||||||
|
<InputError message={form.errors.global} />
|
||||||
|
</FormField>
|
||||||
|
</FormFields>
|
||||||
|
</Form>
|
||||||
|
<DialogFooter>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button type="button" variant="outline">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</DialogClose>
|
||||||
|
<Button type="button" onClick={submit} disabled={form.processing}>
|
||||||
|
{form.processing && <LoaderCircle className="animate-spin" />}
|
||||||
|
Connect
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
39
resources/js/pages/source-controls/index.tsx
Normal file
39
resources/js/pages/source-controls/index.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import SettingsLayout from '@/layouts/settings/layout';
|
||||||
|
import { Head, usePage } from '@inertiajs/react';
|
||||||
|
import Container from '@/components/container';
|
||||||
|
import Heading from '@/components/heading';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import React from 'react';
|
||||||
|
import ConnectSourceControl from '@/pages/source-controls/components/connect-source-control';
|
||||||
|
import { DataTable } from '@/components/data-table';
|
||||||
|
import { columns } from '@/pages/source-controls/components/columns';
|
||||||
|
import { SourceControl } from '@/types/source-control';
|
||||||
|
import { Configs } from '@/types';
|
||||||
|
|
||||||
|
type Page = {
|
||||||
|
sourceControls: {
|
||||||
|
data: SourceControl[];
|
||||||
|
};
|
||||||
|
configs: Configs;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SourceControls() {
|
||||||
|
const page = usePage<Page>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsLayout>
|
||||||
|
<Head title="Source Controls" />
|
||||||
|
<Container className="max-w-5xl">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<Heading title="Source Controls" description="Here you can manage all of the source control connectinos" />
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<ConnectSourceControl providers={page.props.configs.source_control_providers}>
|
||||||
|
<Button>Connect</Button>
|
||||||
|
</ConnectSourceControl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DataTable columns={columns} data={page.props.sourceControls.data} />
|
||||||
|
</Container>
|
||||||
|
</SettingsLayout>
|
||||||
|
);
|
||||||
|
}
|
4
resources/js/types/index.d.ts
vendored
4
resources/js/types/index.d.ts
vendored
@ -33,6 +33,10 @@ export interface Configs {
|
|||||||
server_providers_custom_fields: {
|
server_providers_custom_fields: {
|
||||||
[provider: string]: string[];
|
[provider: string]: string[];
|
||||||
};
|
};
|
||||||
|
source_control_providers: string[];
|
||||||
|
source_control_providers_custom_fields: {
|
||||||
|
[provider: string]: string[];
|
||||||
|
};
|
||||||
operating_systems: string[];
|
operating_systems: string[];
|
||||||
service_versions: {
|
service_versions: {
|
||||||
[service: string]: string[];
|
[service: string]: string[];
|
||||||
|
11
resources/js/types/source-control.d.ts
vendored
Normal file
11
resources/js/types/source-control.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface SourceControl {
|
||||||
|
id: number;
|
||||||
|
project_id?: number;
|
||||||
|
global: boolean;
|
||||||
|
name: string;
|
||||||
|
provider: string;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
@ -3,11 +3,8 @@
|
|||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
use App\Web\Pages\Settings\SourceControls\Index;
|
|
||||||
use App\Web\Pages\Settings\SourceControls\Widgets\SourceControlsList;
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Livewire\Livewire;
|
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class SourceControlsTest extends TestCase
|
class SourceControlsTest extends TestCase
|
||||||
@ -15,6 +12,8 @@ class SourceControlsTest extends TestCase
|
|||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param array<string, mixed> $input
|
||||||
|
*
|
||||||
* @dataProvider data
|
* @dataProvider data
|
||||||
*/
|
*/
|
||||||
public function test_connect_provider(string $provider, ?string $customUrl, array $input): void
|
public function test_connect_provider(string $provider, ?string $customUrl, array $input): void
|
||||||
@ -32,9 +31,7 @@ public function test_connect_provider(string $provider, ?string $customUrl, arra
|
|||||||
$input['url'] = $customUrl;
|
$input['url'] = $customUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Livewire::test(Index::class)
|
$this->post(route('source-controls.store'), $input);
|
||||||
->callAction('connect', $input)
|
|
||||||
->assertSuccessful();
|
|
||||||
|
|
||||||
$this->assertDatabaseHas('source_controls', [
|
$this->assertDatabaseHas('source_controls', [
|
||||||
'provider' => $provider,
|
'provider' => $provider,
|
||||||
@ -69,9 +66,9 @@ public function test_delete_provider(string $provider): void
|
|||||||
'profile' => 'test',
|
'profile' => 'test',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(SourceControlsList::class)
|
$this->delete(route('source-controls.destroy', $sourceControl))
|
||||||
->callTableAction('delete', $sourceControl->id)
|
->assertSessionDoesntHaveErrors()
|
||||||
->assertSuccessful();
|
->assertRedirect(route('source-controls'));
|
||||||
|
|
||||||
$this->assertSoftDeleted('source_controls', [
|
$this->assertSoftDeleted('source_controls', [
|
||||||
'id' => $sourceControl->id,
|
'id' => $sourceControl->id,
|
||||||
@ -95,9 +92,10 @@ public function test_cannot_delete_provider(string $provider): void
|
|||||||
'source_control_id' => $sourceControl->id,
|
'source_control_id' => $sourceControl->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(SourceControlsList::class)
|
$this->delete(route('source-controls.destroy', $sourceControl))
|
||||||
->callTableAction('delete', $sourceControl->id)
|
->assertSessionHasErrors([
|
||||||
->assertNotified('This source control is being used by a site.');
|
'source_control' => 'This source control is being used by a site.',
|
||||||
|
]);
|
||||||
|
|
||||||
$this->assertNotSoftDeleted('source_controls', [
|
$this->assertNotSoftDeleted('source_controls', [
|
||||||
'id' => $sourceControl->id,
|
'id' => $sourceControl->id,
|
||||||
@ -105,6 +103,8 @@ public function test_cannot_delete_provider(string $provider): void
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param array<string, mixed> $input
|
||||||
|
*
|
||||||
* @dataProvider data
|
* @dataProvider data
|
||||||
*/
|
*/
|
||||||
public function test_edit_source_control(string $provider, ?string $url, array $input): void
|
public function test_edit_source_control(string $provider, ?string $url, array $input): void
|
||||||
@ -120,15 +120,10 @@ public function test_edit_source_control(string $provider, ?string $url, array $
|
|||||||
'url' => $url,
|
'url' => $url,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(SourceControlsList::class)
|
$input['name'] = 'new-name';
|
||||||
->callTableAction('edit', $sourceControl->id, [
|
|
||||||
'name' => 'new-name',
|
$this->patch(route('source-controls.update', $sourceControl), $input)
|
||||||
'token' => 'test', // for GitHub and Gitlab
|
->assertSessionDoesntHaveErrors();
|
||||||
'username' => 'test', // for Bitbucket
|
|
||||||
'password' => 'test', // for Bitbucket
|
|
||||||
'url' => $url, // for Gitlab
|
|
||||||
])
|
|
||||||
->assertSuccessful();
|
|
||||||
|
|
||||||
$sourceControl->refresh();
|
$sourceControl->refresh();
|
||||||
|
|
||||||
@ -136,6 +131,9 @@ public function test_edit_source_control(string $provider, ?string $url, array $
|
|||||||
$this->assertEquals($url, $sourceControl->url);
|
$this->assertEquals($url, $sourceControl->url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
public static function data(): array
|
public static function data(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
Reference in New Issue
Block a user