trailer.html: pick a head writer, read the reviews, revise, film
The four scripts had no next step. Everything after "read them" lived in the API and nothing on the page reached it. The choice of head writer is the author's, and it is a judgement about concept rather than a score, so it is a button on each tab rather than a leaderboard. Naming the lead first also changes what the reviews are for: three models arguing about how to fix THIS script is a more useful argument than three models arguing about whose is better. Reviews are split the way they come back - errors are things that are wrong and are worth fixing, suggestions are matters of judgement, and "keeps" is what a revision must not quietly remove. The author's shot notes outrank all of it and the revise button says so. Film is priced and gated on having a storyboard, because every shot needs an opening frame to film from.
This commit is contained in:
parent
31b3474f8f
commit
a20ed2d57b
1 changed files with 174 additions and 39 deletions
213
trailer.html
213
trailer.html
|
|
@ -11,8 +11,10 @@
|
||||||
.tab{border:1px solid var(--line);border-bottom:0;background:none;color:var(--muted);
|
.tab{border:1px solid var(--line);border-bottom:0;background:none;color:var(--muted);
|
||||||
padding:10px 16px;border-radius:10px 10px 0 0;cursor:pointer;font:inherit;font-size:14px}
|
padding:10px 16px;border-radius:10px 10px 0 0;cursor:pointer;font:inherit;font-size:14px}
|
||||||
.tab.on{color:var(--ink);border-color:var(--line);background:var(--panel)}
|
.tab.on{color:var(--ink);border-color:var(--line);background:var(--panel)}
|
||||||
|
.tab.lead{color:var(--accent)}
|
||||||
.tab .sc{color:var(--accent2);margin-left:7px;font-weight:600}
|
.tab .sc{color:var(--accent2);margin-left:7px;font-weight:600}
|
||||||
.tab .st{color:var(--muted);margin-left:7px;font-size:12px}
|
.tab .st{color:var(--muted);margin-left:7px;font-size:12px}
|
||||||
|
.tab .crown{margin-left:6px}
|
||||||
.head{display:flex;gap:18px;flex-wrap:wrap;align-items:baseline;margin-bottom:6px}
|
.head{display:flex;gap:18px;flex-wrap:wrap;align-items:baseline;margin-bottom:6px}
|
||||||
.head h2{margin:0;font-size:22px}
|
.head h2{margin:0;font-size:22px}
|
||||||
.tag{color:var(--muted);font-style:italic}
|
.tag{color:var(--muted);font-style:italic}
|
||||||
|
|
@ -59,6 +61,15 @@
|
||||||
border-radius:999px;padding:0 6px}
|
border-radius:999px;padding:0 6px}
|
||||||
.vobadge{color:var(--muted);font-size:11px;border:1px solid var(--line);
|
.vobadge{color:var(--muted);font-size:11px;border:1px solid var(--line);
|
||||||
border-radius:999px;padding:0 6px}
|
border-radius:999px;padding:0 6px}
|
||||||
|
.revs{margin:0 0 22px}
|
||||||
|
.rev{border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:10px}
|
||||||
|
.rev h4{margin:0 0 6px;font-size:14px}
|
||||||
|
.rev h4 .n{color:var(--accent2);font-weight:600;margin-left:8px}
|
||||||
|
.rev .v{color:var(--muted);font-size:13px;margin:0 0 8px}
|
||||||
|
.rev ul{margin:4px 0 8px;padding-left:18px;font-size:13px}
|
||||||
|
.rev .er{color:#e0685f}
|
||||||
|
.rev .kp{color:var(--accent2)}
|
||||||
|
.rev .sh{color:var(--muted);font-variant-numeric:tabular-nums}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -80,44 +91,59 @@
|
||||||
if (!requireSession()) return;
|
if (!requireSession()) return;
|
||||||
navBar("trailer");
|
navBar("trailer");
|
||||||
|
|
||||||
var RUN = null, DRAFTS = [], CUR = null, PKG = {}, NOTES = {}, timer = null;
|
var RUN = null, DRAFTS = [], CUR = null, PKG = {}, NOTES = {}, REVIEWS = [];
|
||||||
|
var timer = null;
|
||||||
var runId = new URLSearchParams(location.search).get("run") || "";
|
var runId = new URLSearchParams(location.search).get("run") || "";
|
||||||
var audio = new Audio();
|
var audio = new Audio();
|
||||||
|
|
||||||
if (!runId) { showMsg("msg", "No run was named in the link."); return; }
|
if (!runId) { showMsg("msg", "No run was named in the link."); return; }
|
||||||
|
|
||||||
// A draft is busy while it is being written or drawn. Both are minutes long
|
// A draft is busy while it is being written or drawn; a run is busy while it
|
||||||
// and both report progress on the row, so one poll covers them.
|
// is reviewing or revising. Both are minutes long and report on the row.
|
||||||
function busyState(d) {
|
function busyDraft(d) {
|
||||||
var s = String(d.draw_state || "");
|
var s = String(d.draw_state || "");
|
||||||
return d.state === "writing" || (s && !/^(drawn|failed)/.test(s));
|
return d.state === "writing" || (s && !/^(drawn|failed)/.test(s));
|
||||||
}
|
}
|
||||||
|
function busyRun() {
|
||||||
|
return RUN && /^(writing|reviewing|revising)$/.test(String(RUN.stage || ""));
|
||||||
|
}
|
||||||
|
|
||||||
async function load(repaint) {
|
async function load(repaint) {
|
||||||
var r = await api("run_status", { run_id: runId });
|
var r = await api("run_status", { run_id: runId });
|
||||||
if (!r.ok) { showMsg("msg", r.error || "Could not load that run."); return; }
|
if (!r.ok) { showMsg("msg", r.error || "Could not load that run."); return; }
|
||||||
var wasBusy = DRAFTS.length && DRAFTS.some(busyState);
|
var wasBusy = (DRAFTS.length && DRAFTS.some(busyDraft)) || busyRun();
|
||||||
RUN = r.run; DRAFTS = r.drafts || [];
|
RUN = r.run; DRAFTS = r.drafts || [];
|
||||||
document.getElementById("title").textContent = RUN.book_title || "Trailers";
|
document.getElementById("title").textContent = RUN.book_title || "Trailers";
|
||||||
document.getElementById("sub").textContent = sub();
|
document.getElementById("sub").textContent = sub();
|
||||||
if (!CUR && DRAFTS.length) CUR = DRAFTS[0].id;
|
if (!CUR && DRAFTS.length) CUR = leadDraftId() || DRAFTS[0].id;
|
||||||
paintTabs();
|
paintTabs();
|
||||||
|
|
||||||
var busy = DRAFTS.some(busyState);
|
var rv = await api("list_reviews", { run_id: runId });
|
||||||
|
REVIEWS = (rv && rv.reviews) || [];
|
||||||
|
|
||||||
|
var busy = DRAFTS.some(busyDraft) || busyRun();
|
||||||
if (busy && !timer) timer = setInterval(load, 5000);
|
if (busy && !timer) timer = setInterval(load, 5000);
|
||||||
if (!busy && timer) { clearInterval(timer); timer = null; }
|
if (!busy && timer) { clearInterval(timer); timer = null; }
|
||||||
|
|
||||||
var me = DRAFTS.filter(function (d) { return d.id === CUR; })[0];
|
var me = DRAFTS.filter(function (d) { return d.id === CUR; })[0];
|
||||||
if (me && me.state === "writing") { paintWriting(); return; }
|
if (me && me.state === "writing") { paintWriting(); return; }
|
||||||
// Repaint when asked, on first paint, or when work has just finished.
|
|
||||||
if (repaint !== false && (wasBusy || !document.querySelector(".shot"))) openTab(CUR);
|
if (repaint !== false && (wasBusy || !document.querySelector(".shot"))) openTab(CUR);
|
||||||
else paintBar();
|
else paintBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function leadDraftId() {
|
||||||
|
var best = null;
|
||||||
|
DRAFTS.forEach(function (d) {
|
||||||
|
if (d.writer === RUN.lead_writer
|
||||||
|
&& (!best || Number(d.iteration) > Number(best.iteration))) best = d;
|
||||||
|
});
|
||||||
|
return best && best.id;
|
||||||
|
}
|
||||||
|
|
||||||
function sub() {
|
function sub() {
|
||||||
var bits = [];
|
var bits = [];
|
||||||
if (RUN.stage) bits.push(RUN.stage);
|
if (RUN.stage) bits.push(RUN.stage);
|
||||||
bits.push(DRAFTS.length + " writer" + (DRAFTS.length === 1 ? "" : "s"));
|
bits.push(DRAFTS.length + " script" + (DRAFTS.length === 1 ? "" : "s"));
|
||||||
var spent = DRAFTS.reduce(function (a, d) {
|
var spent = DRAFTS.reduce(function (a, d) {
|
||||||
return a + Number(d.write_usd || 0) + Number(d.draw_usd || 0); }, 0);
|
return a + Number(d.write_usd || 0) + Number(d.draw_usd || 0); }, 0);
|
||||||
if (spent) bits.push("$" + spent.toFixed(2) + " so far");
|
if (spent) bits.push("$" + spent.toFixed(2) + " so far");
|
||||||
|
|
@ -133,16 +159,19 @@
|
||||||
: (s && !/^(drawn|failed)/.test(s)) ? '<span class="st">' + esc(s) + '</span>'
|
: (s && !/^(drawn|failed)/.test(s)) ? '<span class="st">' + esc(s) + '</span>'
|
||||||
: d.score ? '<span class="sc">' + d.score + '</span>'
|
: d.score ? '<span class="sc">' + d.score + '</span>'
|
||||||
: '';
|
: '';
|
||||||
|
var isLead = d.writer === RUN.lead_writer;
|
||||||
return '<button type="button" class="tab' + (d.id === CUR ? ' on' : '')
|
return '<button type="button" class="tab' + (d.id === CUR ? ' on' : '')
|
||||||
+ '" data-tab="' + esc(d.id) + '">' + esc(d.label || d.writer)
|
+ (isLead ? ' lead' : '') + '" data-tab="' + esc(d.id) + '">'
|
||||||
|
+ esc(d.label || d.writer)
|
||||||
|
+ (Number(d.iteration) > 1 ? ' v' + d.iteration : '')
|
||||||
|
+ (isLead ? '<span class="crown" title="head writer">★</span>' : '')
|
||||||
+ extra + '</button>';
|
+ extra + '</button>';
|
||||||
}).join("");
|
}).join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function paintWriting() {
|
function paintWriting() {
|
||||||
document.getElementById("pane").innerHTML =
|
document.getElementById("pane").innerHTML =
|
||||||
'<p class="empty">Each writer is reading the whole book and writing its own '
|
'<p class="empty">Working. Reading the whole book takes a few minutes.</p>';
|
||||||
+ 'trailer. This takes a few minutes.</p>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("tabs").addEventListener("click", function (e) {
|
document.getElementById("tabs").addEventListener("click", function (e) {
|
||||||
|
|
@ -160,7 +189,9 @@
|
||||||
var pane = document.getElementById("pane");
|
var pane = document.getElementById("pane");
|
||||||
if (meta.state === "failed") {
|
if (meta.state === "failed") {
|
||||||
pane.innerHTML = '<p class="empty"><b>' + esc(meta.label) + ' did not finish.</b><br>'
|
pane.innerHTML = '<p class="empty"><b>' + esc(meta.label) + ' did not finish.</b><br>'
|
||||||
+ esc(meta.note || "No reason was recorded.") + '</p>';
|
+ esc(meta.note || "No reason was recorded.") + '</p>'
|
||||||
|
+ '<div class="bar"><button type="button" class="btn" data-retry="'
|
||||||
|
+ esc(meta.id) + '">Try this writer again</button></div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (meta.state === "writing") { paintWriting(); return; }
|
if (meta.state === "writing") { paintWriting(); return; }
|
||||||
|
|
@ -172,50 +203,109 @@
|
||||||
pane.innerHTML = paneHtml(meta, r.draft);
|
pane.innerHTML = paneHtml(meta, r.draft);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawBtn(meta) {
|
function barHtml(meta) {
|
||||||
var shots = (PKG.shots || []).length, cast = (PKG.characters || []).length;
|
var shots = (PKG.shots || []).length, cast = (PKG.characters || []).length;
|
||||||
var imgs = cast * 3 + shots * 2;
|
var imgs = cast * 3 + shots * 2;
|
||||||
var price = imgs * 0.068;
|
var price = imgs * 0.068;
|
||||||
var s = String(meta.draw_state || "");
|
var s = String(meta.draw_state || "");
|
||||||
if (s && !/^(drawn|failed)/.test(s)) {
|
var drawing = s && !/^(drawn|failed)/.test(s);
|
||||||
return '<button type="button" class="btn" disabled>Drawing… ' + esc(s)
|
var drawn = /^drawn/.test(s);
|
||||||
+ '</button><span class="soon">Cast sheets first, then every shot. '
|
var isLead = meta.writer === RUN.lead_writer;
|
||||||
+ 'This takes a few minutes.</span>';
|
var out = [];
|
||||||
|
|
||||||
|
// 1. Whose concept wins. The author's call, not a score's.
|
||||||
|
if (!isLead) {
|
||||||
|
out.push('<button type="button" class="btn primary" data-lead="' + esc(meta.id)
|
||||||
|
+ '">Make this the head writer</button>');
|
||||||
|
} else {
|
||||||
|
out.push('<span class="soon">★ head writer</span>');
|
||||||
}
|
}
|
||||||
if (/^drawn/.test(s)) {
|
|
||||||
return '<button type="button" class="btn" data-draw="' + esc(meta.id)
|
// 2. Drawing.
|
||||||
+ '">Draw it again · $' + price.toFixed(2) + '</button>'
|
if (drawing) {
|
||||||
+ '<span class="soon">' + esc(s)
|
out.push('<button type="button" class="btn" disabled>Drawing… ' + esc(s) + '</button>');
|
||||||
+ (meta.draw_usd ? ' · $' + Number(meta.draw_usd).toFixed(2) + ' spent' : '')
|
} else {
|
||||||
+ '</span>';
|
out.push('<button type="button" class="btn" data-draw="' + esc(meta.id) + '">'
|
||||||
|
+ (drawn ? "Draw it again" : "Draw this storyboard") + ' · $'
|
||||||
|
+ price.toFixed(2) + '</button>');
|
||||||
|
if (!drawn) out.push('<span class="soon">' + imgs + ' pictures</span>');
|
||||||
|
else out.push('<span class="soon">' + esc(s)
|
||||||
|
+ (meta.draw_usd ? ' · $' + Number(meta.draw_usd).toFixed(2) : '') + '</span>');
|
||||||
}
|
}
|
||||||
return '<button type="button" class="btn primary" data-draw="' + esc(meta.id)
|
|
||||||
+ '">Draw this storyboard · $' + price.toFixed(2) + '</button>'
|
// 3. Review, revise, film - only meaningful on the head writer's tab.
|
||||||
+ '<span class="soon">' + imgs + ' pictures — ' + cast
|
if (isLead) {
|
||||||
+ ' cast sheets and ' + shots + ' shots, opening and closing.</span>'
|
var others = DRAFTS.filter(function (d) {
|
||||||
+ (s === "failed" && meta.note ? '<span class="soon">' + esc(meta.note) + '</span>' : '');
|
return d.writer !== RUN.lead_writer && /^ready/.test(String(d.state)); }).length;
|
||||||
|
if (RUN.stage === "reviewing") {
|
||||||
|
out.push('<button type="button" class="btn" disabled>The others are reading it…</button>');
|
||||||
|
} else if (others) {
|
||||||
|
out.push('<button type="button" class="btn" data-review="1">'
|
||||||
|
+ (REVIEWS.length ? "Review it again" : "Have the others review this")
|
||||||
|
+ ' · ' + others + ' readers</button>');
|
||||||
|
}
|
||||||
|
if (RUN.stage === "revising") {
|
||||||
|
out.push('<button type="button" class="btn" disabled>Rewriting…</button>');
|
||||||
|
} else if (REVIEWS.length || Object.keys(NOTES).length) {
|
||||||
|
out.push('<button type="button" class="btn primary" data-revise="1">'
|
||||||
|
+ 'Revise with the notes</button>');
|
||||||
|
}
|
||||||
|
if (drawn) {
|
||||||
|
out.push('<button type="button" class="btn primary" data-film="' + esc(meta.id)
|
||||||
|
+ '">Film this trailer</button>');
|
||||||
|
} else {
|
||||||
|
out.push('<span class="soon">Draw the storyboard before filming — '
|
||||||
|
+ 'every shot is filmed from its opening frame.</span>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function paintBar() {
|
function paintBar() {
|
||||||
var el = document.querySelector(".bar");
|
var el = document.querySelector(".bar");
|
||||||
var meta = DRAFTS.filter(function (d) { return d.id === CUR; })[0];
|
var meta = DRAFTS.filter(function (d) { return d.id === CUR; })[0];
|
||||||
if (el && meta) el.innerHTML = drawBtn(meta);
|
if (el && meta) el.innerHTML = barHtml(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reviewsHtml(meta) {
|
||||||
|
var mine = REVIEWS.filter(function (r) {
|
||||||
|
return r.subject === meta.writer && Number(r.iteration) === Number(meta.iteration); });
|
||||||
|
if (!mine.length) return "";
|
||||||
|
return '<div class="revs">' + mine.map(function (r) {
|
||||||
|
var parts = ['<div class="rev"><h4>' + esc(r.label)
|
||||||
|
+ '<span class="n">' + esc(r.score) + '/100</span></h4>'];
|
||||||
|
function list(items, cls, fmt) {
|
||||||
|
if (!items || !items.length) return "";
|
||||||
|
return '<ul class="' + cls + '">' + items.map(fmt).join("") + '</ul>';
|
||||||
|
}
|
||||||
|
parts.push(list(r.errors, "er", function (e) {
|
||||||
|
return '<li>' + (e.shot ? '<span class="sh">shot ' + esc(e.shot) + '</span> ' : '')
|
||||||
|
+ esc(e.problem || "") + (e.fix ? ' — <i>' + esc(e.fix) + '</i>' : '') + '</li>'; }));
|
||||||
|
parts.push(list(r.suggestions, "", function (s) {
|
||||||
|
return '<li>' + (s.shot ? '<span class="sh">shot ' + esc(s.shot) + '</span> ' : '')
|
||||||
|
+ esc(s.change || "") + (s.why ? ' <span class="sh">(' + esc(s.why) + ')</span>' : '') + '</li>'; }));
|
||||||
|
parts.push(list(r.strengths, "kp", function (s) {
|
||||||
|
return '<li>' + esc(typeof s === "string" ? s : JSON.stringify(s)) + '</li>'; }));
|
||||||
|
return parts.join("") + '</div>';
|
||||||
|
}).join("") + '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function paneHtml(meta, draft) {
|
function paneHtml(meta, draft) {
|
||||||
var p = PKG, shots = p.shots || [], cast = p.characters || [];
|
var p = PKG, shots = p.shots || [], cast = p.characters || [];
|
||||||
var voice = {};
|
var voice = {};
|
||||||
cast.forEach(function (c) { voice[c.id] = c; });
|
cast.forEach(function (c) { voice[c.id] = c; });
|
||||||
|
|
||||||
var secs = shots.reduce(function (a, s) { return a + (Number(s.edit_seconds) || 0); }, 0);
|
var secs = shots.reduce(function (a, s) { return a + (Number(s.edit_seconds) || 0); }, 0);
|
||||||
|
|
||||||
var head = '<div class="head"><h2>' + esc(p.title || meta.label) + '</h2>'
|
var head = '<div class="head"><h2>' + esc(p.title || meta.label) + '</h2>'
|
||||||
+ (p.tagline ? '<span class="tag">' + esc(p.tagline) + '</span>' : '') + '</div>'
|
+ (p.tagline ? '<span class="tag">' + esc(p.tagline) + '</span>' : '') + '</div>'
|
||||||
+ (p.logline ? '<p>' + esc(p.logline) + '</p>' : '')
|
+ (p.logline ? '<p>' + esc(p.logline) + '</p>' : '')
|
||||||
+ '<p class="facts">' + esc(meta.label) + ' · ' + shots.length + ' shots · '
|
+ '<p class="facts">' + esc(meta.label)
|
||||||
|
+ (Number(meta.iteration) > 1 ? ' · revision ' + meta.iteration : '')
|
||||||
|
+ ' · ' + shots.length + ' shots · '
|
||||||
+ Math.floor(secs / 60) + ':' + String(Math.round(secs % 60)).padStart(2, "0")
|
+ Math.floor(secs / 60) + ':' + String(Math.round(secs % 60)).padStart(2, "0")
|
||||||
+ ' · ' + cast.length + ' characters'
|
+ ' · ' + cast.length + ' characters'
|
||||||
+ (meta.write_usd ? ' · $' + Number(meta.write_usd).toFixed(2) + ' to write' : '')
|
+ (meta.write_usd ? ' · $' + Number(meta.write_usd).toFixed(2) + ' to write' : '')
|
||||||
|
+ (meta.note ? ' · ' + esc(meta.note) : '')
|
||||||
+ '</p>';
|
+ '</p>';
|
||||||
|
|
||||||
var probs = "";
|
var probs = "";
|
||||||
|
|
@ -240,7 +330,8 @@
|
||||||
+ '<div class="ap">' + esc((c.appearance || "").slice(0, 150)) + '</div></div>';
|
+ '<div class="ap">' + esc((c.appearance || "").slice(0, 150)) + '</div></div>';
|
||||||
}).join("") + '</div>';
|
}).join("") + '</div>';
|
||||||
|
|
||||||
return head + probs + '<div class="bar">' + drawBtn(meta) + '</div>' + castHtml
|
return head + probs + '<div class="bar">' + barHtml(meta) + '</div>'
|
||||||
|
+ reviewsHtml(meta) + castHtml
|
||||||
+ shots.map(function (s) { return shotHtml(s, voice); }).join("");
|
+ shots.map(function (s) { return shotHtml(s, voice); }).join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +365,7 @@
|
||||||
+ (s.continuity ? '<p class="cont">continuity: ' + esc(s.continuity) + '</p>' : '')
|
+ (s.continuity ? '<p class="cont">continuity: ' + esc(s.continuity) + '</p>' : '')
|
||||||
+ lines
|
+ lines
|
||||||
+ '<textarea class="note" rows="2" data-note="' + esc(s.id) + '" '
|
+ '<textarea class="note" rows="2" data-note="' + esc(s.id) + '" '
|
||||||
+ 'placeholder="Your note on this shot. It gets the highest priority in the revision.">'
|
+ 'placeholder="Your note on this shot. It outranks everything the other writers said.">'
|
||||||
+ esc(NOTES[s.id] || "") + '</textarea>'
|
+ esc(NOTES[s.id] || "") + '</textarea>'
|
||||||
+ '</div></div>';
|
+ '</div></div>';
|
||||||
}
|
}
|
||||||
|
|
@ -282,17 +373,61 @@
|
||||||
// ------------------------------------------------------------ actions
|
// ------------------------------------------------------------ actions
|
||||||
|
|
||||||
document.getElementById("pane").addEventListener("click", async function (e) {
|
document.getElementById("pane").addEventListener("click", async function (e) {
|
||||||
var draw = e.target.closest ? e.target.closest("[data-draw]") : null;
|
var t = e.target.closest ? e.target : null;
|
||||||
|
if (!t) return;
|
||||||
|
|
||||||
|
var lead = e.target.closest("[data-lead]");
|
||||||
|
if (lead) {
|
||||||
|
lead.disabled = true;
|
||||||
|
var a = await api("set_lead", { run_id: runId, draft_id: lead.getAttribute("data-lead") });
|
||||||
|
if (!a.ok) { lead.disabled = false; showMsg("msg", a.error || ""); return; }
|
||||||
|
hideMsg("msg"); await load(); openTab(CUR); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var draw = e.target.closest("[data-draw]");
|
||||||
if (draw) {
|
if (draw) {
|
||||||
draw.disabled = true;
|
draw.disabled = true;
|
||||||
var d = await api("draw_storyboard", { draft_id: draw.getAttribute("data-draw") });
|
var d = await api("draw_storyboard", { draft_id: draw.getAttribute("data-draw") });
|
||||||
if (!d.ok) { draw.disabled = false; showMsg("msg", d.error || "That did not start."); return; }
|
if (!d.ok) { draw.disabled = false; showMsg("msg", d.error || ""); return; }
|
||||||
hideMsg("msg");
|
hideMsg("msg"); load(); return;
|
||||||
load();
|
}
|
||||||
|
|
||||||
|
var rev = e.target.closest("[data-review]");
|
||||||
|
if (rev) {
|
||||||
|
rev.disabled = true;
|
||||||
|
var v = await api("start_review", { run_id: runId });
|
||||||
|
if (!v.ok) { rev.disabled = false; showMsg("msg", v.error || ""); return; }
|
||||||
|
hideMsg("msg"); load(); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rvs = e.target.closest("[data-revise]");
|
||||||
|
if (rvs) {
|
||||||
|
rvs.disabled = true;
|
||||||
|
var w = await api("start_revision", { run_id: runId });
|
||||||
|
if (!w.ok) { rvs.disabled = false; showMsg("msg", w.error || ""); return; }
|
||||||
|
hideMsg("msg"); load(); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var film = e.target.closest("[data-film]");
|
||||||
|
if (film) {
|
||||||
|
film.disabled = true;
|
||||||
|
var f = await api("film_draft", { draft_id: film.getAttribute("data-film") });
|
||||||
|
if (!f.ok) { film.disabled = false; showMsg("msg", f.error || ""); return; }
|
||||||
|
showMsg("msg", "Filming " + f.shots + " shots, about $" + f.usd
|
||||||
|
+ ". It appears in My videos as it goes.", "ok");
|
||||||
|
setTimeout(function () { location.href = "/videos.html"; }, 2500);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var btn = e.target.closest ? e.target.closest(".play") : null;
|
var retry = e.target.closest("[data-retry]");
|
||||||
|
if (retry) {
|
||||||
|
retry.disabled = true;
|
||||||
|
var y = await api("retry_writer", { draft_id: retry.getAttribute("data-retry") });
|
||||||
|
if (!y.ok) { retry.disabled = false; showMsg("msg", y.error || ""); return; }
|
||||||
|
hideMsg("msg"); load(); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var btn = e.target.closest(".play");
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
var sid = btn.getAttribute("data-shot");
|
var sid = btn.getAttribute("data-shot");
|
||||||
btn.disabled = true; btn.innerHTML = "…";
|
btn.disabled = true; btn.innerHTML = "…";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue