Admin UI: allow MP4/WebM in billboard upload + video preview element
- Widen file input accept to include .webm/.mp4 - Add a <video> preview element alongside the <img> preview - Update label and help text to mention server-side MP4 conversion
This commit is contained in:
1 parent
0c5123e3a6
commit
2fe4d67518
1 file changed
+1
-147
+1
-147
@@ -1,147 +1 @@
|
|||||||
<!DOCTYPE html>
|
PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgPG1ldGEgY2hhcnNldD0idXRmLTgiIC8+CiAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xIiAvPgogIDx0aXRsZT5OZXdidXJ5IE5pZ2h0cyDigJQgQWRtaW48L3RpdGxlPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iL2Nzcy9hcHAuY3NzIiAvPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iL2Nzcy9hZG1pbi5jc3MiIC8+CjwvaGVhZD4KPGJvZHk+CiAgPCEtLSBMb2dpbiAtLT4KICA8ZGl2IGlkPSJsb2dpbiIgY2xhc3M9ImxvZ2luLXdyYXAiPgogICAgPGRpdiBjbGFzcz0ibG9naW4tY2FyZCI+CiAgICAgIDxoMSBjbGFzcz0ibG9naW4tdGl0bGUiPk5ld2J1cnk8c3Bhbj5OaWdodHM8L3NwYW4+PC9oMT4KICAgICAgPGRpdiBjbGFzcz0ibG9naW4tc3ViIG1vbm8iPkFETUlOIENPTlNPTEU8L2Rpdj4KICAgICAgPGxhYmVsIGZvcj0ibGctdXNlciI+VXNlcm5hbWU8L2xhYmVsPgogICAgICA8aW5wdXQgaWQ9ImxnLXVzZXIiIGF1dG9jb21wbGV0ZT0idXNlcm5hbWUiIC8+CiAgICAgIDxsYWJlbCBmb3I9ImxnLXBhc3MiPlBhc3N3b3JkPC9sYWJlbD4KICAgICAgPGlucHV0IGlkPSJsZy1wYXNzIiB0eXBlPSJwYXNzd29yZCIgYXV0b2NvbXBsZXRlPSJjdXJyZW50LXBhc3N3b3JkIiAvPgogICAgICA8YnV0dG9uIGNsYXNzPSJwcmltYXJ5IiBpZD0ibGctZ28iIHN0eWxlPSJ3aWR0aDoxMDAlO21hcmdpbi10b3A6MTRweCI+U2lnbiBpbjwvYnV0dG9uPgogICAgICA8ZGl2IGlkPSJsZy1lcnJvciIgY2xhc3M9ImxnLWVycm9yIGhpZGRlbiI+PC9kaXY+CiAgICA8L2Rpdj4KICA8L2Rpdj4KCiAgPCEtLSBBcHAgLS0+CiAgPGRpdiBpZD0iYXBwIiBjbGFzcz0iaGlkZGVuIj4KICAgIDxoZWFkZXIgY2xhc3M9InRvcGJhciI+CiAgICAgIDxkaXYgY2xhc3M9ImJyYW5kIj5OZXdidXJ5PHNwYW4+TmlnaHRzPC9zcGFuPiA8c3BhbiBjbGFzcz0iYmFkZ2UgbW9ubyI+QURNSU48L3NwYW4+PC9kaXY+CiAgICAgIDxuYXYgY2xhc3M9InRhYnMiPgogICAgICAgIDxidXR0b24gY2xhc3M9InRhYiBhY3RpdmUiIGRhdGEtdGFiPSJnaG9zdHMiPkdob3N0czwvYnV0dG9uPgogICAgICAgIDxidXR0b24gY2xhc3M9InRhYiIgZGF0YS10YWI9InNldHMiPlNldHM8L2J1dHRvbj4KICAgICAgICA8YnV0dG9uIGNsYXNzPSJ0YWIiIGRhdGEtdGFiPSJhY2NvdW50Ij5BY2NvdW50PC9idXR0b24+CiAgICAgIDwvbmF2PgogICAgICA8YnV0dG9uIGlkPSJsb2dvdXQiIGNsYXNzPSJzbWFsbCI+U2lnbiBvdXQ8L2J1dHRvbj4KICAgIDwvaGVhZGVyPgoKICAgIDwhLS0gR0hPU1RTIC0tPgogICAgPHNlY3Rpb24gaWQ9InRhYi1naG9zdHMiIGNsYXNzPSJ0YWItcGFuZWwiPgogICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkIj4KICAgICAgICA8aDI+R2hvc3RzPC9oMj4KICAgICAgICA8ZGl2IGNsYXNzPSJoZWFkLWFjdGlvbnMiPgogICAgICAgICAgPGlucHV0IGlkPSJnaG9zdC1zZWFyY2giIHBsYWNlaG9sZGVyPSJTZWFyY2ggbmFtZSAvIGFiaWxpdHnigKYiIHN0eWxlPSJ3aWR0aDoyMjBweCIgLz4KICAgICAgICAgIDxidXR0b24gY2xhc3M9InByaW1hcnkiIGlkPSJuZXctZ2hvc3QiPisgTmV3IGdob3N0PC9idXR0b24+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGNsYXNzPSJ0YWJsZS13cmFwIj4KICAgICAgICA8dGFibGUgaWQ9Imdob3N0cy10YWJsZSI+CiAgICAgICAgICA8dGhlYWQ+CiAgICAgICAgICAgIDx0cj48dGg+PC90aD48dGg+TmFtZSAvIERpc3BsYXk8L3RoPjx0aD5UeXBlPC90aD48dGg+UmFyaXR5PC90aD48dGg+SFA8L3RoPjx0aD5ETUc8L3RoPjx0aD5BYmlsaXR5PC90aD48dGg+U2V0PC90aD48dGg+T248L3RoPjx0aD48L3RoPjwvdHI+CiAgICAgICAgICA8L3RoZWFkPgogICAgICAgICAgPHRib2R5PjwvdGJvZHk+CiAgICAgICAgPC90YWJsZT4KICAgICAgPC9kaXY+CiAgICA8L3NlY3Rpb24+CgogICAgPCEtLSBTRVRTIC0tPgogICAgPHNlY3Rpb24gaWQ9InRhYi1zZXRzIiBjbGFzcz0idGFiLXBhbmVsIGhpZGRlbiI+CiAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWhlYWQiPgogICAgICAgIDxoMj5TZXRzPC9oMj4KICAgICAgICA8YnV0dG9uIGNsYXNzPSJwcmltYXJ5IiBpZD0ibmV3LXNldCI+KyBOZXcgc2V0PC9idXR0b24+CiAgICAgIDwvZGl2PgogICAgICA8ZGl2IGlkPSJzZXRzLWxpc3QiIGNsYXNzPSJzZXRzLWxpc3QiPjwvZGl2PgogICAgPC9zZWN0aW9uPgoKICAgIDwhLS0gQUNDT1VOVCAtLT4KICAgIDxzZWN0aW9uIGlkPSJ0YWItYWNjb3VudCIgY2xhc3M9InRhYi1wYW5lbCBoaWRkZW4iPgogICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkIj48aDI+QWNjb3VudDwvaDI+PC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9ImFjY291bnQtY2FyZCI+CiAgICAgICAgPHAgY2xhc3M9Im11dGVkIj5TaWduZWQgaW4gYXMgPHN0cm9uZyBpZD0iYWNjdC11c2VyIj7igJQ8L3N0cm9uZz4uIENoYW5nZSB5b3VyIHBhc3N3b3JkIGJlbG93LjwvcD4KICAgICAgICA8bGFiZWw+Q3VycmVudCBwYXNzd29yZDwvbGFiZWw+PGlucHV0IGlkPSJjcC1jdXJyZW50IiB0eXBlPSJwYXNzd29yZCIgLz4KICAgICAgICA8bGFiZWw+TmV3IHBhc3N3b3JkIChtaW4gOCBjaGFycyk8L2xhYmVsPjxpbnB1dCBpZD0iY3AtbmV3IiB0eXBlPSJwYXNzd29yZCIgLz4KICAgICAgICA8YnV0dG9uIGNsYXNzPSJwcmltYXJ5IiBpZD0iY3AtZ28iIHN0eWxlPSJtYXJnaW4tdG9wOjEycHgiPlVwZGF0ZSBwYXNzd29yZDwvYnV0dG9uPgogICAgICAgIDxkaXYgaWQ9ImNwLW1zZyIgY2xhc3M9ImNwLW1zZyBoaWRkZW4iPjwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvc2VjdGlvbj4KICA8L2Rpdj4KCiAgPCEtLSBHaG9zdCBlZGl0b3IgbW9kYWwgLS0+CiAgPGRpdiBpZD0iZ2hvc3QtbW9kYWwiIGNsYXNzPSJtb2RhbCBoaWRkZW4iPgogICAgPGRpdiBjbGFzcz0ibW9kYWwtY2FyZCI+CiAgICAgIDxoMyBpZD0iZ20tdGl0bGUiPkVkaXQgZ2hvc3Q8L2gzPgogICAgICA8ZGl2IGNsYXNzPSJncmlkMiI+CiAgICAgICAgPGRpdj48bGFiZWw+TmFtZTwvbGFiZWw+PGlucHV0IGlkPSJnbS1uYW1lIiAvPjwvZGl2PgogICAgICAgIDxkaXY+PGxhYmVsPkRpc3BsYXkgbmFtZSAobG9jay1vbiBsYWJlbCk8L2xhYmVsPjxpbnB1dCBpZD0iZ20tZGlzcGxheSIgLz48L2Rpdj4KICAgICAgICA8ZGl2PjxsYWJlbD5UeXBlPC9sYWJlbD4KICAgICAgICAgIDxzZWxlY3QgaWQ9ImdtLXR5cGUiPjxvcHRpb24gdmFsdWU9InJlZCI+UmVkPC9vcHRpb24+PG9wdGlvbiB2YWx1ZT0ieWVsbG93Ij5ZZWxsb3c8L29wdGlvbj48b3B0aW9uIHZhbHVlPSJibHVlIj5CbHVlPC9vcHRpb24+PC9zZWxlY3Q+CiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdj48bGFiZWw+UmFyaXR5ICgx4oCTNCk8L2xhYmVsPjxpbnB1dCBpZD0iZ20tcmFyaXR5IiB0eXBlPSJudW1iZXIiIG1pbj0iMSIgbWF4PSI0IiAvPjwvZGl2PgogICAgICAgIDxkaXY+PGxhYmVsPkhlYWx0aDwvbGFiZWw+PGlucHV0IGlkPSJnbS1oZWFsdGgiIHR5cGU9Im51bWJlciIgLz48L2Rpdj4KICAgICAgICA8ZGl2PjxsYWJlbD5EYW1hZ2U8L2xhYmVsPjxpbnB1dCBpZD0iZ20tZGFtYWdlIiB0eXBlPSJudW1iZXIiIC8+PC9kaXY+CiAgICAgICAgPGRpdj48bGFiZWw+U3BlZWQgKDDigJM1KTwvbGFiZWw+PGlucHV0IGlLine truncated
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<title>Newbury Nights — Admin</title>
|
|
||||||
<link rel="stylesheet" href="/css/app.css" />
|
|
||||||
<link rel="stylesheet" href="/css/admin.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- Login -->
|
|
||||||
<div id="login" class="login-wrap">
|
|
||||||
<div class="login-card">
|
|
||||||
<h1 class="login-title">Newbury<span>Nights</span></h1>
|
|
||||||
<div class="login-sub mono">ADMIN CONSOLE</div>
|
|
||||||
<label for="lg-user">Username</label>
|
|
||||||
<input id="lg-user" autocomplete="username" />
|
|
||||||
<label for="lg-pass">Password</label>
|
|
||||||
<input id="lg-pass" type="password" autocomplete="current-password" />
|
|
||||||
<button class="primary" id="lg-go" style="width:100%;margin-top:14px">Sign in</button>
|
|
||||||
<div id="lg-error" class="lg-error hidden"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- App -->
|
|
||||||
<div id="app" class="hidden">
|
|
||||||
<header class="topbar">
|
|
||||||
<div class="brand">Newbury<span>Nights</span> <span class="badge mono">ADMIN</span></div>
|
|
||||||
<nav class="tabs">
|
|
||||||
<button class="tab active" data-tab="ghosts">Ghosts</button>
|
|
||||||
<button class="tab" data-tab="sets">Sets</button>
|
|
||||||
<button class="tab" data-tab="account">Account</button>
|
|
||||||
</nav>
|
|
||||||
<button id="logout" class="small">Sign out</button>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- GHOSTS -->
|
|
||||||
<section id="tab-ghosts" class="tab-panel">
|
|
||||||
<div class="panel-head">
|
|
||||||
<h2>Ghosts</h2>
|
|
||||||
<div class="head-actions">
|
|
||||||
<input id="ghost-search" placeholder="Search name / ability…" style="width:220px" />
|
|
||||||
<button class="primary" id="new-ghost">+ New ghost</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-wrap">
|
|
||||||
<table id="ghosts-table">
|
|
||||||
<thead>
|
|
||||||
<tr><th></th><th>Name / Display</th><th>Type</th><th>Rarity</th><th>HP</th><th>DMG</th><th>Ability</th><th>Set</th><th>On</th><th></th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody></tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- SETS -->
|
|
||||||
<section id="tab-sets" class="tab-panel hidden">
|
|
||||||
<div class="panel-head">
|
|
||||||
<h2>Sets</h2>
|
|
||||||
<button class="primary" id="new-set">+ New set</button>
|
|
||||||
</div>
|
|
||||||
<div id="sets-list" class="sets-list"></div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ACCOUNT -->
|
|
||||||
<section id="tab-account" class="tab-panel hidden">
|
|
||||||
<div class="panel-head"><h2>Account</h2></div>
|
|
||||||
<div class="account-card">
|
|
||||||
<p class="muted">Signed in as <strong id="acct-user">—</strong>. Change your password below.</p>
|
|
||||||
<label>Current password</label><input id="cp-current" type="password" />
|
|
||||||
<label>New password (min 8 chars)</label><input id="cp-new" type="password" />
|
|
||||||
<button class="primary" id="cp-go" style="margin-top:12px">Update password</button>
|
|
||||||
<div id="cp-msg" class="cp-msg hidden"></div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Ghost editor modal -->
|
|
||||||
<div id="ghost-modal" class="modal hidden">
|
|
||||||
<div class="modal-card">
|
|
||||||
<h3 id="gm-title">Edit ghost</h3>
|
|
||||||
<div class="grid2">
|
|
||||||
<div><label>Name</label><input id="gm-name" /></div>
|
|
||||||
<div><label>Display name (lock-on label)</label><input id="gm-display" /></div>
|
|
||||||
<div><label>Type</label>
|
|
||||||
<select id="gm-type"><option value="red">Red</option><option value="yellow">Yellow</option><option value="blue">Blue</option></select>
|
|
||||||
</div>
|
|
||||||
<div><label>Rarity (1–4)</label><input id="gm-rarity" type="number" min="1" max="4" /></div>
|
|
||||||
<div><label>Health</label><input id="gm-health" type="number" /></div>
|
|
||||||
<div><label>Damage</label><input id="gm-damage" type="number" /></div>
|
|
||||||
<div><label>Speed (0–5)</label><input id="gm-speed" type="number" min="0" max="5" /></div>
|
|
||||||
<div><label>Range (0–5)</label><input id="gm-range" type="number" min="0" max="5" /></div>
|
|
||||||
<div><label>Charge shot (0–3)</label><input id="gm-charge" type="number" min="0" max="3" /></div>
|
|
||||||
<div><label>Ability</label><input id="gm-ability" /></div>
|
|
||||||
<div><label>Set number (ref)</label><input id="gm-setnum" /></div>
|
|
||||||
<div><label>Set name (ref)</label><input id="gm-setname" /></div>
|
|
||||||
</div>
|
|
||||||
<div class="checks">
|
|
||||||
<label class="chk"><input type="checkbox" id="gm-boss" /> Boss ghost</label>
|
|
||||||
<label class="chk"><input type="checkbox" id="gm-enabled" checked /> Enabled</label>
|
|
||||||
</div>
|
|
||||||
<div class="image-row">
|
|
||||||
<label>Billboard image (GIF / PNG)</label>
|
|
||||||
<div class="row">
|
|
||||||
<input id="gm-file" type="file" accept=".gif,.png,.jpg,.jpeg,.webp" />
|
|
||||||
<img id="gm-preview" class="gm-preview hidden" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="muted" style="font-size:11px;margin-top:4px">Upload happens after you save the ghost.</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-actions">
|
|
||||||
<button data-close>Cancel</button>
|
|
||||||
<button class="primary" id="gm-save">Save</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Set editor modal -->
|
|
||||||
<div id="set-modal" class="modal hidden">
|
|
||||||
<div class="modal-card">
|
|
||||||
<h3 id="sm-title">Edit set</h3>
|
|
||||||
<div class="grid2">
|
|
||||||
<div><label>Scan code (QR payload)</label><input id="sm-code" placeholder="NN-70419" /></div>
|
|
||||||
<div><label>Set number (ref)</label><input id="sm-setnum" /></div>
|
|
||||||
<div><label>Set name</label><input id="sm-setname" /></div>
|
|
||||||
<div><label>Boss ghost</label><select id="sm-boss"><option value="">— none —</option></select></div>
|
|
||||||
</div>
|
|
||||||
<label class="chk"><input type="checkbox" id="sm-enabled" checked /> Enabled</label>
|
|
||||||
<div class="roster-pick">
|
|
||||||
<label>Roster (ghosts returned on scan)</label>
|
|
||||||
<input id="sm-roster-search" placeholder="Filter ghosts…" />
|
|
||||||
<div id="sm-roster" class="roster-checklist"></div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-actions">
|
|
||||||
<button data-close>Cancel</button>
|
|
||||||
<button class="primary" id="sm-save">Save set</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="disclaimer">
|
|
||||||
Fan-made tribute. Not affiliated with, sponsored by, or endorsed by the LEGO Group.
|
|
||||||
LEGO® and Hidden Side™ are trademarks of the LEGO Group.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="module" src="/js/admin.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in new issue
Block a user