184 lines
6.8 KiB
Plaintext
184 lines
6.8 KiB
Plaintext
---
|
|
import "../styles/global.css";
|
|
import Sidebar from "../components/SidebarAdd.astro";
|
|
|
|
const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL;
|
|
const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|
---
|
|
|
|
<html>
|
|
<head>
|
|
<title>Prompt Catalog - Add New Prompt</title>
|
|
</head>
|
|
|
|
<body class="font-sans antialiased bg-gray-800 text-gray-100">
|
|
<div
|
|
id="supabase-env"
|
|
data-url={supabaseUrl}
|
|
data-key={supabaseKey}
|
|
hidden
|
|
></div>
|
|
|
|
<div class="border-b p-4">
|
|
<h1 class="text-2xl font-bold">Prompt Catalog - Add New Prompt</h1>
|
|
<p class="text-sm mt-1">Add or import new AI prompts to the catalog</p>
|
|
</div>
|
|
|
|
<div class="flex h-screen">
|
|
<Sidebar />
|
|
|
|
<div class="flex-1 flex flex-col overflow-hidden">
|
|
<main class="flex-1 overflow-y-auto p-4">
|
|
<div id="success" class="bg-green-100 text-green-700 p-4 rounded mb-4 hidden">
|
|
Prompt added successfully!
|
|
</div>
|
|
<div id="error" class="bg-red-100 text-red-700 p-4 rounded mb-4 hidden"></div>
|
|
|
|
<form id="add-form" class="space-y-4">
|
|
<div>
|
|
<label for="title" class="block text-md font-semibold mb-1">Title<span class="text-red-600">*</span></label>
|
|
<input name="title" id="title" required class="border p-2 w-full rounded" />
|
|
<input type="hidden" name="slug" id="slug" />
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div>
|
|
<label for="type" class="block text-md font-semibold mb-1">Type<span class="text-red-600">*</span></label>
|
|
<select name="type" id="type" required class="border border-gray-100 p-2 rounded w-full bg-gray-800">
|
|
<option value="System">System</option>
|
|
<option value="Task">Task</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="tags" class="block text-md font-semibold mb-1">Tags (comma-separated)</label>
|
|
<input name="tags" id="tags" class="border p-2 pt-1 w-full rounded" />
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="description" class="block text-md font-semibold mb-1">Prompt<span class="text-red-600">*</span></label>
|
|
<textarea name="description" id="description" rows="6" required class="border p-2 w-full rounded"></textarea>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="notes" class="block text-md font-semibold mb-1">Description<span class="text-red-600">*</span></label>
|
|
<textarea name="notes" id="notes" rows="3" required class="border p-2 w-full rounded"></textarea>
|
|
</div>
|
|
|
|
<button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors duration-300 cursor-pointer">
|
|
Add Prompt
|
|
</button>
|
|
|
|
<hr class="my-6 border-gray-600" />
|
|
|
|
<div>
|
|
<label for="importFile" class="block text-md font-semibold mb-1">Import Prompts from JSON</label>
|
|
<input type="file" id="importFile" accept="application/json" class="border p-2 w-full rounded bg-gray-800 text-white" />
|
|
<button type="button" id="importBtn" class="mt-2 bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 transition-colors duration-300 cursor-pointer">
|
|
Import Prompts
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module">
|
|
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
|
|
|
|
const SUPABASE_URL = document.getElementById('supabase-env').dataset.url;
|
|
const SUPABASE_ANON_KEY = document.getElementById('supabase-env').dataset.key;
|
|
|
|
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const form = document.getElementById('add-form');
|
|
const successBox = document.getElementById('success');
|
|
const errorBox = document.getElementById('error');
|
|
|
|
document.getElementById('title').addEventListener('input', (e) => {
|
|
const value = e.target.value
|
|
.toLowerCase()
|
|
.replace(/[^\w\s-]/g, '')
|
|
.replace(/\s+/g, '-')
|
|
.trim();
|
|
document.getElementById('slug').value = value;
|
|
});
|
|
|
|
form.addEventListener('submit', async (e) => {
|
|
e.preventDefault();
|
|
|
|
successBox.style.display = 'none';
|
|
errorBox.style.display = 'none';
|
|
|
|
const formData = new FormData(form);
|
|
const payload = {
|
|
title: formData.get('title'),
|
|
slug: formData.get('slug'),
|
|
type: formData.get('type'),
|
|
description: formData.get('description'),
|
|
tags: formData.get('tags')?.split(',').map(t => t.trim()).filter(Boolean),
|
|
notes: formData.get('notes')
|
|
};
|
|
|
|
const { error } = await supabase.from('prompts').insert([payload]);
|
|
|
|
if (error) {
|
|
errorBox.innerText = error.message;
|
|
errorBox.style.display = 'block';
|
|
} else {
|
|
successBox.style.display = 'block';
|
|
form.reset();
|
|
}
|
|
});
|
|
});
|
|
|
|
document.getElementById('importBtn').addEventListener('click', async () => {
|
|
const fileInput = document.getElementById('importFile');
|
|
const file = fileInput.files[0];
|
|
|
|
if (!file) {
|
|
alert('Please select a JSON file.');
|
|
return;
|
|
}
|
|
|
|
const successBox = document.getElementById('success');
|
|
const errorBox = document.getElementById('error');
|
|
|
|
try {
|
|
const text = await file.text();
|
|
const prompts = JSON.parse(text);
|
|
|
|
const formatted = prompts.map(p => ({
|
|
type: p.type.charAt(0).toUpperCase() + p.type.slice(1), // normalize to "System"/"Task"
|
|
title: p.title,
|
|
description: p.description,
|
|
tags: p.tags.replace(/[{}"]/g, '').split(',').map(t => t.trim()), // parse tag string
|
|
notes: p.notes,
|
|
slug: p.title
|
|
.toLowerCase()
|
|
.replace(/[^\w\s-]/g, '')
|
|
.replace(/\s+/g, '-')
|
|
.trim()
|
|
}));
|
|
|
|
const { error } = await supabase.from('prompts').insert(formatted);
|
|
|
|
if (error) {
|
|
errorBox.innerText = `Import failed: ${error.message}`;
|
|
errorBox.style.display = 'block';
|
|
} else {
|
|
successBox.innerText = 'Prompts imported successfully!';
|
|
successBox.style.display = 'block';
|
|
fileInput.value = '';
|
|
}
|
|
} catch (err) {
|
|
errorBox.innerText = `Error: ${err.message}`;
|
|
errorBox.style.display = 'block';
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|