From f4ab98a2b00f889c38318d7fe9908b32d73061a8 Mon Sep 17 00:00:00 2001 From: Julien Nahum Date: Sun, 26 Mar 2023 12:54:12 +0200 Subject: [PATCH] WIP --- app/Console/Commands/GenerateTemplate.php | 3 +- .../Controllers/Forms/AiFormController.php | 38 ++++++ app/Http/Requests/AiGenerateFormRequest.php | 20 +++ .../forms/create/CreateFormBaseModal.vue | 114 ++++++++++++++++++ resources/js/pages/forms/create.vue | 14 ++- resources/js/pages/welcome.vue | 5 +- resources/views/spa.blade.php | 1 + routes/api.php | 5 +- 8 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 app/Http/Controllers/Forms/AiFormController.php create mode 100644 app/Http/Requests/AiGenerateFormRequest.php create mode 100644 resources/js/components/pages/forms/create/CreateFormBaseModal.vue diff --git a/app/Console/Commands/GenerateTemplate.php b/app/Console/Commands/GenerateTemplate.php index f408553..c16e211 100644 --- a/app/Console/Commands/GenerateTemplate.php +++ b/app/Console/Commands/GenerateTemplate.php @@ -28,7 +28,7 @@ class GenerateTemplate extends Command I created a form builder. Forms are represented as Json objects. Here's an example form: ```json { - "title": "Contact Form", + "title": "Contact Us", "properties": [ { "help": null, @@ -219,7 +219,6 @@ class GenerateTemplate extends Command { $url = 'https://api.unsplash.com/search/photos?query=' . urlencode($searchQuery) . '&client_id=' . config('services.unslash.access_key'); $response = Http::get($url)->json(); - ray($response, $url); if (isset($response['results'][0]['urls']['regular'])) { return $response['results'][0]['urls']['regular']; } diff --git a/app/Http/Controllers/Forms/AiFormController.php b/app/Http/Controllers/Forms/AiFormController.php new file mode 100644 index 0000000..aa371fb --- /dev/null +++ b/app/Http/Controllers/Forms/AiFormController.php @@ -0,0 +1,38 @@ +middleware('throttle:4,1'); + $completer = (new GptCompleter(config('services.openai.api_key'))) + ->setSystemMessage('You are a robot helping to generate forms.'); + $completer->completeChat([ + ["role" => "user", "content" => Str::of(GenerateTemplate::FORM_STRUCTURE_PROMPT) + ->replace('[REPLACE]', $request->form_prompt)->toString()] + ], 3000); + + return $this->success([ + 'message' => 'Form successfully generated!', + 'form' => $this->cleanOutput($completer->getArray()) + ]); + } + + private function cleanOutput($formData) + { + // Add property uuids + foreach ($formData['properties'] as &$property) { + $property['id'] = Str::uuid()->toString(); + } + + return $formData; + } +} diff --git a/app/Http/Requests/AiGenerateFormRequest.php b/app/Http/Requests/AiGenerateFormRequest.php new file mode 100644 index 0000000..6aac735 --- /dev/null +++ b/app/Http/Requests/AiGenerateFormRequest.php @@ -0,0 +1,20 @@ + + */ + public function rules() + { + return [ + 'form_prompt' => 'required|string' + ]; + } +} diff --git a/resources/js/components/pages/forms/create/CreateFormBaseModal.vue b/resources/js/components/pages/forms/create/CreateFormBaseModal.vue new file mode 100644 index 0000000..3132028 --- /dev/null +++ b/resources/js/components/pages/forms/create/CreateFormBaseModal.vue @@ -0,0 +1,114 @@ + + + diff --git a/resources/js/pages/forms/create.vue b/resources/js/pages/forms/create.vue index 76c626c..ef21c5a 100644 --- a/resources/js/pages/forms/create.vue +++ b/resources/js/pages/forms/create.vue @@ -2,6 +2,8 @@
+ it's free.
- + + Create a form for FREE + + Create a form for FREE
diff --git a/resources/views/spa.blade.php b/resources/views/spa.blade.php index 7a369f2..f9dc12d 100644 --- a/resources/views/spa.blade.php +++ b/resources/views/spa.blade.php @@ -13,6 +13,7 @@ 'google_analytics_code' => config('services.google_analytics_code'), 'amplitude_code' => config('services.amplitude_code'), 'crisp_website_id' => config('services.crisp_website_id'), + 'ai_features_enabled' => !is_null(config('services.openai.api_key')) ]; @endphp diff --git a/routes/api.php b/routes/api.php index da24172..90968fe 100644 --- a/routes/api.php +++ b/routes/api.php @@ -144,6 +144,9 @@ Route::prefix('forms')->name('forms.')->group(function () { // File uploads Route::get('assets/{assetFileName}', [PublicFormController::class, 'showAsset'])->name('assets.show'); + + // AI + Route::post('ai/generate', [\App\Http\Controllers\Forms\AiFormController::class, 'generateForm'])->name('ai.generate'); }); /** @@ -155,4 +158,4 @@ Route::prefix('content')->name('content.')->group(function () { // Templates Route::get('templates', [TemplateController::class, 'index'])->name('templates.show'); -Route::post('templates', [TemplateController::class, 'create'])->name('templates.create'); \ No newline at end of file +Route::post('templates', [TemplateController::class, 'create'])->name('templates.create');