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.
This commit is contained in:
2026-04-29 02:29:49 +03:00
parent a8c0666b5a
commit e330fb04b3
15 changed files with 3309 additions and 189 deletions

View File

@@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WarpBox - {{ .BoxID }}</title>
<link rel="icon" type="image/png" href="/static/WarpBoxLogo.png">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/app.css">
<link rel="stylesheet" href="/static/css/window.css">
<link rel="stylesheet" href="/static/css/box.css">
@@ -19,37 +18,24 @@
<img class="win98-titlebar-icon" src="/static/WarpBoxLogo.png" alt="" aria-hidden="true">
<h1 id="box-window-title">WarpBox Explorer - {{ .BoxID }}</h1>
</div>
<div class="win98-window-controls" aria-hidden="true">
<span class="win98-control">_</span>
<span class="win98-control"></span>
<span class="win98-control">×</span>
<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>
</header>
<div class="win98-menu box-menu" aria-hidden="true">
<span class="win98-menu-option">File</span>
<span class="win98-menu-option">Edit</span>
<span class="win98-menu-option">View</span>
<span class="win98-menu-option">Tools</span>
<span class="win98-menu-option">Help</span>
</div>
<div class="box-toolbar">
<a class="win98-button box-toolbar-button" href="/">Upload</a>
<div class="box-command-row">
<button class="box-address" type="button" id="box-address" data-copy-url="{{ .BoxID }}" title="Copy current page URL">{{ .BoxID }}</button>
<a class="win98-button box-toolbar-button" href="/"><img src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true"><span>Upload</span></a>
{{ if .DownloadAll }}
<a class="win98-button box-toolbar-button" href="{{ .DownloadAll }}">Download Zip</a>
<a class="win98-button box-toolbar-button" href="{{ .DownloadAll }}"><img src="/static/img/icons/Windows Icons - PNG/zipfldr.dll_14_101-0.png" alt="" aria-hidden="true"><span>Download Zip</span></a>
{{ end }}
</div>
<div class="box-address">
<span>Address</span>
<code>/box/{{ .BoxID }}</code>
</div>
{{ if .RetentionLabel }}
<div class="box-meta">
<span>Retention</span>
<span>{{ .RetentionLabel }}</span>
<div class="box-meta" data-expires-at="{{ .ExpiresAtISO }}">
<span id="box-expiry-text">Expires in {{ .RetentionLabel }}</span>
</div>
{{ end }}
@@ -57,7 +43,7 @@
{{ if .Files }}
<div class="box-file-grid" aria-label="Uploaded files">
{{ range .Files }}
<a class="box-file {{ if .IsComplete }}is-complete{{ else if eq .Status "failed" }}is-failed{{ else }}is-loading{{ end }} {{ if .ThumbnailURL }}has-thumbnail{{ end }}" href="{{ if and .IsComplete (not $.ZipOnly) }}{{ .DownloadPath }}{{ else }}#{{ end }}" title="{{ if $.ZipOnly }}Available in ZIP download{{ else }}{{ .Title }}{{ end }}" data-file-id="{{ .ID }}" data-status="{{ .Status }}" {{ if and .IsComplete (not $.ZipOnly) }}download{{ else }}aria-disabled="true"{{ end }}>
<a class="box-file {{ if .IsComplete }}is-complete{{ else if eq .Status "failed" }}is-failed{{ else }}is-loading{{ end }} {{ if .ThumbnailURL }}has-thumbnail{{ end }}" href="{{ if and .IsComplete (not $.ZipOnly) }}{{ .DownloadPath }}{{ else }}#{{ end }}" title="{{ if $.ZipOnly }}Available in ZIP download{{ else }}{{ .Title }}{{ end }}" data-file-id="{{ .ID }}" data-status="{{ .Status }}" data-name="{{ .Name }}" data-size="{{ .SizeLabel }}" data-mime="{{ .MimeType }}" data-download-path="{{ .DownloadPath }}" data-thumbnail="{{ .ThumbnailURL }}" {{ if and .IsComplete (not $.ZipOnly) }}download{{ else }}aria-disabled="true"{{ end }}>
<img class="box-file-icon" src="{{ if .ThumbnailURL }}{{ .ThumbnailURL }}{{ else }}{{ .IconPath }}{{ end }}" alt="" aria-hidden="true">
<span class="box-file-name">{{ .Name }}</span>
<span class="box-file-meta">{{ .StatusLabel }} · {{ .SizeLabel }}</span>
@@ -75,6 +61,24 @@
</div>
</section>
</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</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="box-context-menu" id="box-context-menu" role="menu" aria-hidden="true">
<button type="button" data-context-action="preview"><img src="/static/img/sprites/bitmap.png" alt="" aria-hidden="true"><span>Preview</span></button>
<button type="button" data-context-action="download"><img src="/static/img/icons/directory_open_cool-4.png" alt="" aria-hidden="true"><span>Download</span></button>
<button type="button" data-context-action="properties"><img src="/static/img/icons/tip.png" alt="" aria-hidden="true"><span>Properties</span></button>
</div>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="/static/js/warpbox-ui.js"></script>
<script src="/static/js/box.js"></script>
</body>
</html>

View File

@@ -32,7 +32,6 @@
<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>
<button class="menu-action" type="button" data-action="copy-link"><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>
<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>
@@ -41,7 +40,7 @@
<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"><img src="/static/img/sprites/frame_web-0.png" alt="" aria-hidden="true"><span>Copy share URL</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>
@@ -51,14 +50,12 @@
<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>
<button class="menu-action" type="button" data-action="toggle-page"><img src="/static/img/sprites/frame_web-0.png" alt="" aria-hidden="true"><span>Download page</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-action="terminal-help"><img src="/static/img/icons/shell_window1.png" alt="" aria-hidden="true"><span>Show cURL command</span><span></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>
@@ -99,7 +96,7 @@
<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" disabled data-disabled-reason="There is no share URL yet. Start an upload first.">Copy</button>
<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>
@@ -110,7 +107,7 @@
<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" {{ if not .UploadsEnabled }}disabled{{ end }} data-disabled-reason="Start upload is unavailable right now.">Start upload</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>
@@ -145,7 +142,7 @@
</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">
<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>
@@ -238,6 +235,7 @@
</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>