Skip to content

Commit

Permalink
add the settings page now to make it work
Browse files Browse the repository at this point in the history
  • Loading branch information
alnutile committed Jun 11, 2024
1 parent 67d1513 commit bb56d58
Show file tree
Hide file tree
Showing 16 changed files with 711 additions and 6 deletions.
122 changes: 122 additions & 0 deletions app/Http/Controllers/SettingController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

namespace App\Http\Controllers;

use App\Http\Resources\SettingResource;
use App\Models\Setting;
use Illuminate\Http\Request;

class SettingController extends Controller
{
public function show()
{
if (! Setting::exists()) {
$setting = Setting::create([
'steps' => [
'setup_secrets' => false,
],
'meta_data' => [
'openai' => [
'models' => [],
],
],
'secrets' => [
'openai' => [
'api_key' => null,
'api_url' => 'https://api.openai.com/v1',
],
'claude' => [
'api_key' => null,
],
'groq' => [
'api_key' => null,
'api_url' => 'https://api.groq.com/openai/v1/',
],
'ollama' => [
'api_key' => 'ollama',
'api_url' => 'http://localhost:11434/api/',
],
],
]);
} else {
$setting = Setting::first();
}

return inertia('Settings/Show', [
'setting' => new SettingResource($setting),
]);
}

protected function updateStep(Setting $setting): Setting
{
$steps = $setting->steps;
$steps['setup_secrets'] = true;
$setting->steps = $steps;
$setting->save();

return $setting;
}

public function updateClaude(Request $request, Setting $setting)
{
$validated = $request->validate([
'api_key' => 'string|required',
]);

$secrets = $setting->secrets;
$secrets['claude'] = $validated;
$setting->secrets = $secrets;
$setting->save();
$this->updateStep($setting);

return back();
}

public function updateOllama(Request $request, Setting $setting)
{
$validated = $request->validate([
'api_key' => 'string|required',
'api_url' => 'string|required',
]);

$secrets = $setting->secrets;
$secrets['ollama'] = $validated;
$setting->secrets = $secrets;
$setting->save();
$this->updateStep($setting);

return back();
}

public function updateGroq(Request $request, Setting $setting)
{
$validated = $request->validate([
'api_key' => 'string|required',
'api_url' => 'string|required',
]);

$secrets = $setting->secrets;
$secrets['groq'] = $validated;
$setting->secrets = $secrets;
$setting->save();
$this->updateStep($setting);

return back();
}

public function updateOpenAi(Request $request, Setting $setting)
{
$validated = $request->validate([
'api_key' => 'string|required',
'api_url' => 'string|required',
]);

$secrets = $setting->secrets;
$secrets['openai'] = $validated;
$setting->secrets = $secrets;
$setting->save();
$this->updateStep($setting);

return back();
}
}
19 changes: 19 additions & 0 deletions app/Http/Resources/SettingResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class SettingResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}
25 changes: 25 additions & 0 deletions app/Models/Setting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Setting extends Model
{
use HasFactory;

protected $guarded = [];

protected $casts = [
'steps' => 'array',
'meta_data' => 'array',
'secrets' => 'encrypted:array',
];

public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
39 changes: 39 additions & 0 deletions database/factories/SettingFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Setting>
*/
class SettingFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'steps' => [
'setup_secrets' => false,
],
'meta_data' => [
'openai' => [
'models' => [
'completion_model' => 'gpt-3.5-turbo',
],
],
],
'secrets' => [
'openai' => [
'api_key' => 'foobar',
],
],
'user_id' => User::factory(),
];
}
}
31 changes: 31 additions & 0 deletions database/migrations/2024_06_11_183813_create_settings_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->json('steps')->nullable();
$table->json('meta_data')->nullable();
$table->longText('secrets')->nullable();
$table->foreignIdFor(\App\Models\User::class)->nullable();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('settings');
}
};
2 changes: 1 addition & 1 deletion resources/js/Components/ActionMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defineProps({
<template>
<div>
<transition leave-active-class="transition ease-in duration-1000" leave-from-class="opacity-100" leave-to-class="opacity-0">
<div v-show="on" class="text-sm text-gray-600">
<div v-show="on" class="text-sm ">
<slot />
</div>
</transition>
Expand Down
6 changes: 3 additions & 3 deletions resources/js/Components/FormSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const hasActions = computed(() => !! useSlots().actions);
</script>

<template>
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:grid md:grid-cols-3 md:gap-6 ">
<SectionTitle>
<template #title>
<slot name="title" />
Expand All @@ -21,15 +21,15 @@ const hasActions = computed(() => !! useSlots().actions);
<div class="mt-5 md:mt-0 md:col-span-2">
<form @submit.prevent="$emit('submitted')">
<div
class="px-4 py-5 bg-white sm:p-6 shadow"
class="px-4 py-5 sm:p-6 shadow"
:class="hasActions ? 'sm:rounded-tl-md sm:rounded-tr-md' : 'sm:rounded-md'"
>
<div class="grid grid-cols-6 gap-6">
<slot name="form" />
</div>
</div>

<div v-if="hasActions" class="flex items-center justify-end px-4 py-3 bg-gray-50 text-end sm:px-6 shadow sm:rounded-bl-md sm:rounded-br-md">
<div v-if="hasActions" class="flex items-center justify-end px-4 py-3 text-end sm:px-6 shadow sm:rounded-bl-md sm:rounded-br-md">
<slot name="actions" />
</div>
</form>
Expand Down
4 changes: 2 additions & 2 deletions resources/js/Components/SectionTitle.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<template>
<div class="md:col-span-1 flex justify-between">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium text-gray-900">
<h3 class="text-lg font-medium">
<slot name="title" />
</h3>

<p class="mt-1 text-sm text-gray-600">
<p class="mt-1 text-sm">
<slot name="description" />
</p>
</div>
Expand Down
75 changes: 75 additions & 0 deletions resources/js/Pages/Settings/Partials/ClaudeSecrets.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script setup>
import { ref } from 'vue';
import { Link, router, useForm } from '@inertiajs/vue3';
import ActionMessage from '@/Components/ActionMessage.vue';
import FormSection from '@/Components/FormSection.vue';
import InputError from '@/Components/InputError.vue';
import InputLabel from '@/Components/InputLabel.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import SecondaryButton from '@/Components/SecondaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
const props = defineProps({
setting: Object,
});
const form = useForm({
_method: 'PUT',
api_key: props.setting.secrets?.claude?.api_key,
});
const updateSecrets = () => {
form.put(route('settings.update.claude', {
setting: props.setting.id,
}), {
errorBag: 'updateProfileInformation',
preserveScroll: true,
});
};
</script>
<template>
<FormSection @submitted="updateSecrets">
<template #title>
Claude API Key and Token
</template>
<template #description>
If you want to use this service make sure to setup your API Token.
You can get your keys
<a
class="underline"
href="https://docs.anthropic.com/en/docs/intro-to-claude" target="_blank">here</a>
</template>
<template #form>
<!-- Name -->
<div class="col-span-6 sm:col-span-4">
<InputLabel for="name" value="Api Token" />
<TextInput
id="name"
v-model="form.api_key"
type="text"
class="mt-1 block w-full"
required
/>
<InputError :message="form.errors.api_key" class="mt-2" />
</div>
</template>
<template #actions>
<ActionMessage :on="form.recentlySuccessful" class="me-3">
Saved.
</ActionMessage>
<PrimaryButton :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Save
</PrimaryButton>
</template>
</FormSection>
</template>
Loading

0 comments on commit bb56d58

Please sign in to comment.