feat: model selection+visibility, better filenames, picdrop direct upload + configurable gallery

- studio: quality/model selector (friendly names from active models); library shows model used
- seed 2 models (Schnell/Beste Qualitaet); GET /api/models for studio+library
- filename: YYYY-MM-DD_motif_format.png (was redundant slug, no date)
- picdrop: direct upload to final name (fix .tmp- leftover from failed rename on picdrop); cleanupTmp helper
- configurable default gallery (migration 003, settings + admin field); base_path=SFTP root, gallery=subfolder
This commit is contained in:
2026-07-23 18:54:37 +00:00
parent b047f55687
commit 6d58c6c8fd
12 changed files with 120 additions and 28 deletions
+2 -1
View File
@@ -15,6 +15,7 @@ export const GET: APIRoute = async () => {
openrouter_key_masked: orMask, openrouter_key_set: !!s.openrouter_key_enc,
picdrop_host: s.picdrop_host, picdrop_protocol: s.picdrop_protocol, picdrop_port: s.picdrop_port,
picdrop_user: s.picdrop_user, picdrop_base_path: s.picdrop_base_path,
picdrop_default_gallery: s.picdrop_default_gallery,
picdrop_password_set: !!s.picdrop_password_enc,
default_dpi: s.default_dpi, default_crop_mode: s.default_crop_mode, concurrency: s.concurrency,
cricut_sheet_cm: s.cricut_sheet_cm, monthly_budget: s.monthly_budget, n8n_webhook_url: s.n8n_webhook_url,
@@ -29,7 +30,7 @@ export const PATCH: APIRoute = async ({ request }) => {
if (b.openrouter_key) set('openrouter_key_enc', encrypt(String(b.openrouter_key)));
if (b.picdrop_password) set('picdrop_password_enc', encrypt(String(b.picdrop_password)));
for (const col of ['picdrop_host', 'picdrop_protocol', 'picdrop_port', 'picdrop_user', 'picdrop_base_path',
'default_dpi', 'default_crop_mode', 'concurrency', 'cricut_sheet_cm', 'monthly_budget', 'n8n_webhook_url']) {
'picdrop_default_gallery', 'default_dpi', 'default_crop_mode', 'concurrency', 'cricut_sheet_cm', 'monthly_budget', 'n8n_webhook_url']) {
if (col in b) set(col, b[col] === '' ? null : b[col]);
}
if (!sets.length) return json({ ok: true });
+1 -1
View File
@@ -24,7 +24,7 @@ export const GET: APIRoute = async ({ url, locals }) => {
const rows = await query(
`SELECT i.id, i.filename, i.output_px, i.has_alpha, i.result_path, i.folder_id,
i.delivery_status, i.created_at, u.display_name AS by_name,
i.delivery_status, i.created_at, i.model_used, u.display_name AS by_name,
j.recipe_snapshot->'tasks' AS tasks
FROM items i
JOIN jobs j ON j.id = i.job_id
+13
View File
@@ -0,0 +1,13 @@
import type { APIRoute } from 'astro';
import { query } from '../../lib/db';
export const prerender = false;
// Aktive Modelle mit freundlichen Namen (für Studio-Auswahl + Ergebnis-Anzeige).
export const GET: APIRoute = async ({ locals }) => {
if (!locals.user) return new Response('Unauthorized', { status: 401 });
const models = await query(
`SELECT model_id, label, description, is_default, supports_alpha FROM models
WHERE active ORDER BY sort, label`);
return new Response(JSON.stringify({ models }), { headers: { 'Content-Type': 'application/json' } });
};