feat: add configurable data directory and file-based logging
Introduce the `WARPBOX_DATA_DIR` environment variable to define where runtime data is stored. This directory will house uploaded files, the bbolt metadata database, and application logs. Changes include: - Added `WARPBOX_DATA_DIR` to configuration, defaulting to `./data`. - Implemented a custom logging package that writes JSONL logs to the data directory. - Updated `.gitignore` and `.env.example` to support the new data directory. - Documented the runtime data structure in `README.md`. - Updated the frontend upload script to handle form submission and display results.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{if .Title}}{{.Title}} - {{end}}{{.AppName}}</title>
|
||||
<meta name="description" content="{{.Description}}">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<meta name="theme-color" content="#09090b">
|
||||
<meta property="og:site_name" content="{{.AppName}}">
|
||||
<meta property="og:title" content="{{if .Title}}{{.Title}}{{else}}{{.AppName}}{{end}}">
|
||||
<meta property="og:description" content="{{.Description}}">
|
||||
@@ -16,7 +16,7 @@
|
||||
<link rel="stylesheet" href="/static/css/app.css">
|
||||
<script defer src="/static/js/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="dark">
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
<header class="site-header">
|
||||
<nav class="nav" aria-label="Main navigation">
|
||||
@@ -36,7 +36,8 @@
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<span>© {{.CurrentYear}} {{.AppName}}</span>
|
||||
<span>{{.AppName}} · {{.CurrentYear}} · self-hosted</span>
|
||||
<span class="footer-links"><a href="/">Upload</a><a href="/healthz">Health</a></span>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
41
backend/templates/pages/download.gohtml
Normal file
41
backend/templates/pages/download.gohtml
Normal file
@@ -0,0 +1,41 @@
|
||||
{{define "download.gohtml"}}{{template "base" .}}{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<section class="download-view" aria-labelledby="download-title">
|
||||
<div class="card download-card">
|
||||
<div class="card-content">
|
||||
<div class="file-emblem" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" /><path d="M14 2v6h6" /></svg>
|
||||
</div>
|
||||
<h1 id="download-title">Download files</h1>
|
||||
<p class="download-subtitle">Bucket id: {{.Data.Box.ID}}</p>
|
||||
|
||||
{{if .Data.Files}}
|
||||
<div class="badge-row">
|
||||
<span class="badge">Expires {{.Data.ExpiresLabel}}</span>
|
||||
{{if .Data.MaxDownloads}}<span class="badge">{{.Data.DownloadCount}} / {{.Data.MaxDownloads}} downloads</span>{{end}}
|
||||
</div>
|
||||
|
||||
<a class="button button-primary button-wide" href="{{.Data.ZipURL}}">
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false" aria-hidden="true"><path d="M12 3v12m0 0 4-4m-4 4-4-4M5 21h14" /></svg>
|
||||
Download zip
|
||||
</a>
|
||||
|
||||
<div class="download-list">
|
||||
{{range .Data.Files}}
|
||||
<a class="download-item" href="{{.URL}}">
|
||||
<span>
|
||||
<strong>{{.Name}}</strong>
|
||||
<small>{{.Size}} · {{.ContentType}}</small>
|
||||
</span>
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false" aria-hidden="true"><path d="M12 3v12m0 0 4-4m-4 4-4-4M5 21h14" /></svg>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else}}
|
||||
<p class="download-subtitle">{{.Data.ExpiresLabel}}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -2,45 +2,80 @@
|
||||
|
||||
{{define "content"}}
|
||||
<section class="upload-view" aria-labelledby="upload-title">
|
||||
<form class="upload-panel" action="/api/v1/upload" method="post" enctype="multipart/form-data">
|
||||
<div class="panel-header">
|
||||
<h1 id="upload-title">Upload your files</h1>
|
||||
<p>Drag files here or choose them from your device.</p>
|
||||
</div>
|
||||
<div class="hero-copy">
|
||||
<h1 id="upload-title">Send a file. Get a link.</h1>
|
||||
<p>Anonymous, self-hosted transfers. No account required.</p>
|
||||
</div>
|
||||
|
||||
<label class="drop-zone" for="file-input">
|
||||
<span class="drop-icon" aria-hidden="true">+</span>
|
||||
<span class="drop-title">Drop files to upload</span>
|
||||
<span class="drop-copy">Click to browse</span>
|
||||
<input id="file-input" name="file" type="file" multiple>
|
||||
</label>
|
||||
<form class="upload-panel card" id="upload-form" action="/api/v1/upload" method="post" enctype="multipart/form-data">
|
||||
<div class="card-content">
|
||||
<label class="drop-zone" for="file-input">
|
||||
<span class="drop-icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false" aria-hidden="true"><path d="M12 16V4m0 0 4 4m-4-4-4 4M5 20h14" /></svg>
|
||||
</span>
|
||||
<span class="drop-title">Drop files to upload</span>
|
||||
<span class="drop-copy">or click to browse</span>
|
||||
<span class="drop-meta">Max file size: {{.Data.MaxUploadSize}} · Links expire in 7 days</span>
|
||||
<input id="file-input" name="file" type="file" multiple>
|
||||
</label>
|
||||
|
||||
<details class="advanced-options">
|
||||
<summary>Advanced options</summary>
|
||||
<div class="option-grid">
|
||||
<label>
|
||||
<span>Expires after</span>
|
||||
<select name="max_days">
|
||||
<option value="7">7 days</option>
|
||||
<option value="1">1 day</option>
|
||||
<option value="30">30 days</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Max downloads</span>
|
||||
<input type="number" name="max_downloads" min="1" placeholder="Unlimited">
|
||||
</label>
|
||||
<label>
|
||||
<span>Password</span>
|
||||
<input type="password" name="password" autocomplete="new-password" placeholder="Optional">
|
||||
</label>
|
||||
<details class="advanced-options">
|
||||
<summary>
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
|
||||
Advanced options
|
||||
</summary>
|
||||
<div class="option-grid">
|
||||
<label>
|
||||
<span>Expires in</span>
|
||||
<select name="max_days">
|
||||
<option value="7">7 days</option>
|
||||
<option value="1">1 day</option>
|
||||
<option value="30">30 days</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Max downloads</span>
|
||||
<input type="number" name="max_downloads" min="1" placeholder="Unlimited">
|
||||
</label>
|
||||
<label>
|
||||
<span>Password</span>
|
||||
<input type="password" name="password" autocomplete="new-password" placeholder="Coming soon" disabled>
|
||||
</label>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="upload-progress" id="upload-progress" hidden>
|
||||
<div class="progress-row">
|
||||
<span>Uploading</span>
|
||||
<span id="upload-status">Preparing...</span>
|
||||
</div>
|
||||
<div class="progress"><span></span></div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="form-footer">
|
||||
<p>Current max file size: {{.Data.MaxUploadSize}}</p>
|
||||
<button class="button button-primary" type="submit">Upload files</button>
|
||||
<div class="form-footer">
|
||||
<p id="file-summary">Choose one or more files to begin.</p>
|
||||
<button class="button button-primary" type="submit">Upload files</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<section class="upload-result card" id="upload-result" hidden aria-live="polite">
|
||||
<div class="card-content">
|
||||
<div class="result-header">
|
||||
<div>
|
||||
<div class="result-title">
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>
|
||||
<span>Upload complete</span>
|
||||
</div>
|
||||
<p id="result-meta"></p>
|
||||
</div>
|
||||
<div class="result-actions">
|
||||
<button class="button button-outline" type="button" id="copy-all">Copy all</button>
|
||||
<a class="button button-primary" id="open-box" href="/">Open box</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="result-list" id="result-list"></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user