Files
WarpBox/templates/index.html
Daniel Legt e330fb04b3 feat(ui): add clear queue flow and expose ISO expiry
- Add `formatBrowserTime()` and include ISO-8601 `expires_at` in box status JSON and `ExpiresAtISO` in the box view for browser-friendly rendering.
- Refresh UI styling (switch to MonoCraft/PixelOperatorMono, tweak base font size) and treat `aria-disabled="true"` like `disabled` for consistent button states.
- Introduce a clear-queue action with confirmation to reset upload state, unlock controls, and provide user feedback.feat(ui): add clear queue flow and expose ISO expiry

- Add `formatBrowserTime()` and include ISO-8601 `expires_at` in box status JSON and `ExpiresAtISO` in the box view for browser-friendly rendering.
- Refresh UI styling (switch to MonoCraft/PixelOperatorMono, tweak base font size) and treat `aria-disabled="true"` like `disabled` for consistent button states.
- Introduce a clear-queue action with confirmation to reset upload state, unlock controls, and provide user feedback.
2026-04-29 02:29:49 +03:00

244 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WarpBox</title>
<link rel="icon" type="image/png" href="/static/WarpBoxLogo.png">
<link rel="stylesheet" href="/static/css/app.css">
<link rel="stylesheet" href="/static/css/window.css">
<link rel="stylesheet" href="/static/css/upload.css">
</head>
<body>
<main class="upload-main">
<div class="desktop-wrap">
<section class="win98-window upload-window" aria-label="WarpBox upload window">
<div class="win98-titlebar upload-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/WarpBoxLogo.png" alt="" aria-hidden="true">
<h1>WarpBox</h1>
</div>
<div class="win98-window-controls" aria-label="Window controls">
<button class="win98-control win98-minimize" type="button" data-action="minimize" title="Minimize" aria-label="Minimize">_</button>
<button class="win98-control" type="button" data-action="toggle-fit" title="Fit window" aria-label="Maximize"></button>
<button class="win98-control" type="button" data-action="fake-close" title="Close" aria-label="Close">×</button>
</div>
</div>
<nav class="menu-bar" aria-label="Upload menu">
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>F</u>ile</button>
<div class="menu-popup" role="menu">
<button class="menu-action" type="button" data-action="browse"><img src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true"><span>Add files...</span><span class="shortcut">Ctrl+O</span></button>
<button class="menu-action" type="button" data-action="start-upload"><img src="/static/img/icons/check_mark_pixel.png" alt="" aria-hidden="true"><span>Start upload</span><span class="shortcut">Ctrl+U</span></button>
<div class="menu-separator"></div>
<button class="menu-action" type="button" data-action="clear"><img src="/static/img/icons/x_mark_pixel.png" alt="" aria-hidden="true"><span>Clear queue</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>B</u>ox</button>
<div class="menu-popup" role="menu">
<button class="menu-action" type="button" data-action="toggle-delete-once"><img src="/static/img/icons/recycle_bin_full_cool-5.png" alt="" aria-hidden="true"><span>One-time download</span><span></span></button>
<button class="menu-action" type="button" data-action="copy-link" aria-disabled="true" data-disabled-reason="There is no share URL yet. Start an upload first."><img src="/static/img/sprites/frame_web-0.png" alt="" aria-hidden="true"><span>Copy share URL</span><span class="shortcut">Ctrl+L</span></button>
<button class="menu-action" type="button" data-doc="dailyQuota"><img src="/static/img/icons/scanner_alt-3.png" alt="" aria-hidden="true"><span>Upload limits...</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>O</u>ptions</button>
<div class="menu-popup" role="menu">
<button class="menu-action" type="button" data-action="random-password"><img src="/static/img/sprites/file_padlock.png" alt="" aria-hidden="true"><span>Generate password</span><span></span></button>
<button class="menu-action" type="button" data-action="random-box-name"><img src="/static/img/icons/directory_closed-2.png" alt="" aria-hidden="true"><span>Random box name</span><span></span></button>
<button class="menu-action" type="button" data-action="clear-password"><img src="/static/img/icons/x_mark_pixel.png" alt="" aria-hidden="true"><span>Clear password</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false"><u>H</u>elp</button>
<div class="menu-popup" role="menu">
<button class="menu-action" type="button" data-action="help"><img src="/static/img/icons/tip.png" alt="" aria-hidden="true"><span>Show quick help</span><span>F1</span></button>
<button class="menu-action" type="button" data-doc="about"><img src="/static/WarpBoxLogo.png" alt="" aria-hidden="true"><span>About WarpBox</span><span></span></button>
</div>
</div>
</nav>
<form class="upload-form" id="upload-form" action="/box" method="post" data-uploads-enabled="{{ if .UploadsEnabled }}true{{ else }}false{{ end }}" data-max-file-bytes="{{ .MaxFileSizeBytes }}" data-max-box-bytes="{{ .MaxBoxSizeBytes }}" data-default-retention="{{ .DefaultRetention }}">
<div class="win98-panel upload-panel" id="drop-surface">
<header class="upload-header">
<div>
<p class="upload-heading">Upload files</p>
<p class="upload-subtext">Drop files into this window or browse from your computer. WarpBox creates a temporary share link when the upload finishes.</p>
</div>
<aside class="upload-quota" aria-label="Box space">
<strong>Box space</strong>
<span id="box-space-text">0 B</span>
<span class="upload-quota-track" aria-hidden="true"><span class="upload-quota-bar" id="box-space-bar"></span></span>
</aside>
</header>
<label class="upload-dropzone" for="file-upload" tabindex="1" id="dropzone" data-disabled-reason="The current box is sealed after upload. Press Clear to start a new box.">
<img class="upload-icon-img" src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true">
<span class="upload-primary">{{ if .UploadsEnabled }}Drop files here{{ else }}Guest uploads disabled{{ end }}</span>
<span class="upload-secondary">or <span class="upload-linklike">click to browse</span> from your computer</span>
<span class="upload-secondary" id="limit-hint">Links expire automatically</span>
<input class="upload-input" id="file-upload" name="files" type="file" multiple {{ if not .UploadsEnabled }}disabled{{ end }} data-disabled-reason="Guest uploads are disabled.">
</label>
<div class="upload-details">
<span class="upload-detail-label">Queue:</span>
<span id="queue-label">{{ if .UploadsEnabled }}No files selected{{ else }}Guest uploads are disabled{{ end }}</span>
<span class="upload-file-count" id="queue-size">0 B total</span>
</div>
<div class="upload-file-list" aria-label="Upload queue" id="file-list">
<p class="upload-empty-state">{{ if .UploadsEnabled }}No files in the box yet. Drop files here, use File &gt; Add files, or click the dropzone.{{ else }}Guest uploads are disabled.{{ end }}</p>
</div>
<div class="upload-result">
<span class="upload-result-label">Share URL:</span>
<a class="upload-result-link is-empty" id="share-link" href="#" aria-disabled="true">Not created yet</a>
<button class="win98-button upload-share-button" type="button" id="copy-button" aria-disabled="true" data-disabled-reason="There is no share URL yet. Start an upload first.">Copy</button>
</div>
</div>
<div class="upload-overall">
<span class="upload-overall-track" aria-label="Overall upload progress"><span class="upload-overall-bar" id="overall-bar"></span></span>
<span class="upload-overall-percent" id="overall-percent">0%</span>
</div>
<div class="upload-actions">
<button class="win98-button" type="button" data-action="clear">Clear</button>
<button class="win98-button start-upload-cta" type="submit" id="start-button" tabindex="4" aria-disabled="true" data-disabled-reason="There are no files selected. Please select files to upload.">Start upload</button>
</div>
</form>
<div class="win98-statusbar upload-statusbar">
<span id="status-text">{{ if .UploadsEnabled }}Ready · drag files anywhere onto the window{{ else }}Guest uploads are disabled{{ end }}</span>
<span>WarpBox</span>
</div>
</section>
<aside class="side-stack" aria-label="Secondary upload panels">
<section class="win98-window side-panel">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/scanner_alt-3.png" alt="" aria-hidden="true">
<h2>Box Options</h2>
</div>
<div class="win98-window-controls"><button class="win98-control" type="button" data-action="side-close" title="Close-ish">×</button></div>
</div>
<div class="win98-panel side-body">
<div class="box-options-form" id="box-options-form">
<label class="option-row">
<span>Expires:</span>
<select class="upload-select" id="expiry-select" name="retention_key" tabindex="2">
{{ range .RetentionOptions }}
<option value="{{ .Key }}" {{ if eq .Key $.DefaultRetention }}selected{{ end }}>{{ .Label }}</option>
{{ end }}
</select>
</label>
<label class="option-row">
<span>Password:</span>
<input class="upload-text-input" id="password-input" type="text" placeholder="optional" autocomplete="off" tabindex="3">
</label>
<label class="option-row">
<span>Max views:</span>
<input class="upload-text-input" id="max-views" type="number" min="1" max="9999" placeholder="local note" data-disabled-reason="">
</label>
<label class="option-row">
<span>Box name:</span>
<input class="upload-text-input" id="box-name" type="text" maxlength="42" placeholder="optional, normal text">
</label>
<label class="option-row">
<span>Custom slug:</span>
<input class="upload-text-input" id="custom-slug" type="text" maxlength="32" pattern="[a-z0-9-]*" placeholder="optional-slug">
</label>
<label class="option-check">
<input type="checkbox" id="download-page" checked>
<span>Generate download page</span>
</label>
<label class="option-check">
<input type="checkbox" id="allow-zip" checked>
<span>Allow Download Zip</span>
</label>
<label class="option-check">
<input type="checkbox" id="allow-preview" checked>
<span>Allow previews when possible</span>
</label>
<label class="option-check">
<input type="checkbox" id="keep-filenames" checked>
<span>Keep original filenames</span>
</label>
<label class="option-check">
<input type="checkbox" id="private-box">
<span>Hide from public listings</span>
</label>
<label class="option-check">
<input type="checkbox" id="api-key-mode">
<span>Use API key for larger quota</span>
</label>
<label class="option-row api-key-row" id="api-key-row">
<span>API key:</span>
<span class="api-key-field">
<input class="upload-text-input" id="api-key-input" type="password" placeholder="paste key when enabled" autocomplete="off" disabled data-disabled-reason="Enable Use API key for larger quota before typing an API key.">
<span class="api-key-state" id="api-key-state" aria-live="polite"></span>
</span>
</label>
</div>
</div>
</section>
<section class="win98-window side-panel">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/shell_window1.png" alt="" aria-hidden="true">
<h2>Terminal Upload</h2>
</div>
<div class="win98-window-controls"><button class="win98-control" type="button" data-action="side-help" title="Help-ish">?</button></div>
</div>
<div class="win98-panel side-body">
<div class="terminal-box" id="terminal-box" tabindex="0" aria-label="Terminal upload command"></div>
<div class="terminal-actions">
<button class="win98-button terminal-copy-button" type="button" id="copy-curl-button">Copy cURL command</button>
</div>
</div>
</section>
<section class="win98-window helper-window" aria-label="WarpBox help folder">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/tip.png" alt="" aria-hidden="true">
<h2>WarpBox Help Folder</h2>
</div>
<div class="win98-window-controls"><button class="win98-control" type="button" data-action="side-folder-close" title="Nope">×</button></div>
</div>
<div class="win98-panel helper-body">
<button class="folder-icon-button" type="button" data-doc="cli"><img src="/static/img/icons/directory_closed-2.png" alt="" aria-hidden="true"><span>CLI Guide</span></button>
<button class="folder-icon-button" type="button" data-doc="faq"><img src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true"><span>Help &amp; FAQ</span></button>
<button class="folder-icon-button" type="button" data-doc="examples"><img src="/static/img/icons/shell_window1.png" alt="" aria-hidden="true"><span>Examples</span></button>
<button class="folder-icon-button folder-icon-button-disabled" type="button" data-action="coming-soon"><img src="/static/WarpBoxLogo.png" alt="" aria-hidden="true"><span>WarpBox.exe</span></button>
</div>
</section>
</aside>
</div>
</main>
<div class="modal-backdrop" id="modal-backdrop"></div>
<section class="win98-window popup-window" id="doc-popup" aria-modal="true" role="dialog" aria-labelledby="doc-popup-title">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/img/icons/tip.png" alt="" aria-hidden="true">
<h2 id="doc-popup-title">WarpBox Help</h2>
</div>
<div class="win98-window-controls"><button class="win98-control popup-close" type="button" id="doc-popup-close" title="Close">×</button></div>
</div>
<div class="win98-panel popup-body" id="doc-popup-body"></div>
</section>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="/static/js/warpbox-ui.js"></script>
<script src="/static/js/upload-utils.js"></script>
<script src="/static/js/upload-popups.js"></script>
<script src="/static/js/app.js"></script>
</body>
</html>