Add revisions_requested status and visible revision note on admin detail page

This commit is contained in:
Troll (Hermes Agent) 2026-08-01 20:41:59 +00:00
parent cfb725144a
commit 2b960bd3d5
4 changed files with 49 additions and 27 deletions

3
app.py
View file

@ -56,6 +56,7 @@ STATUS_LABELS = {
'pending': 'Pending', 'pending': 'Pending',
'prompt_ready': 'Prompt Ready', 'prompt_ready': 'Prompt Ready',
'songs_uploaded': 'Songs Uploaded — Awaiting Approval', 'songs_uploaded': 'Songs Uploaded — Awaiting Approval',
'revisions_requested': 'Revisions Requested',
'awaiting_payment': 'Awaiting Payment', 'awaiting_payment': 'Awaiting Payment',
'paid': 'Paid', 'paid': 'Paid',
'delivered': 'Delivered', 'delivered': 'Delivered',
@ -235,7 +236,7 @@ def revise(token):
if not req: if not req:
abort(404) abort(404)
note = request.form.get('revision_note', '').strip() note = request.form.get('revision_note', '').strip()
update_request(req['id'], revision_note=note, status='songs_uploaded') update_request(req['id'], revision_note=note, status='revisions_requested')
# NOTE: No operator email is sent; the dashboard is the single queue. # NOTE: No operator email is sent; the dashboard is the single queue.
flash('Your feedback has been saved. We will regenerate and update you.', 'success') flash('Your feedback has been saved. We will regenerate and update you.', 'success')

View file

@ -49,6 +49,7 @@
.paid,.delivered{background:#10b981;color:#000;} .paid,.delivered{background:#10b981;color:#000;}
.pending,.prompt_ready{background:#60a5fa;color:#000;} .pending,.prompt_ready{background:#60a5fa;color:#000;}
.songs_uploaded{background:#a78bfa;color:#000;} .songs_uploaded{background:#a78bfa;color:#000;}
.revisions_requested{background:#f87171;color:#000;}
.actions a{ .actions a{
color:#93c5fd; color:#93c5fd;
text-decoration:none; text-decoration:none;

View file

@ -7,11 +7,12 @@
<style> <style>
/* /*
Single-request admin detail page. Single-request admin detail page.
Four sections: Sections:
1. Generate Suno prompt (copy to Hermes, paste response, extract/copy) 1. Customer info (with revisions note if any)
2. Upload Songs (with status badges) 2. Generate Suno prompt
3. Notify Customer (preview email status + send button) 3. Upload Songs
4. Payment & Delivery (approval status + deliver button) 4. Notify Customer
5. Payment & Delivery
*/ */
body{ body{
font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif; font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
@ -55,6 +56,7 @@
button.secondary{background:#4b5563;} button.secondary{background:#4b5563;}
button.danger{background:#dc2626;} button.danger{background:#dc2626;}
button.success{background:#10b981;} button.success{background:#10b981;}
button:disabled{background:#374151;color:#9ca3af;cursor:not-allowed;}
.actions{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.5rem;} .actions{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.5rem;}
.flash{ .flash{
padding:.8rem; padding:.8rem;
@ -84,6 +86,17 @@
.status-badge.missing{background:#ef4444;color:#000;} .status-badge.missing{background:#ef4444;color:#000;}
.status-badge.sent{background:#60a5fa;color:#000;} .status-badge.sent{background:#60a5fa;color:#000;}
.copy-hint{font-size:.85rem;color:#9ca3af;margin-top:.3rem;} .copy-hint{font-size:.85rem;color:#9ca3af;margin-top:.3rem;}
.revision-note{
margin-top:1rem;
background:#450a0a;
border:1px solid #7f1d1d;
border-radius:.5rem;
padding:1rem;
}
.revision-note h3{
margin-top:0;
color:#f87171;
}
</style> </style>
</head> </head>
<body> <body>
@ -108,35 +121,42 @@
<p><strong>Notable facts:</strong><br>{{ req.notable_facts or '-' }}</p> <p><strong>Notable facts:</strong><br>{{ req.notable_facts or '-' }}</p>
<p><strong>Style / genre:</strong><br>{{ req.style_genre or '-' }}</p> <p><strong>Style / genre:</strong><br>{{ req.style_genre or '-' }}</p>
<p><strong>Extra requests:</strong><br>{{ req.extra_requests or '-' }}</p> <p><strong>Extra requests:</strong><br>{{ req.extra_requests or '-' }}</p>
{% if req.revision_note %}
<!-- Revisions requested by the customer -->
<div class="revision-note">
<h3>📝 Revisions Requested</h3>
<p>{{ req.revision_note }}</p>
</div>
{% endif %}
</div> </div>
<!-- Section 2: Generate Suno prompt --> <!-- Section 2: Generate Suno prompt -->
<div class="section"> <div class="section">
<h2>1. Generate Suno Prompt</h2> <h2>1. Generate Suno Prompt</h2>
<!-- Button copies a plain-text prompt you can paste into Hermes. --> <button type="button" onclick="copyPromptForHermes()">Copy customer info for Hermes</button>
<button type="button" onclick="copyPromptForHermes()">Copy customer info for Hermes</button> <p class="copy-hint">Paste Hermes' Title, Style, and Lyrics directly into the fields below, then save.</p>
<p class="copy-hint">Paste Hermes' Title, Style, and Lyrics directly into the fields below, then save.</p>
<form method="POST"> <form method="POST">
<input type="hidden" name="action" value="save_prompt"> <input type="hidden" name="action" value="save_prompt">
<label for="suno_title">Title</label> <label for="suno_title">Title</label>
<input type="text" id="suno_title" name="suno_title" value="{{ req.suno_title or '' }}"> <input type="text" id="suno_title" name="suno_title" value="{{ req.suno_title or '' }}">
<label for="suno_style">Style</label> <label for="suno_style">Style</label>
<textarea id="suno_style" name="suno_style">{{ req.suno_style or '' }}</textarea> <textarea id="suno_style" name="suno_style">{{ req.suno_style or '' }}</textarea>
<label for="suno_lyrics">Lyrics (with metatags)</label> <label for="suno_lyrics">Lyrics (with metatags)</label>
<textarea id="suno_lyrics" name="suno_lyrics" rows="12">{{ req.suno_lyrics or '' }}</textarea> <textarea id="suno_lyrics" name="suno_lyrics" rows="12">{{ req.suno_lyrics or '' }}</textarea>
<div class="actions"> <div class="actions">
<button type="button" class="secondary" onclick="copyToClipboard('suno_title', 'Title')">Copy Title</button> <button type="button" class="secondary" onclick="copyToClipboard('suno_title', 'Title')">Copy Title</button>
<button type="button" class="secondary" onclick="copyToClipboard('suno_style', 'Style')">Copy Style</button> <button type="button" class="secondary" onclick="copyToClipboard('suno_style', 'Style')">Copy Style</button>
<button type="button" class="secondary" onclick="copyToClipboard('suno_lyrics', 'Lyrics')">Copy Lyrics</button> <button type="button" class="secondary" onclick="copyToClipboard('suno_lyrics', 'Lyrics')">Copy Lyrics</button>
<button type="submit">Save Prompt</button> <button type="submit">Save Prompt</button>
</div> </div>
</form> </form>
</div> </div>
<!-- Section 3: Upload songs --> <!-- Section 3: Upload songs -->
@ -174,7 +194,7 @@
<!-- Section 4: Notify customer --> <!-- Section 4: Notify customer -->
<div class="section"> <div class="section">
<h2>3. Notify Customer</h2> <h2>3. Notify Customer</h2>
<!-- Preview link shown to operator after songs are uploaded. -->
<p> <p>
Preview email: Preview email:
{% if req.preview_sent_at %} {% if req.preview_sent_at %}

View file

@ -85,7 +85,7 @@
<audio controls src="{{ url_for('audio', token=req.player_token, version='b') }}"></audio> <audio controls src="{{ url_for('audio', token=req.player_token, version='b') }}"></audio>
</div> </div>
{% if req.status in ['songs_uploaded','awaiting_payment','paid','delivered'] %} {% if req.status in ['songs_uploaded','revisions_requested','awaiting_payment','paid','delivered'] %}
<!-- Approval form: customer picks A, B, or both --> <!-- Approval form: customer picks A, B, or both -->
<form method="POST" action="{{ url_for('approve', token=req.player_token) }}"> <form method="POST" action="{{ url_for('approve', token=req.player_token) }}">
<input type="hidden" name="choice" id="choice"> <input type="hidden" name="choice" id="choice">