✨feature: Update layout to have footer, update export button for all/selected prompt export text
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
// TODO: Add options for AND/OR switching and sort by options
|
// TODO: Add options for AND/OR switching and sort by options
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="w-64 border-r h-full p-4 text-gray-100">
|
<div class="w-64 border-r h-full p-4 text-gray-100 min-h-screen">
|
||||||
<a href="/add" id="add-prompt" class="block w-fit bg-green-600 text-white px-4 py-2 mb-4 rounded hover:bg-green-700 transition-colors duration-300">
|
<a href="/add" id="add-prompt" class="block w-fit bg-green-600 text-white px-4 py-2 mb-4 rounded hover:bg-green-700 transition-colors duration-300">
|
||||||
Add Prompt
|
Add Prompt
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const code = `[
|
|||||||
`;
|
`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<aside class="w-64 border-r h-full p-4 text-gray-100">
|
<aside class="w-64 border-r h-full p-4 text-gray-100 min-h-screen">
|
||||||
<h2 class="text-lg font-semibold mb-4">Add a prompt</h2>
|
<h2 class="text-lg font-semibold mb-4">Add a prompt</h2>
|
||||||
|
|
||||||
<p class="text-sm">Use the form to add a new AI prompt to the catalog.</p>
|
<p class="text-sm">Use the form to add a new AI prompt to the catalog.</p>
|
||||||
|
|||||||
@@ -2,15 +2,11 @@
|
|||||||
// Sidebar.astro
|
// Sidebar.astro
|
||||||
---
|
---
|
||||||
|
|
||||||
<aside class="w-64 border-r h-full p-4 text-gray-100">
|
<aside class="w-64 border-r h-full p-4 text-gray-100 min-h-screen">
|
||||||
<h2 class="text-lg font-semibold mb-4">Edit a prompt</h2>
|
<h2 class="text-lg font-semibold mb-4">Edit a prompt</h2>
|
||||||
|
|
||||||
<p class="text-sm">Use the form to edit an AI prompt in the catalog.</p>
|
<p class="text-sm">Use the form to edit an AI prompt in the catalog.</p>
|
||||||
|
|
||||||
<!-- <p class="text-sm mt-2">Make sure to include a title, type, description, and any relevant tags.</p> -->
|
|
||||||
|
|
||||||
<!-- <p class="text-sm mt-2">You can also add notes for your own reference.</p> -->
|
|
||||||
|
|
||||||
<a href="/" id="home" class="block w-fit bg-green-600 text-white px-4 py-2 mt-4 rounded hover:bg-green-700 transition-colors duration-300">
|
<a href="/" id="home" class="block w-fit bg-green-600 text-white px-4 py-2 mt-4 rounded hover:bg-green-700 transition-colors duration-300">
|
||||||
Go Back
|
Go Back
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -19,16 +19,16 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
hidden
|
hidden
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div class="border-b p-4">
|
<header class="border-b p-4">
|
||||||
<h1 class="text-2xl font-bold">Prompt Catalog - Add New Prompt</h1>
|
<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>
|
<p class="text-sm mt-1">Add or import new AI prompts to the catalog</p>
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<div class="flex h-screen">
|
<main class="flex">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
||||||
<div class="flex-1 flex flex-col overflow-hidden">
|
<div class="flex-1 flex flex-col overflow-hidden">
|
||||||
<main class="flex-1 overflow-y-auto p-4">
|
<div class="flex-1 overflow-y-auto p-4">
|
||||||
<div id="success" class="bg-green-100 text-green-700 p-4 rounded mb-4 hidden">
|
<div id="success" class="bg-green-100 text-green-700 p-4 rounded mb-4 hidden">
|
||||||
Prompt added successfully!
|
Prompt added successfully!
|
||||||
</div>
|
</div>
|
||||||
@@ -92,14 +92,18 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
<div id="prompt-list" class="max-h-64 overflow-y-auto mb-4 border py-1 pb-2 px-3 rounded flex flex-wrap gap-x-4 gap-y-1"></div>
|
<div id="prompt-list" class="max-h-64 overflow-y-auto mb-4 border py-1 pb-2 px-3 rounded flex flex-wrap gap-x-4 gap-y-1"></div>
|
||||||
|
|
||||||
<button type="button" id="exportBtn" class="bg-yellow-600 text-white px-4 py-2 rounded hover:bg-yellow-700 transition-colors duration-300 cursor-pointer">
|
<button type="button" id="exportBtn" class="bg-yellow-600 text-white px-4 py-2 rounded hover:bg-yellow-700 transition-colors duration-300 cursor-pointer">
|
||||||
Export Selected Prompts
|
Export All Prompts
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
|
||||||
</div>
|
<footer class="border-t p-4 text-center text-sm">
|
||||||
|
© {new Date().getFullYear()} Prompt Catalog
|
||||||
|
</footer>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
|
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
|
||||||
@@ -109,11 +113,48 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
|
|
||||||
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const form = document.getElementById('add-form');
|
const form = document.getElementById('add-form');
|
||||||
|
const importBtn = document.getElementById('importBtn');
|
||||||
|
const exportBtn = document.getElementById('exportBtn');
|
||||||
const successBox = document.getElementById('success');
|
const successBox = document.getElementById('success');
|
||||||
const errorBox = document.getElementById('error');
|
const errorBox = document.getElementById('error');
|
||||||
|
|
||||||
|
async function loadPromptCheckboxes() {
|
||||||
|
const promptList = document.getElementById('prompt-list');
|
||||||
|
const { data, error } = await supabase.from('prompts').select('id, title');
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
promptList.innerHTML = `<p class="text-red-400">Failed to load prompts: ${error.message}</p>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
promptList.innerHTML = data
|
||||||
|
.map(
|
||||||
|
prompt => `
|
||||||
|
<label class="block mb-0">
|
||||||
|
<input type="checkbox" value="${prompt.id}" class="mr-0" />
|
||||||
|
${prompt.title}
|
||||||
|
</label>`
|
||||||
|
)
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
// After rendering, attach change listeners to checkboxes
|
||||||
|
const checkboxes = Array.from(document.querySelectorAll('#prompt-list input[type="checkbox"]'));
|
||||||
|
checkboxes.forEach(cb => cb.addEventListener('change', updateExportBtnText));
|
||||||
|
updateExportBtnText();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load checkboxes on DOM load
|
||||||
|
loadPromptCheckboxes();
|
||||||
|
|
||||||
|
function updateExportBtnText() {
|
||||||
|
const checkboxes = Array.from(document.querySelectorAll('#prompt-list input[type="checkbox"]'));
|
||||||
|
const checkedCount = checkboxes.filter(cb => cb.checked).length;
|
||||||
|
|
||||||
|
exportBtn.textContent = checkedCount > 0 ? 'Export Selected Prompts' : 'Export All Prompts';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
document.getElementById('title').addEventListener('input', (e) => {
|
document.getElementById('title').addEventListener('input', (e) => {
|
||||||
const value = e.target.value
|
const value = e.target.value
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
@@ -151,7 +192,7 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('importBtn').addEventListener('click', async () => {
|
importBtn.addEventListener('click', async () => {
|
||||||
const fileInput = document.getElementById('importFile');
|
const fileInput = document.getElementById('importFile');
|
||||||
const file = fileInput.files[0];
|
const file = fileInput.files[0];
|
||||||
|
|
||||||
@@ -196,36 +237,13 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadPromptCheckboxes() {
|
exportBtn.addEventListener('click', async () => {
|
||||||
const promptList = document.getElementById('prompt-list');
|
|
||||||
const { data, error } = await supabase.from('prompts').select('id, title');
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
promptList.innerHTML = `<p class="text-red-400">Failed to load prompts: ${error.message}</p>`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
promptList.innerHTML = data
|
|
||||||
.map(
|
|
||||||
prompt => `
|
|
||||||
<label class="block mb-0">
|
|
||||||
<input type="checkbox" value="${prompt.id}" class="mr-0" />
|
|
||||||
${prompt.title}
|
|
||||||
</label>`
|
|
||||||
)
|
|
||||||
.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('exportBtn').addEventListener('click', async () => {
|
|
||||||
const checkboxes = Array.from(document.querySelectorAll('#prompt-list input[type="checkbox"]'));
|
|
||||||
const selectedIds = checkboxes.filter(cb => cb.checked).map(cb => cb.value);
|
const selectedIds = checkboxes.filter(cb => cb.checked).map(cb => cb.value);
|
||||||
|
|
||||||
const { data, error } = selectedIds.length > 0
|
const { data, error } = selectedIds.length > 0
|
||||||
? await supabase.from('prompts').select('*').in('id', selectedIds)
|
? await supabase.from('prompts').select('*').in('id', selectedIds)
|
||||||
: await supabase.from('prompts').select('*');
|
: await supabase.from('prompts').select('*');
|
||||||
|
|
||||||
const successBox = document.getElementById('success');
|
|
||||||
const errorBox = document.getElementById('error');
|
|
||||||
successBox.style.display = 'none';
|
successBox.style.display = 'none';
|
||||||
errorBox.style.display = 'none';
|
errorBox.style.display = 'none';
|
||||||
|
|
||||||
@@ -256,9 +274,6 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
link.click();
|
link.click();
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load checkboxes on DOM load
|
|
||||||
loadPromptCheckboxes();
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
hidden
|
hidden
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div class="border-b p-4">
|
<header class="border-b p-4">
|
||||||
<h1 class="text-2xl font-bold">Prompt Catalog - Add New Prompt</h1>
|
<h1 class="text-2xl font-bold">Prompt Catalog - Add New Prompt</h1>
|
||||||
<p class="text-sm mt-1">Add a new AI prompt to the catalog</p>
|
<p class="text-sm mt-1">Add a new AI prompt to the catalog</p>
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<div class="flex h-screen">
|
<main class="flex">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
||||||
<div class="flex-1 flex flex-col overflow-hidden">
|
<div class="flex-1 flex flex-col overflow-hidden">
|
||||||
@@ -32,7 +32,11 @@ const supabaseKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
|
|||||||
<div id="edit-root">Loading...</div>
|
<div id="edit-root">Loading...</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
|
|
||||||
|
<footer class="border-t p-4 text-center text-sm">
|
||||||
|
© {new Date().getFullYear()} Prompt Catalog
|
||||||
|
</footer>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
|
import { createClient } from 'https://cdn.jsdelivr.net/npm/@supabase/supabase-js/+esm';
|
||||||
|
|||||||
@@ -17,20 +17,24 @@ const allTags = Array.from(
|
|||||||
---
|
---
|
||||||
|
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
<div class="border-b p-4">
|
<header class="border-b p-4">
|
||||||
<h1 class="text-2xl font-bold">Prompt Catalog</h1>
|
<h1 class="text-2xl font-bold">Prompt Catalog</h1>
|
||||||
<p class="text-sm mt-1">Explore and filter AI prompts</p>
|
<p class="text-sm mt-1">Explore and filter AI prompts</p>
|
||||||
</div>
|
</header>
|
||||||
|
|
||||||
<div class="flex h-screen">
|
<main class="flex">
|
||||||
<SearchBar allTags={allTags} />
|
<SearchBar allTags={allTags} />
|
||||||
|
|
||||||
<div class="flex-1 flex flex-col overflow-hidden">
|
<div class="flex-1 flex flex-col overflow-hidden">
|
||||||
<main class="flex-1 overflow-y-auto p-4">
|
<div class="flex-1 overflow-y-auto px-6 pt-2">
|
||||||
{error
|
{error
|
||||||
? <p class="text-red-500">Supabase error: {error.message}</p>
|
? <p class="text-red-500">Supabase error: {error.message}</p>
|
||||||
: <FilteredPromptList prompts={prompts} />}
|
: <FilteredPromptList prompts={prompts} />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
|
||||||
</div>
|
<footer class="border-t p-4 text-center text-sm">
|
||||||
|
© {new Date().getFullYear()} Prompt Catalog
|
||||||
|
</footer>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user