admin: copy the prompt, and list the renditions derived from the master
This commit is contained in:
parent
30da437300
commit
ddf6056d43
1 changed files with 42 additions and 1 deletions
43
admin.html
43
admin.html
|
|
@ -111,8 +111,13 @@ function shotHtml(s) {
|
||||||
+ 'after filming — it was NOT used for the video above</div>'
|
+ 'after filming — it was NOT used for the video above</div>'
|
||||||
: '')
|
: '')
|
||||||
+ '</div>'
|
+ '</div>'
|
||||||
|
// Copyable on purpose: the same text pasted into the Gemini web app is how
|
||||||
|
// we tell an artifact of OUR prompt from an artifact of the API path.
|
||||||
+ (s.prompt_sent
|
+ (s.prompt_sent
|
||||||
? '<details><summary>Exact prompt sent</summary><pre>' + esc(s.prompt_sent) + '</pre></details>'
|
? '<details><summary>Exact prompt sent</summary>'
|
||||||
|
+ '<button type="button" class="btn copyp" '
|
||||||
|
+ 'style="padding:4px 10px;font-size:12px;margin:10px 0">Copy this prompt</button>'
|
||||||
|
+ '<pre>' + esc(s.prompt_sent) + '</pre></details>'
|
||||||
: '<div class="kv">no prompt recorded (filmed before prompts were stored)</div>')
|
: '<div class="kv">no prompt recorded (filmed before prompts were stored)</div>')
|
||||||
// The prompt and the request are not the same claim. An earlier version of
|
// The prompt and the request are not the same claim. An earlier version of
|
||||||
// video_render validated its images and then posted only the prompt, which
|
// video_render validated its images and then posted only the prompt, which
|
||||||
|
|
@ -159,6 +164,21 @@ function projHtml(p) {
|
||||||
+ (p.owner_notes ? '<p class="kv" style="margin-top:10px"><b>notes</b> ' + esc(p.owner_notes) + '</p>' : '')
|
+ (p.owner_notes ? '<p class="kv" style="margin-top:10px"><b>notes</b> ' + esc(p.owner_notes) + '</p>' : '')
|
||||||
+ '</div></div>'
|
+ '</div></div>'
|
||||||
+ (p.full_text ? '<details><summary>Full piece as written</summary><pre>' + esc(p.full_text) + '</pre></details>' : '')
|
+ (p.full_text ? '<details><summary>Full piece as written</summary><pre>' + esc(p.full_text) + '</pre></details>' : '')
|
||||||
|
// The master is what Veo produced. Everything else is derived from it and
|
||||||
|
// is disposable; the master is not regenerated and not overwritten.
|
||||||
|
+ (p.renditions && p.renditions.length
|
||||||
|
? '<details open><summary>' + p.renditions.length + ' renditions</summary>'
|
||||||
|
+ p.renditions.map(function (r) {
|
||||||
|
return '<div class="kv" style="margin:10px 0;padding-left:12px;'
|
||||||
|
+ 'border-left:3px solid ' + (r.kind === "master" ? 'var(--accent2)' : 'var(--line)') + '">'
|
||||||
|
+ '<b>' + esc(r.label || r.kind || "") + '</b>'
|
||||||
|
+ (r.url ? ' · <a href="' + esc(r.url) + '" target="_blank" rel="noopener">open</a>' : '')
|
||||||
|
+ (r.made_at ? ' · ' + esc(when(r.made_at)) : '')
|
||||||
|
+ (r.note ? '<br><span style="opacity:.72">' + esc(r.note) + '</span>' : '')
|
||||||
|
+ '</div>';
|
||||||
|
}).join("")
|
||||||
|
+ '</details>'
|
||||||
|
: '')
|
||||||
+ (p.shots && p.shots.length
|
+ (p.shots && p.shots.length
|
||||||
? '<details open><summary>' + p.shots.length + ' shots</summary>' + p.shots.map(shotHtml).join("") + '</details>'
|
? '<details open><summary>' + p.shots.length + ' shots</summary>' + p.shots.map(shotHtml).join("") + '</details>'
|
||||||
: '')
|
: '')
|
||||||
|
|
@ -191,6 +211,27 @@ async function load() {
|
||||||
|
|
||||||
// Delegated, because the list is re-rendered wholesale on every load.
|
// Delegated, because the list is re-rendered wholesale on every load.
|
||||||
document.getElementById("out").onclick = async function (ev) {
|
document.getElementById("out").onclick = async function (ev) {
|
||||||
|
var cp = ev.target.closest ? ev.target.closest(".copyp") : null;
|
||||||
|
if (cp) {
|
||||||
|
var pre = cp.parentElement.querySelector("pre");
|
||||||
|
if (pre) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(pre.textContent);
|
||||||
|
cp.textContent = "Copied";
|
||||||
|
} catch (e) {
|
||||||
|
// Clipboard needs a secure context and permission; selecting the
|
||||||
|
// text is a working fallback rather than a dead button.
|
||||||
|
var rg = document.createRange();
|
||||||
|
rg.selectNodeContents(pre);
|
||||||
|
var sel = window.getSelection();
|
||||||
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(rg);
|
||||||
|
cp.textContent = "Selected — press Ctrl+C";
|
||||||
|
}
|
||||||
|
setTimeout(function () { cp.textContent = "Copy this prompt"; }, 2500);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
var b = ev.target.closest ? ev.target.closest("[data-redub]") : null;
|
var b = ev.target.closest ? ev.target.closest("[data-redub]") : null;
|
||||||
if (!b) return;
|
if (!b) return;
|
||||||
b.disabled = true;
|
b.disabled = true;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue