Created
July 8, 2026 01:23
-
-
Save simsong/f9f87c1fcaf5a398fec69a6dcabcfc74 to your computer and use it in GitHub Desktop.
Codex-created Plant Tracer admin UI wireframe for Plant-Tracer/webapp#1106
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en" data-theme="winter"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Plant Tracer Admin UI Wireframe</title> | |
| <link href="https://cdn.jsdelivr.net/npm/daisyui@4.12.24/dist/full.min.css" rel="stylesheet" type="text/css"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <style> | |
| html { | |
| scroll-behavior: smooth; | |
| } | |
| section { | |
| scroll-margin-top: 1rem; | |
| } | |
| .course-chip-primary { | |
| box-shadow: 0 0 0 2px #111827 inset; | |
| } | |
| .course-chip-admin { | |
| box-shadow: 0 0 0 2px #111827 inset, 0 0 0 4px #ef4444 inset; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-slate-50 text-slate-900"> | |
| <div class="min-h-screen"> | |
| <header class="sticky top-0 z-40 border-b border-slate-200 bg-white/95 backdrop-blur"> | |
| <div class="flex items-center justify-between px-6 py-3"> | |
| <div> | |
| <div class="text-xl font-semibold tracking-normal">Plant Tracer Admin</div> | |
| <div class="text-sm text-slate-500">Review prototype for /admin</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="badge badge-error font-semibold text-white">super_admin</span> | |
| <button class="btn btn-sm btn-ghost">Sign out</button> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="grid grid-cols-[15rem_minmax(0,1fr)] gap-6 px-6 py-6"> | |
| <aside class="sticky top-20 h-[calc(100vh-6rem)]"> | |
| <nav class="menu rounded-box border border-slate-200 bg-white p-3 shadow-sm"> | |
| <li class="menu-title">Admin</li> | |
| <li><a href="#courses" class="active">Courses</a></li> | |
| <li><a href="#users">Users</a></li> | |
| <li><a href="#movies">Movies</a></li> | |
| <li><a href="#storage">Storage</a></li> | |
| </nav> | |
| <div class="mt-4 rounded-box border border-slate-200 bg-white p-4 text-sm shadow-sm"> | |
| <div class="font-semibold">Current Scan</div> | |
| <div class="mt-2 text-slate-600">Not running</div> | |
| <progress class="progress progress-info mt-3 w-full" value="0" max="100"></progress> | |
| </div> | |
| </aside> | |
| <main class="space-y-8"> | |
| <div class="grid grid-cols-4 gap-4"> | |
| <div class="stat rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="stat-title">Courses</div> | |
| <div class="stat-value text-3xl">18</div> | |
| </div> | |
| <div class="stat rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="stat-title">Users</div> | |
| <div class="stat-value text-3xl">412</div> | |
| </div> | |
| <div class="stat rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="stat-title">Movies</div> | |
| <div class="stat-value text-3xl">9,244</div> | |
| </div> | |
| <div class="stat rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="stat-title">Storage</div> | |
| <div class="stat-value text-2xl">Scan not run</div> | |
| </div> | |
| </div> | |
| <section id="courses" class="rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="flex items-start justify-between border-b border-slate-200 p-5"> | |
| <div> | |
| <h1 class="text-2xl font-semibold">Courses</h1> | |
| <p class="mt-1 text-sm text-slate-500">Create, rename, delete, and manage course membership.</p> | |
| </div> | |
| <button class="btn btn-primary btn-sm">Create course</button> | |
| </div> | |
| <div class="p-5"> | |
| <div class="mb-4 flex items-center gap-3"> | |
| <input class="input input-bordered input-sm w-72" placeholder="Search courses"> | |
| <button class="btn btn-sm">Show empty</button> | |
| <button class="btn btn-sm">Show with movies</button> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="table table-zebra"> | |
| <thead> | |
| <tr> | |
| <th>Course number</th> | |
| <th>Name</th> | |
| <th>Users</th> | |
| <th>Movies</th> | |
| <th>Admins</th> | |
| <th class="w-72">Inline editor</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td class="font-mono">BIO101</td> | |
| <td>Biology 101</td> | |
| <td>42</td> | |
| <td>612</td> | |
| <td>Ada Lovelace, Kim Park</td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs">Rename number/name</button> | |
| <button class="btn join-item btn-xs">Members</button> | |
| <button class="btn join-item btn-xs btn-error text-white" disabled>Delete course</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr class="bg-blue-50"> | |
| <td colspan="6"> | |
| <div class="rounded-box border border-blue-200 bg-white p-4"> | |
| <div class="mb-3 flex items-center justify-between"> | |
| <div class="font-semibold">BIO101 membership editor</div> | |
| <button class="btn btn-xs btn-ghost">Close</button> | |
| </div> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div> | |
| <div class="mb-2 text-sm font-semibold">Admins</div> | |
| <div class="flex flex-wrap gap-2"> | |
| <span class="badge badge-error gap-2 text-white">Ada Lovelace ×</span> | |
| <span class="badge badge-error gap-2 text-white">Kim Park ×</span> | |
| <button class="btn btn-xs">Add admin</button> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="mb-2 text-sm font-semibold">Course number/name</div> | |
| <div class="grid grid-cols-[10rem_minmax(0,1fr)_auto] gap-2"> | |
| <input class="input input-bordered input-sm" value="BIO101" aria-label="Course number"> | |
| <input class="input input-bordered input-sm" value="Biology 101" aria-label="Course name"> | |
| <button class="btn btn-sm btn-primary">Save</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td class="font-mono">CHEM10</td> | |
| <td>Chemistry Lab</td> | |
| <td>18</td> | |
| <td>0</td> | |
| <td>Sam Rivera</td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs">Rename number/name</button> | |
| <button class="btn join-item btn-xs">Members</button> | |
| <button class="btn join-item btn-xs btn-error text-white" data-confirm-target="delete-course-chemlist">Delete course</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr id="delete-course-chemlist" class="hidden bg-red-50"> | |
| <td colspan="6"> | |
| <div class="flex items-center justify-between rounded-box border border-red-200 bg-white p-4"> | |
| <div> | |
| <div class="font-semibold text-red-700">Delete course CHEM10?</div> | |
| <div class="text-sm text-slate-600">This course has no movies. Users whose last course is CHEM10 will be deleted.</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="countdown-label text-sm text-slate-600">Confirm enabled in 5s</span> | |
| <button class="btn btn-sm btn-error text-white confirm-button" disabled>Confirm delete course</button> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="users" class="rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="flex items-start justify-between border-b border-slate-200 p-5"> | |
| <div> | |
| <h1 class="text-2xl font-semibold">Users</h1> | |
| <p class="mt-1 text-sm text-slate-500">Edit course membership, primary course, admin status, and super role.</p> | |
| </div> | |
| <button class="btn btn-primary btn-sm">Add user</button> | |
| </div> | |
| <div class="p-5"> | |
| <div class="mb-4 flex flex-wrap items-center gap-3"> | |
| <input class="input input-bordered input-sm w-72" placeholder="Search users"> | |
| <select class="select select-bordered select-sm"> | |
| <option>All courses</option> | |
| <option>BIO101</option> | |
| <option>CHEM10</option> | |
| </select> | |
| <select class="select select-bordered select-sm"> | |
| <option>All super roles</option> | |
| <option>no</option> | |
| <option>auditor</option> | |
| <option>admin</option> | |
| </select> | |
| <button class="btn btn-sm">Add selected to course</button> | |
| <button class="btn btn-sm btn-error text-white" data-confirm-target="delete-selected-users">Delete selected users</button> | |
| </div> | |
| <div id="delete-selected-users" class="mb-4 hidden rounded-box border border-red-200 bg-red-50 p-4"> | |
| <div class="flex items-center justify-between gap-4"> | |
| <div> | |
| <div class="font-semibold text-red-700">Delete selected users?</div> | |
| <div class="text-sm text-slate-600">This deletes user accounts, not just course memberships.</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="countdown-label text-sm text-slate-600">Confirm enabled in 5s</span> | |
| <button class="btn btn-sm btn-error text-white confirm-button" disabled>Confirm delete users</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="table table-zebra"> | |
| <thead> | |
| <tr> | |
| <th><input type="checkbox" class="checkbox checkbox-sm"></th> | |
| <th>Name</th> | |
| <th>Email</th> | |
| <th>Super</th> | |
| <th>Courses</th> | |
| <th class="w-64">Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td>Ada Lovelace</td> | |
| <td>ada@example.edu</td> | |
| <td> | |
| <details class="dropdown"> | |
| <summary class="btn btn-xs btn-error font-bold text-white">admin</summary> | |
| <ul class="menu dropdown-content z-10 mt-1 w-36 rounded-box bg-white p-2 shadow"> | |
| <li><a>no</a></li> | |
| <li><a class="font-bold text-blue-700">auditor</a></li> | |
| <li><a class="font-bold text-red-700">admin</a></li> | |
| </ul> | |
| </details> | |
| </td> | |
| <td> | |
| <div class="flex flex-wrap gap-2"> | |
| <span class="badge course-chip-admin">BIO101 admin primary</span> | |
| <span class="badge">PHY200</span> | |
| </div> | |
| </td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs">Edit courses</button> | |
| <button class="btn join-item btn-xs btn-error text-white" data-confirm-target="delete-user-ada">Delete user</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr id="delete-user-ada" class="hidden bg-red-50"> | |
| <td colspan="6"> | |
| <div class="flex items-center justify-between rounded-box border border-red-200 bg-white p-4"> | |
| <div> | |
| <div class="font-semibold text-red-700">Delete user Ada Lovelace?</div> | |
| <div class="text-sm text-slate-600">Five-second delay prevents accidental account deletion.</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="countdown-label text-sm text-slate-600">Confirm enabled in 5s</span> | |
| <button class="btn btn-sm btn-error text-white confirm-button" disabled>Confirm delete user</button> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td>Grace Hopper</td> | |
| <td>grace@example.edu</td> | |
| <td><span class="badge badge-info font-bold text-white">auditor</span></td> | |
| <td> | |
| <div class="flex flex-wrap gap-2"> | |
| <span class="badge course-chip-primary">BIO101 primary</span> | |
| <span class="badge">CHEM10</span> | |
| </div> | |
| </td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs">Edit courses</button> | |
| <button class="btn join-item btn-xs btn-error text-white">Delete user</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr class="bg-blue-50"> | |
| <td colspan="6"> | |
| <div class="rounded-box border border-blue-200 bg-white p-4"> | |
| <div class="mb-3 flex items-center justify-between"> | |
| <div class="font-semibold">Edit Grace Hopper courses</div> | |
| <button class="btn btn-xs btn-ghost">Close</button> | |
| </div> | |
| <div class="flex flex-wrap items-center gap-2"> | |
| <span class="badge course-chip-primary">BIO101 primary</span> | |
| <span class="badge">CHEM10</span> | |
| <button class="btn btn-xs">Add course</button> | |
| <button class="btn btn-xs">Set selected primary</button> | |
| <button class="btn btn-xs btn-error text-white">Remove selected</button> | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td>Pat Lee</td> | |
| <td>pat@example.edu</td> | |
| <td><span class="badge">no</span></td> | |
| <td><span class="badge course-chip-primary">CHEM10 primary</span></td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs">Edit courses</button> | |
| <button class="btn join-item btn-xs btn-error text-white">Delete user</button> | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="movies" class="rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="flex items-start justify-between border-b border-slate-200 p-5"> | |
| <div> | |
| <h1 class="text-2xl font-semibold">Movies</h1> | |
| <p class="mt-1 text-sm text-slate-500">Per-course subtables are collapsed by default and lazy-loaded on expand.</p> | |
| </div> | |
| <div class="flex gap-2"> | |
| <button id="expand-all-movies" class="btn btn-sm">Expand all</button> | |
| <button class="btn btn-sm btn-error text-white">Purge deleted in all courses</button> | |
| </div> | |
| </div> | |
| <div class="space-y-4 p-5"> | |
| <div class="collapse-arrow collapse border border-slate-200 bg-slate-50"> | |
| <input type="checkbox" class="movie-course-toggle"> | |
| <div class="collapse-title flex items-center justify-between text-lg font-semibold"> | |
| <span>BIO101 - Biology 101</span> | |
| <span class="mr-8 flex gap-2 text-sm font-normal"> | |
| <span class="badge">612 movies</span> | |
| <span class="badge badge-warning">3 stale</span> | |
| </span> | |
| </div> | |
| <div class="collapse-content"> | |
| <div class="mb-3 flex flex-wrap items-center justify-between gap-3"> | |
| <div class="flex gap-2"> | |
| <input class="input input-bordered input-sm w-64" placeholder="Search BIO101 movies"> | |
| <button class="btn btn-sm">Publish</button> | |
| <button class="btn btn-sm">Unpublish</button> | |
| <button class="btn btn-sm">Move course</button> | |
| <button class="btn btn-sm">Assign owner</button> | |
| </div> | |
| <button class="btn btn-sm btn-error text-white">Purge deleted in BIO101</button> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="table table-sm"> | |
| <thead> | |
| <tr> | |
| <th><input type="checkbox" class="checkbox checkbox-sm"></th> | |
| <th>State</th> | |
| <th>Movie</th> | |
| <th>Owner</th> | |
| <th>MP4</th> | |
| <th>ZIP</th> | |
| <th>Research</th> | |
| <th>Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td><span class="badge badge-success text-white">published</span></td> | |
| <td>stem-growth-042.mp4</td> | |
| <td>Ada Lovelace</td> | |
| <td>32.1 MB</td> | |
| <td>4.2 MB</td> | |
| <td>allowed; MIT</td> | |
| <td><button class="btn btn-xs">Edit inline</button></td> | |
| </tr> | |
| <tr class="bg-red-50 text-red-900"> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td><span class="badge badge-error text-white">stale upload</span></td> | |
| <td>pending-upload-118</td> | |
| <td>Pat Lee</td> | |
| <td>missing</td> | |
| <td>-</td> | |
| <td>-</td> | |
| <td><button class="btn btn-xs btn-error text-white">Remove red movies</button></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="collapse-arrow collapse border border-slate-200 bg-slate-50"> | |
| <input type="checkbox" class="movie-course-toggle"> | |
| <div class="collapse-title flex items-center justify-between text-lg font-semibold"> | |
| <span>CHEM10 - Chemistry Lab</span> | |
| <span class="mr-8 flex gap-2 text-sm font-normal"> | |
| <span class="badge">0 movies</span> | |
| <span class="badge badge-success text-white">empty</span> | |
| </span> | |
| </div> | |
| <div class="collapse-content"> | |
| <div class="alert justify-between"> | |
| <span>No movies in this course. The course can be deleted if no other constraints apply.</span> | |
| <button class="btn btn-sm btn-error text-white" data-confirm-target="delete-course-chem10">Delete course</button> | |
| </div> | |
| <div id="delete-course-chem10" class="mt-3 hidden rounded-box border border-red-200 bg-white p-4"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <div class="font-semibold text-red-700">Delete CHEM10?</div> | |
| <div class="text-sm text-slate-600">This deletes the empty course; users with no other course are deleted.</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="countdown-label text-sm text-slate-600">Confirm enabled in 5s</span> | |
| <button class="btn btn-sm btn-error text-white confirm-button" disabled>Confirm delete course</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="storage" class="rounded-box border border-slate-200 bg-white shadow-sm"> | |
| <div class="flex items-start justify-between border-b border-slate-200 p-5"> | |
| <div> | |
| <h1 class="text-2xl font-semibold">Storage</h1> | |
| <p class="mt-1 text-sm text-slate-500">Scan S3, recover orphaned movie data, and delete objects that cannot be recovered.</p> | |
| </div> | |
| <div class="flex gap-2"> | |
| <button class="btn btn-sm btn-primary">Start scan</button> | |
| <button class="btn btn-sm">Continue scan</button> | |
| <button class="btn btn-sm">Export all storage CSV</button> | |
| </div> | |
| </div> | |
| <div class="space-y-5 p-5"> | |
| <div class="rounded-box border border-slate-200 bg-slate-50 p-4"> | |
| <div class="mb-2 flex items-center justify-between"> | |
| <span class="font-semibold">S3 scan</span> | |
| <span class="text-sm text-slate-500">18,200 objects scanned; incomplete</span> | |
| </div> | |
| <progress class="progress progress-info w-full" value="45" max="100"></progress> | |
| </div> | |
| <div class="flex flex-wrap gap-2"> | |
| <button class="btn btn-sm">Recover selected</button> | |
| <button class="btn btn-sm">Convert selected ZIPs</button> | |
| <button class="btn btn-sm btn-error text-white" data-confirm-target="delete-selected-storage">Delete selected</button> | |
| <button class="btn btn-sm btn-error text-white" data-confirm-target="delete-all-unrecognized">Delete all unrecognized</button> | |
| </div> | |
| <div id="delete-selected-storage" class="hidden rounded-box border border-red-200 bg-red-50 p-4"> | |
| <div class="flex items-center justify-between gap-4"> | |
| <div> | |
| <div class="font-semibold text-red-700">Delete selected storage objects?</div> | |
| <div class="text-sm text-slate-600">Deletion is final. Confirmation is disabled for five seconds.</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="countdown-label text-sm text-slate-600">Confirm enabled in 5s</span> | |
| <button class="btn btn-sm btn-error text-white confirm-button" disabled>Confirm delete selected</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="delete-all-unrecognized" class="hidden rounded-box border border-red-200 bg-red-50 p-4"> | |
| <div class="flex items-center justify-between gap-4"> | |
| <div> | |
| <div class="font-semibold text-red-700">Delete all unrecognized objects?</div> | |
| <div class="text-sm text-slate-600">This affects only objects classified as unrecognized by the current scan.</div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <span class="countdown-label text-sm text-slate-600">Confirm enabled in 5s</span> | |
| <button class="btn btn-sm btn-error text-white confirm-button" disabled>Confirm delete all</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="table table-zebra"> | |
| <thead> | |
| <tr> | |
| <th><input type="checkbox" class="checkbox checkbox-sm"></th> | |
| <th>Type</th> | |
| <th>Object / prefix</th> | |
| <th>Evidence</th> | |
| <th>Default recovery</th> | |
| <th class="w-80">Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td><span class="badge badge-success text-white">MP4 orphan</span></td> | |
| <td class="font-mono text-xs">lost/plant-growth-2026-07-01.mp4</td> | |
| <td>embedded metadata found</td> | |
| <td>BIO101, Ada Lovelace</td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs btn-success text-white">Recover</button> | |
| <button class="btn join-item btn-xs">Review</button> | |
| <button class="btn join-item btn-xs btn-error text-white" data-confirm-target="delete-selected-storage">Delete</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr class="bg-blue-50"> | |
| <td colspan="6"> | |
| <div class="rounded-box border border-blue-200 bg-white p-4"> | |
| <div class="mb-3 flex items-center justify-between"> | |
| <div class="font-semibold">One-click recovery preview</div> | |
| <button class="btn btn-xs btn-ghost">Close</button> | |
| </div> | |
| <div class="grid grid-cols-4 gap-3 text-sm"> | |
| <label class="form-control"> | |
| <span class="label-text">Course</span> | |
| <select class="select select-bordered select-sm"><option>BIO101</option></select> | |
| </label> | |
| <label class="form-control"> | |
| <span class="label-text">Owner</span> | |
| <select class="select select-bordered select-sm"><option>Ada Lovelace</option><option>Course admin</option></select> | |
| </label> | |
| <label class="form-control"> | |
| <span class="label-text">State</span> | |
| <select class="select select-bordered select-sm"><option>unpublished</option><option>published</option></select> | |
| </label> | |
| <label class="form-control"> | |
| <span class="label-text">Name</span> | |
| <input class="input input-bordered input-sm" value="plant-growth-2026-07-01"> | |
| </label> | |
| </div> | |
| <button class="btn btn-sm btn-success mt-4 text-white">Create movie record</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td><span class="badge badge-info text-white">ZIP-only</span></td> | |
| <td class="font-mono text-xs">uploads/frame-set-889.zip</td> | |
| <td>frame ZIP; no MP4</td> | |
| <td>Convert to MP4, assign to course admin</td> | |
| <td> | |
| <div class="join"> | |
| <button class="btn join-item btn-xs btn-info text-white">Convert</button> | |
| <button class="btn join-item btn-xs">Review</button> | |
| <button class="btn join-item btn-xs btn-error text-white" data-confirm-target="delete-selected-storage">Delete</button> | |
| </div> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td><span class="badge badge-warning">empty frame group</span></td> | |
| <td class="font-mono text-xs">movies/old-999/frames/</td> | |
| <td>no frames, no MP4, no ZIP</td> | |
| <td>none</td> | |
| <td><button class="btn btn-xs btn-error text-white" data-confirm-target="delete-selected-storage">Delete</button></td> | |
| </tr> | |
| <tr> | |
| <td><input type="checkbox" class="checkbox checkbox-sm"></td> | |
| <td><span class="badge">unrecognized</span></td> | |
| <td class="font-mono text-xs">tmp/debug-output.log</td> | |
| <td>not movie-like</td> | |
| <td>none</td> | |
| <td><button class="btn btn-xs btn-error text-white" data-confirm-target="delete-selected-storage">Delete</button></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| </main> | |
| </div> | |
| </div> | |
| <script> | |
| const expandAllMovies = document.getElementById('expand-all-movies'); | |
| if (expandAllMovies) { | |
| expandAllMovies.addEventListener('click', () => { | |
| document.querySelectorAll('.movie-course-toggle').forEach((toggle) => { | |
| toggle.checked = true; | |
| }); | |
| }); | |
| } | |
| document.querySelectorAll('[data-confirm-target]').forEach((button) => { | |
| button.addEventListener('click', () => { | |
| const target = document.getElementById(button.dataset.confirmTarget); | |
| if (!target) { | |
| return; | |
| } | |
| target.classList.remove('hidden'); | |
| const label = target.querySelector('.countdown-label'); | |
| const confirm = target.querySelector('.confirm-button'); | |
| if (!label || !confirm) { | |
| return; | |
| } | |
| confirm.disabled = true; | |
| let remaining = 5; | |
| label.textContent = `Confirm enabled in ${remaining}s`; | |
| const timer = window.setInterval(() => { | |
| remaining -= 1; | |
| if (remaining > 0) { | |
| label.textContent = `Confirm enabled in ${remaining}s`; | |
| return; | |
| } | |
| window.clearInterval(timer); | |
| label.textContent = 'Confirm is enabled'; | |
| confirm.disabled = false; | |
| }, 1000); | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment