Files
LLeMbas/src/lembas/web/templates/admin/suggestions.html
T
Jaroslav Beneš d9f274ec1a A suggestion card sends its prompt
Filling the composer and waiting for Enter made the card a form to review
rather than a thing to press. One click, one reply.

That changes what a prompt has to be. The built-ins ended mid-sentence --
"My plan: " -- because nothing was sent until the person finished the
thought; sent cold they are a model guessing at material nobody gave it. All
three are rewritten to ask for what they need, so the first reply is the
right question instead. There is a test that they end as complete sentences,
since the failure is silent and only visible in the answer.

requestSubmit, not submit: it fires the submit event, which is what htmx
listens for. Same call the Enter key already makes.

Version bumped because app.js is what changed, and the service worker caches
it -- without the bump the first load after this would still only fill the
box.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 01:12:02 +02:00

121 lines
4.6 KiB
HTML

{% extends "admin/_layout.html" %}
{% from "_macros.html" import icon %}
{% set section = "suggestions" %}
{% block title %}Suggestions - LLeMbas{% endblock %}
{% block heading %}Suggestions{% endblock %}
{% block admin_content %}
<p class="admin-lede">
Cards on the new-chat screen. Clicking one sends its prompt straight away, so
each has to work on its own — write one that asks for whatever it needs, and
the first reply becomes the right question rather than a guess. The first
{{ max_shown }} enabled ones are shown, in this order.
</p>
{% if saved %}
<div class="alert alert--success">{{ icon("check", "icon--sm") }} <span>{{ saved }}</span></div>
{% endif %}
{% for suggestion in suggestions %}
<form class="card" method="post" action="/admin/suggestions/{{ suggestion.id }}">
<div class="card__header">
<h2 class="card__title">
{{ suggestion.name }}
{% if not suggestion.enabled %}<span class="badge">hidden</span>{% endif %}
{% if loop.index > max_shown and suggestion.enabled %}
<span class="badge badge--warning" title="Only the first {{ max_shown }} are shown">
below the cut
</span>
{% endif %}
</h2>
<button class="btn btn--sm btn--danger" type="submit"
formaction="/admin/suggestions/{{ suggestion.id }}/delete"
data-confirm-button="Delete the suggestion “{{ suggestion.name }}”?"
data-confirm-title="Delete suggestion">
{{ icon("trash", "icon--sm") }}
</button>
</div>
<div class="grid grid--2">
<div class="field">
<label class="field__label" for="name-{{ suggestion.id }}">Name</label>
<input class="input" id="name-{{ suggestion.id }}" name="name"
value="{{ suggestion.name }}" maxlength="120">
<p class="field__hint">The heading on the card.</p>
</div>
<div class="field">
<label class="field__label" for="position-{{ suggestion.id }}">Position</label>
<input class="input" id="position-{{ suggestion.id }}" name="position" type="number"
min="1" value="{{ suggestion.position + 1 }}">
<p class="field__hint">Order on the screen, lowest first.</p>
</div>
</div>
<div class="field">
<label class="field__label" for="description-{{ suggestion.id }}">Description</label>
<input class="input" id="description-{{ suggestion.id }}" name="description"
value="{{ suggestion.description }}" maxlength="300">
<p class="field__hint">One line under the name, saying what it is for.</p>
</div>
<div class="field">
<label class="field__label" for="prompt-{{ suggestion.id }}">Prompt</label>
<textarea class="textarea" id="prompt-{{ suggestion.id }}" name="prompt"
rows="4">{{ suggestion.prompt }}</textarea>
<p class="field__hint">
Sent as the first message. Nothing is added to it, so a prompt that needs
material should ask for it.
</p>
</div>
<div class="field">
<label class="checkbox">
<input type="checkbox" name="enabled" value="true" {{ 'checked' if suggestion.enabled }}>
<span>Show this one</span>
</label>
</div>
<div class="card__footer">
<button class="btn btn--primary btn--sm" type="submit">Save</button>
</div>
</form>
{% else %}
<div class="empty">
{{ icon("sparkle", "empty__mark") }}
<h2 class="empty__title">No suggestions</h2>
<p class="empty__text">The new-chat screen shows its empty state instead.</p>
</div>
{% endfor %}
{% if not at_limit %}
<form class="card" method="post" action="/admin/suggestions">
<h2 class="card__title">Add a suggestion</h2>
<div class="field">
<label class="field__label" for="new-name">Name</label>
<input class="input" id="new-name" name="name" maxlength="120"
placeholder="Summarise a document" required>
</div>
<div class="field">
<label class="field__label" for="new-description">Description</label>
<input class="input" id="new-description" name="description" maxlength="300"
placeholder="What it is for, in one line.">
</div>
<div class="field">
<label class="field__label" for="new-prompt">Prompt</label>
<textarea class="textarea" id="new-prompt" name="prompt" rows="4"
placeholder="Sent as the first message when the card is clicked."></textarea>
</div>
<div class="card__footer">
<button class="btn btn--primary" type="submit">Add</button>
</div>
</form>
{% else %}
<p class="admin-lede">
{{ max_suggestions }} is the limit. Delete one to add another — past a dozen
this is a menu, and a menu on the empty screen is a worse blank page than a
blank page.
</p>
{% endif %}
{% endblock %}