Add phase 4: AI cleanup and photo/text import via OpenAI
- recipes/ai.py: Chat Completions with strict JSON schema (Structured Outputs), Pydantic re-validation, plausibility clamping, prompt treats input as data only - "Mit KI aufbereiten" on create/edit form returns an editable draft - Import page: photo/screenshot (vision, downscaled JPEG, not stored) and pasted text; drafts pre-fill the recipe form with a preview - Clear UI messages for timeout, rate limit, quota, auth, model and connection errors; without OPENAI_API_KEY AI features show a notice - Optional per-user and global daily AI limits (default unlimited) - Tests for response parsing, schema strictness, error mapping, views Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9256e94286
commit
1bf8ef8b65
@@ -39,3 +39,25 @@ document.addEventListener("change", (event) => {
|
||||
});
|
||||
acquire();
|
||||
})();
|
||||
|
||||
// Long-running submits (AI): show progress on the clicked button and prevent double submits.
|
||||
// Disabling happens after the browser has captured the form data (incl. the clicked button).
|
||||
document.addEventListener("submit", (event) => {
|
||||
const button = event.submitter;
|
||||
if (!button || !button.dataset.busyText) return;
|
||||
setTimeout(() => {
|
||||
event.target.querySelectorAll("button[type=submit]").forEach((b) => {
|
||||
b.dataset.label = b.dataset.label || b.textContent;
|
||||
b.disabled = true;
|
||||
});
|
||||
button.textContent = button.dataset.busyText;
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// Back/forward cache: restore buttons disabled by the handler above.
|
||||
window.addEventListener("pageshow", () => {
|
||||
document.querySelectorAll("button[data-label]").forEach((b) => {
|
||||
b.disabled = false;
|
||||
b.textContent = b.dataset.label;
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user