Skip to content

Commit bcb3b9b

Browse files
authored
Merge pull request #7 from fluxdesk/dev
Removed installation GUI, added AI-integration (OpenAI/Claude)
2 parents 380c293 + 68a144f commit bcb3b9b

62 files changed

Lines changed: 4416 additions & 4959 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/Console/Commands/InstallCommand.php

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
class InstallCommand extends Command
2626
{
27-
protected $signature = 'app:install
27+
protected $signature = 'fluxdesk:install
2828
{--force : Force installation even if already installed}';
2929

3030
protected $description = 'Interactive installation wizard for FluxDesk';
@@ -53,6 +53,67 @@ public function handle(): int
5353
}
5454
}
5555

56+
// Ask if .env is already configured manually
57+
$manualEnv = confirm(
58+
label: 'Have you already configured the .env file manually?',
59+
default: false,
60+
hint: 'If yes, we\'ll skip environment setup and just run migrations'
61+
);
62+
63+
if ($manualEnv) {
64+
return $this->runManualEnvInstall();
65+
}
66+
67+
return $this->runGuidedInstall();
68+
}
69+
70+
/**
71+
* Run installation when .env is already configured manually.
72+
*/
73+
protected function runManualEnvInstall(): int
74+
{
75+
// Copy .env.example if .env doesn't exist
76+
if (! file_exists(base_path('.env'))) {
77+
error('.env file not found. Please create one first or run guided setup.');
78+
79+
return 1;
80+
}
81+
82+
info('Using existing .env configuration.');
83+
84+
// Test database connection
85+
if (! $this->testExistingDatabaseConnection()) {
86+
return 1;
87+
}
88+
89+
// Run migrations
90+
if (! $this->runMigrations()) {
91+
return 1;
92+
}
93+
94+
// Create admin user
95+
$this->createAdminUser();
96+
97+
// Mark as installed
98+
$this->envVariables['APP_INSTALLED'] = 'true';
99+
$this->writeEnvironmentFile();
100+
101+
// Build frontend assets
102+
$this->buildAssets();
103+
104+
outro('Installation complete!');
105+
106+
note('Start the development server with: composer run dev');
107+
note('Or for production, configure your web server to point to the public directory.');
108+
109+
return 0;
110+
}
111+
112+
/**
113+
* Run guided installation with full environment configuration.
114+
*/
115+
protected function runGuidedInstall(): int
116+
{
56117
// Copy .env.example if .env doesn't exist
57118
if (! file_exists(base_path('.env'))) {
58119
copy(base_path('.env.example'), base_path('.env'));
@@ -101,6 +162,33 @@ public function handle(): int
101162
return 0;
102163
}
103164

165+
/**
166+
* Test database connection using existing .env configuration.
167+
*/
168+
protected function testExistingDatabaseConnection(): bool
169+
{
170+
$result = spin(function () {
171+
try {
172+
$this->database->connection()->getPdo();
173+
174+
return true;
175+
} catch (\Exception $e) {
176+
return $e->getMessage();
177+
}
178+
}, 'Testing database connection...');
179+
180+
if ($result !== true) {
181+
error('Database connection failed: '.$result);
182+
warning('Please check your .env database configuration and try again.');
183+
184+
return false;
185+
}
186+
187+
info('Database connection successful.');
188+
189+
return true;
190+
}
191+
104192
protected function generateAppKey(): void
105193
{
106194
$key = config('app.key');
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Models\Ticket;
6+
use App\Services\AI\AIService;
7+
use App\Services\OrganizationContext;
8+
use Illuminate\Http\JsonResponse;
9+
use Illuminate\Http\Request;
10+
11+
class AIController extends Controller
12+
{
13+
public function __construct(
14+
private AIService $aiService,
15+
private OrganizationContext $organizationContext,
16+
) {}
17+
18+
/**
19+
* Generate suggested replies for a ticket.
20+
*/
21+
public function suggest(Request $request, Ticket $ticket): JsonResponse
22+
{
23+
$organization = $this->organizationContext->organization();
24+
25+
if (! $this->aiService->isConfigured($organization)) {
26+
return response()->json([
27+
'error' => 'AI is niet geconfigureerd. Configureer eerst een AI provider in de instellingen.',
28+
], 422);
29+
}
30+
31+
$settings = $organization->aiSettings;
32+
33+
if (! $settings->suggested_replies_enabled) {
34+
return response()->json([
35+
'error' => 'Suggesties zijn uitgeschakeld in de AI instellingen.',
36+
], 422);
37+
}
38+
39+
try {
40+
$suggestions = $this->aiService->suggestReplies(
41+
$ticket,
42+
count: 3,
43+
user: $request->user()
44+
);
45+
46+
return response()->json([
47+
'suggestions' => $suggestions,
48+
]);
49+
} catch (\Exception $e) {
50+
return response()->json([
51+
'error' => 'Kon geen suggesties genereren: '.$e->getMessage(),
52+
], 500);
53+
}
54+
}
55+
56+
/**
57+
* Refactor/improve reply text.
58+
*/
59+
public function refactor(Request $request): JsonResponse
60+
{
61+
$validated = $request->validate([
62+
'text' => ['required', 'string', 'min:10', 'max:10000'],
63+
'instructions' => ['nullable', 'string', 'max:500'],
64+
'ticket_id' => ['nullable', 'integer', 'exists:tickets,id'],
65+
]);
66+
67+
$organization = $this->organizationContext->organization();
68+
69+
if (! $this->aiService->isConfigured($organization)) {
70+
return response()->json([
71+
'error' => 'AI is niet geconfigureerd. Configureer eerst een AI provider in de instellingen.',
72+
], 422);
73+
}
74+
75+
$settings = $organization->aiSettings;
76+
77+
if (! $settings->reply_refactor_enabled) {
78+
return response()->json([
79+
'error' => 'Tekst verbeteren is uitgeschakeld in de AI instellingen.',
80+
], 422);
81+
}
82+
83+
$ticket = null;
84+
if (! empty($validated['ticket_id'])) {
85+
$ticket = Ticket::find($validated['ticket_id']);
86+
}
87+
88+
try {
89+
$refactored = $this->aiService->refactorReply(
90+
$validated['text'],
91+
$organization,
92+
$validated['instructions'] ?? null,
93+
$request->user(),
94+
$ticket
95+
);
96+
97+
return response()->json([
98+
'text' => $refactored,
99+
]);
100+
} catch (\Exception $e) {
101+
return response()->json([
102+
'error' => 'Kon tekst niet verbeteren: '.$e->getMessage(),
103+
], 500);
104+
}
105+
}
106+
107+
/**
108+
* Check if AI is configured and available.
109+
*/
110+
public function status(): JsonResponse
111+
{
112+
$organization = $this->organizationContext->organization();
113+
$settings = $organization->aiSettings;
114+
115+
return response()->json([
116+
'configured' => $this->aiService->isConfigured($organization),
117+
'suggested_replies_enabled' => $settings?->suggested_replies_enabled ?? false,
118+
'reply_refactor_enabled' => $settings?->reply_refactor_enabled ?? false,
119+
]);
120+
}
121+
}

0 commit comments

Comments
 (0)