feat: add Integration Credentials CRUD and Deploy UI

Integration Credentials:
- Add IntegrationCredential model with encrypted payload
- Add full CRUD: ManageIntegrationCredentialsAction, 4 Tasks, Controller, Requests
- Add migration for integration_credentials table
- Add Vue pages: Index, Create, Edit
- AI tasks now read API keys from DB instead of .env
- Add sidebar menu item

Deploy UI:
- Add DeployTask with full deploy lifecycle management
- Extend DeployController with index, log, history endpoints
- Add Deploy/Index.vue with live polling and deploy log viewer
- Add sidebar menu item and QuickAction for Sveden

UI:
- Add 'key' icon to SidebarNavItem
- Change deploy button color to amber in Main.vue
This commit is contained in:
F4ilji
2026-07-02 01:03:13 +05:00
parent 09bba25993
commit 8364b220cc
21 changed files with 1191 additions and 16 deletions
@@ -0,0 +1,78 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\IntegrationCredentials\ManageIntegrationCredentialsAction;
use App\Containers\Dashboard\Models\IntegrationCredential;
use App\Containers\Dashboard\UI\WEB\Requests\StoreIntegrationCredentialRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateIntegrationCredentialRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
class IntegrationCredentialsController extends Controller
{
public function __construct(
private readonly ManageIntegrationCredentialsAction $action,
) {}
public function index(): \Inertia\Response
{
return Inertia::render('Dashboard/IntegrationCredentials/Index', [
'credentials' => $this->action->list(),
]);
}
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/IntegrationCredentials/Create');
}
public function store(StoreIntegrationCredentialRequest $request): RedirectResponse
{
try {
$this->action->create($request->validated());
return redirect()->route('dashboard.integration-credentials.index')
->with('success', 'Провайдер успешно добавлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении: ' . $e->getMessage());
}
}
public function edit(IntegrationCredential $credential): \Inertia\Response
{
return Inertia::render('Dashboard/IntegrationCredentials/Edit', [
'credential' => $credential,
]);
}
public function update(UpdateIntegrationCredentialRequest $request, IntegrationCredential $credential): RedirectResponse
{
try {
$this->action->update($credential, $request->validated());
return redirect()->route('dashboard.integration-credentials.index')
->with('success', 'Провайдер успешно обновлён!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении: ' . $e->getMessage());
}
}
public function destroy(IntegrationCredential $credential): RedirectResponse
{
try {
$this->action->delete($credential);
return redirect()->route('dashboard.integration-credentials.index')
->with('success', 'Провайдер успешно удалён!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении: ' . $e->getMessage());
}
}
}