book.html: let a book be named, because a filename is not a title
Uploading "Memory Road interior 12-28.pdf" produced a book, a run and a storyboard all headed "Memory Road interior 12-28". The title is derived from the filename because that is the only thing an upload carries, and publishers name files after print runs. Guessing harder is the wrong fix - stripping "interior 12-28" would be a rule that works on one file. Letting the author type the title takes eight lines and is right for every file. The author field goes in at the same time; it costs nothing and a trailer should know whose book it is.
This commit is contained in:
parent
c6788afba5
commit
fa1992f200
1 changed files with 39 additions and 7 deletions
46
book.html
46
book.html
|
|
@ -25,6 +25,9 @@
|
|||
border:1px dashed var(--line);border-radius:12px;padding:18px}
|
||||
.pick.on{border-color:var(--accent);border-style:solid}
|
||||
.pick .or{color:var(--muted);font-size:13px}
|
||||
.rename{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
|
||||
.rename input{font:inherit;font-size:13px;background:transparent;color:var(--ink);
|
||||
border:1px solid var(--line);border-radius:8px;padding:6px 9px}
|
||||
.writers{display:flex;flex-wrap:wrap;gap:10px;margin-top:8px}
|
||||
.wr{display:flex;gap:8px;align-items:center;border:1px solid var(--line);
|
||||
border-radius:10px;padding:9px 12px;cursor:pointer}
|
||||
|
|
@ -125,7 +128,7 @@ function readFileB64(file) {
|
|||
if (!email) return;
|
||||
navBar("trailer");
|
||||
|
||||
var BOOKS = [], PICKED = null, WRITERS = [], CHOSEN = {}, LEAD = "";
|
||||
var BOOKS = [], PICKED = null, WRITERS = [], CHOSEN = {}, LEAD = "", EDIT = null;
|
||||
var pollTimer = null;
|
||||
|
||||
// ---------------------------------------------------------------- books
|
||||
|
|
@ -141,17 +144,30 @@ function readFileB64(file) {
|
|||
} else {
|
||||
sub = "reading the manuscript…";
|
||||
}
|
||||
// A filename is not a title. Publishers name files after print runs, so
|
||||
// the derived title is a starting point the author can correct.
|
||||
var rename = EDIT === b.id
|
||||
? '<div class="rename">'
|
||||
+ '<input id="rt" value="' + esc(b.title || "") + '" placeholder="Title">'
|
||||
+ '<input id="ra" value="' + esc(b.author || "") + '" placeholder="Author">'
|
||||
+ '<button type="button" class="btn" data-save="' + esc(b.id) + '">Save</button>'
|
||||
+ '<button type="button" class="btn" data-cancel="1">Cancel</button>'
|
||||
+ '</div>'
|
||||
: '';
|
||||
return '<div class="bk" data-id="' + esc(b.id) + '">'
|
||||
+ '<div class="meta">'
|
||||
+ '<h3>' + esc(b.title || "Untitled") + '</h3>'
|
||||
+ '<div class="sub">' + sub + (b.created_at ? ' · ' + esc(when(b.created_at)) : '') + '</div>'
|
||||
+ '<div class="sub">' + (b.author ? esc(b.author) + ' · ' : '') + sub
|
||||
+ (b.created_at ? ' · ' + esc(when(b.created_at)) : '') + '</div>'
|
||||
+ (st === "failed" && b.note ? '<div class="why">' + esc(b.note) + '</div>' : '')
|
||||
+ rename
|
||||
+ '</div>'
|
||||
+ '<div class="acts">'
|
||||
+ '<span class="state ' + esc(st) + '">' + esc(st) + '</span>'
|
||||
+ (st === "ready"
|
||||
? '<button type="button" class="btn" data-pick="' + esc(b.id) + '">'
|
||||
+ (PICKED === b.id ? "Selected" : "Use this book") + '</button>'
|
||||
+ '<button type="button" class="btn" data-edit="' + esc(b.id) + '">Rename</button>'
|
||||
: '')
|
||||
+ '<button type="button" class="btn" data-del="' + esc(b.id) + '">Remove</button>'
|
||||
+ '</div></div>';
|
||||
|
|
@ -179,13 +195,26 @@ function readFileB64(file) {
|
|||
}
|
||||
|
||||
document.getElementById("books").addEventListener("click", async function (e) {
|
||||
var pick = e.target.getAttribute("data-pick");
|
||||
var del = e.target.getAttribute("data-del");
|
||||
var t = e.target;
|
||||
var pick = t.getAttribute("data-pick"), del = t.getAttribute("data-del");
|
||||
var edit = t.getAttribute("data-edit"), save = t.getAttribute("data-save");
|
||||
if (t.getAttribute("data-cancel")) { EDIT = null; paintBooks(); return; }
|
||||
if (edit) { EDIT = edit; paintBooks(); return; }
|
||||
if (save) {
|
||||
var title = document.getElementById("rt").value.trim();
|
||||
var author = document.getElementById("ra").value.trim();
|
||||
if (!title) { showMsg("msg", "A book needs a title."); return; }
|
||||
t.disabled = true;
|
||||
var u = await api("update_book", { book_id: save, title: title, author: author });
|
||||
if (!u.ok) { showMsg("msg", u.error || "That did not save."); t.disabled = false; return; }
|
||||
hideMsg("msg"); EDIT = null; loadBooks();
|
||||
return;
|
||||
}
|
||||
if (pick) { PICKED = pick; hideMsg("msg"); paintBooks(); paintQuote(); return; }
|
||||
if (del) {
|
||||
e.target.disabled = true;
|
||||
t.disabled = true;
|
||||
var r = await api("delete_book", { book_id: del });
|
||||
if (!r.ok) { showMsg("msg", r.error || "Could not remove that."); e.target.disabled = false; return; }
|
||||
if (!r.ok) { showMsg("msg", r.error || "Could not remove that."); t.disabled = false; return; }
|
||||
if (PICKED === del) PICKED = null;
|
||||
loadBooks();
|
||||
}
|
||||
|
|
@ -227,6 +256,9 @@ function readFileB64(file) {
|
|||
resetPick();
|
||||
if (!r.ok) { showMsg("msg", r.error || "That upload did not go through."); return; }
|
||||
PICKED = null;
|
||||
// Straight into rename: the derived title is a guess and this is the one
|
||||
// moment the author is looking at it.
|
||||
EDIT = r.book && r.book.id;
|
||||
loadBooks();
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +307,7 @@ function readFileB64(file) {
|
|||
// Writing is the cheap half. Drawing the storyboards is priced separately,
|
||||
// per writer, once you have read the scripts.
|
||||
el.innerHTML = n + " writer" + (n > 1 ? "s" : "")
|
||||
+ " · about $" + (n * 0.6).toFixed(2) + " to write"
|
||||
+ " · about $" + (n * 0.85).toFixed(2) + " to write a full-length novel"
|
||||
+ " · storyboards are priced separately once you have read them";
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue