Files
Gitea-Tools/webui/prompt_views.py
T
sysadminandClaude Opus 4.8 6670c72e65 feat: add canonical workflow prompt library to web UI (Closes #428)
Expose short copy/paste operator prompts on /prompts derived from canonical
workflow files with workflow path and SHA-256 hash. Adds JSON export at
/api/prompts, copy buttons, and tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-07 14:53:16 -04:00

80 lines
2.4 KiB
Python

"""HTML views for the prompt library (#428)."""
from __future__ import annotations
import html
from webui.prompt_library import PromptEntry, load_prompt_library
def _escape(text: str) -> str:
return html.escape(text, quote=True)
def render_prompts_page() -> str:
entries = load_prompt_library()
cards: list[str] = []
for entry in entries:
cards.append(_render_prompt_card(entry))
body = (
"<h2>Prompt library</h2>"
"<p>Short copy/paste task prompts derived from canonical workflows. "
"Full policy remains in the cited workflow files — not duplicated here.</p>"
f"{''.join(cards)}"
f"{PROMPT_PAGE_SCRIPT}"
)
from webui.layout import render_page
return render_page(title="Prompts", body_html=body)
def _render_prompt_card(entry: PromptEntry) -> str:
hash_short = (
f"<code>{_escape(entry.workflow_hash[:12])}</code>"
if entry.workflow_hash
else "<span class=\"muted\">n/a</span>"
)
task_mode = (
f"<code>{_escape(entry.task_mode)}</code>"
if entry.task_mode
else "<span class=\"muted\">n/a</span>"
)
note = (
f'<p class="meta">{_escape(entry.source_note)}</p>'
if entry.source_note
else ""
)
prompt_id = f"prompt-{entry.slug}"
return (
f'<section class="prompt-card" id="{_escape(entry.slug)}">'
f"<h3>{_escape(entry.label)}</h3>"
f'<p class="meta">Workflow: <code>{_escape(entry.workflow_path)}</code> · '
f"task_mode: {task_mode} · sha256: {hash_short}</p>"
f'<pre class="prompt-text" id="{prompt_id}">{_escape(entry.prompt_text)}</pre>'
f'<button type="button" class="copy-btn" data-copy-target="{prompt_id}">'
"Copy prompt</button>"
f"{note}"
"</section>"
)
PROMPT_PAGE_SCRIPT = """
<script>
document.querySelectorAll('.copy-btn').forEach((btn) => {
btn.addEventListener('click', async () => {
const targetId = btn.getAttribute('data-copy-target');
const node = document.getElementById(targetId);
if (!node) return;
const text = node.textContent || '';
try {
await navigator.clipboard.writeText(text);
const prior = btn.textContent;
btn.textContent = 'Copied';
setTimeout(() => { btn.textContent = prior; }, 1200);
} catch (_err) {
btn.textContent = 'Copy failed';
}
});
});
</script>
"""