177 lines
9.3 KiB
PHP
Executable File
177 lines
9.3 KiB
PHP
Executable File
@extends('chatgpt::layouts.master')
|
|
|
|
@section('content')
|
|
<section class="mx-auto max-w-5xl space-y-6 p-6">
|
|
<div class="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
|
|
<div class="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
|
|
<div>
|
|
<h1 class="text-2xl font-semibold text-slate-900">ChatGPT API Settings</h1>
|
|
<p class="mt-1 text-sm text-slate-600">
|
|
Store the OpenAI API key used by the module command. Keys are encrypted at rest by Laravel.
|
|
</p>
|
|
</div>
|
|
|
|
<code class="rounded-lg bg-slate-100 px-3 py-2 text-sm text-slate-700">
|
|
php artisan chatgpt:delete-api-files
|
|
</code>
|
|
</div>
|
|
</div>
|
|
|
|
@if (session('status'))
|
|
<div class="rounded-xl border border-green-200 bg-green-50 px-4 py-3 text-sm font-medium text-green-800">
|
|
{{ session('status') }}
|
|
</div>
|
|
@endif
|
|
|
|
@if ($errors->any())
|
|
<div class="rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800">
|
|
<strong>Unable to save the API key.</strong>
|
|
<ul class="mt-2 list-disc pl-5">
|
|
@foreach ($errors->all() as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
|
|
<h2 class="text-lg font-semibold text-slate-900">Create API Key</h2>
|
|
|
|
<form method="POST" action="{{ route('chatgpt.settings.store') }}" class="mt-5 grid gap-4">
|
|
@csrf
|
|
|
|
<div>
|
|
<label for="name" class="block text-sm font-medium text-slate-700">Name</label>
|
|
<input
|
|
id="name"
|
|
name="name"
|
|
type="text"
|
|
value="{{ old('name', 'OpenAI API Key') }}"
|
|
class="mt-1 w-full rounded-lg border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
|
>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="api_key" class="block text-sm font-medium text-slate-700">API Key</label>
|
|
<input
|
|
id="api_key"
|
|
name="api_key"
|
|
type="password"
|
|
value=""
|
|
autocomplete="new-password"
|
|
required
|
|
class="mt-1 w-full rounded-lg border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
|
>
|
|
</div>
|
|
|
|
<label class="inline-flex items-center gap-2 text-sm text-slate-700">
|
|
<label for="sonar-input-a09f3b253f" class="visually-hidden">is active</label>
|
|
<input type="checkbox" name="is_active" value="1" checked class="rounded border-slate-300 text-blue-600 focus:ring-blue-500" id="sonar-input-a09f3b253f">
|
|
Make active key
|
|
</label>
|
|
|
|
<div>
|
|
<button type="submit" class="rounded-lg bg-blue-600 px-4 py-2 text-sm font-semibold text-white hover:bg-blue-700">
|
|
Save API Key
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
|
|
<h2 class="text-lg font-semibold text-slate-900">Stored API Keys</h2>
|
|
|
|
<div class="mt-5 overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-slate-200 text-sm">
|
|
<caption class="sr-only">Data table</caption>
|
|
<thead class="bg-slate-50 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">
|
|
<tr>
|
|
<th class="px-4 py-3">Name</th>
|
|
<th class="px-4 py-3">Key</th>
|
|
<th class="px-4 py-3">Active</th>
|
|
<th class="px-4 py-3">Updated</th>
|
|
<th class="px-4 py-3 text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100 bg-white">
|
|
@forelse ($settings as $setting)
|
|
<tr>
|
|
<td class="px-4 py-4 align-top font-medium text-slate-900">
|
|
<form id="setting-update-{{ $setting->id }}" method="POST" action="{{ route('chatgpt.settings.update', $setting) }}" class="grid gap-3">
|
|
@csrf
|
|
@method('PUT')
|
|
|
|
<label for="sonar-input-30f47d1294" class="visually-hidden">name</label>
|
|
<input
|
|
name="name"
|
|
type="text"
|
|
value="{{ old('name', $setting->name) }}"
|
|
class="w-full rounded-lg border-slate-300 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
|
id="name">
|
|
|
|
<label for="sonar-input-707eb8d2ba" class="visually-hidden">Leave blank to keep existing key</label>
|
|
<input
|
|
name="api_key"
|
|
type="password"
|
|
value=""
|
|
autocomplete="new-password"
|
|
placeholder="Leave blank to keep existing key"
|
|
class="w-full rounded-lg border-slate-300 text-sm shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
|
id="sonar-input-707eb8d2ba">
|
|
|
|
<label class="inline-flex items-center gap-2 text-xs text-slate-600">
|
|
<label for="sonar-input-da782f0360" class="visually-hidden">is active</label>
|
|
<input
|
|
type="checkbox"
|
|
name="is_active"
|
|
value="1"
|
|
@checked($setting->is_active)
|
|
class="rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
|
>
|
|
Active
|
|
</label>
|
|
</form>
|
|
</td>
|
|
<td class="px-4 py-4 align-top font-mono text-slate-700">{{ $setting->maskedApiKey() }}</td>
|
|
<td class="px-4 py-4 align-top">
|
|
@if ($setting->is_active)
|
|
<span class="rounded-full bg-green-100 px-2.5 py-1 text-xs font-semibold text-green-800">Yes</span>
|
|
@else
|
|
<span class="rounded-full bg-slate-100 px-2.5 py-1 text-xs font-semibold text-slate-600">No</span>
|
|
@endif
|
|
</td>
|
|
<td class="px-4 py-4 align-top text-slate-600">{{ $setting->updated_at?->format('d M Y H:i') }}</td>
|
|
<td class="px-4 py-4 align-top">
|
|
<div class="flex justify-end gap-2">
|
|
<button
|
|
type="submit"
|
|
form="setting-update-{{ $setting->id }}"
|
|
class="rounded-lg bg-blue-600 px-3 py-2 text-xs font-semibold text-white hover:bg-blue-700"
|
|
>
|
|
Update
|
|
</button>
|
|
|
|
<form method="POST" action="{{ route('chatgpt.settings.destroy', $setting) }}">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="rounded-lg bg-red-600 px-3 py-2 text-xs font-semibold text-white hover:bg-red-700">
|
|
Delete
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="5" class="px-4 py-8 text-center text-slate-500">
|
|
No API keys have been stored yet.
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
@endsection
|