testing boxes

This commit is contained in:
StormyCloud
2025-06-30 21:42:14 -05:00
parent 5abc6c80ec
commit 69af50424c
3 changed files with 113 additions and 60 deletions

6
app.py
View File

@ -283,8 +283,10 @@ def admin_dashboard():
db = get_db()
now = datetime.now()
imgs = db.execute("SELECT id, expiry_date, view_count, max_views FROM images ORDER BY expiry_date ASC").fetchall()
past = db.execute("SELECT id, language, expiry_date, view_count, max_views FROM pastes ORDER BY expiry_date ASC").fetchall()
# Fetch only active images and pastes
imgs = db.execute("SELECT id, expiry_date, view_count, max_views FROM images WHERE expiry_date > ? ORDER BY expiry_date ASC", (now,)).fetchall()
past = db.execute("SELECT id, language, expiry_date, view_count, max_views FROM pastes WHERE expiry_date > ? ORDER BY expiry_date ASC", (now,)).fetchall()
images = [(i['id'], i['expiry_date'], get_time_left(i['expiry_date']), i['view_count'], i['max_views']) for i in imgs]
pastes = [(p['id'], p['language'], p['expiry_date'], get_time_left(p['expiry_date']), p['view_count'], p['max_views']) for p in past]

View File

@ -32,9 +32,11 @@
{% endif %}
<div class="flex items-center justify-center min-h-screen py-8">
<a href="/" class="inline-block mb-4">
<img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
</a>
<div class="w-full max-w-7xl mx-auto p-4">
<header class="flex flex-col items-center mb-8">
<a href="/" class="inline-block mb-4">
<img src="{{ url_for('static', filename='images/stormycloud.svg') }}" alt="StormyCloud Logo" style="width: 350px; max-width: 100%;" class="mx-auto">
</a>
<h1 class="text-4xl font-bold text-white">Admin Dashboard</h1>
</header>

View File

@ -17,6 +17,7 @@
select,textarea,input[type="text"],input[type="password"],input[type="number"] {
background-color:#4a5568; border:1px solid #718096; color:#cbd5e0;
}
input:disabled { background-color: #2d3748; color: #718096; cursor: not-allowed; }
.alert-success { background-color:#38a169; }
.alert-error { background-color:#e53e3e; }
.announcement-bar { background-color:#2563eb; border-bottom:1px solid #1e3a8a; }
@ -37,6 +38,7 @@
.stat-value { color:#63b3ed; }
.label-with-icon {
display:inline-flex; align-items:center; gap:0.5rem; font-size:0.875rem; color:#cbd5e0;
cursor: pointer;
}
.label-with-icon svg {
width:1rem; height:1rem; color:#4299e1; flex-shrink:0;
@ -46,6 +48,13 @@
border: 1px solid #4a5568;
border-radius: 0.5rem;
}
input[type="checkbox"] {
width: 20px;
height: 20px;
accent-color: #4299e1;
vertical-align: middle;
cursor: pointer;
}
/* API Docs Styling */
.docs-container h3 {
font-size: 1.5rem;
@ -100,9 +109,12 @@
<div class="flex items-center justify-center min-h-screen py-8">
<div id="main-container" class="w-full max-w-2xl mx-auto p-4">
<header class="text-center mb-8">
<a href="/" class="inline-block mb-4">
<img src="/static/images/stormycloud.svg" alt="StormyCloud Logo" style="width:350px; max-width:100%;" class="mx-auto"/>
</a>
<a href="/" class="inline-block mb-4">
<img src="/static/images/stormycloud.svg"
alt="StormyCloud Logo"
style="width:350px;max-width:100%;"
class="mx-auto"/>
</a>
<h1 class="text-4xl font-bold text-white">I2P Secure Share</h1>
<p class="text-gray-400">Anonymously share images and text pastes.</p>
</header>
@ -145,7 +157,14 @@
<div class="mb-6">
<label for="image-file" class="block text-gray-300 text-sm font-bold mb-2">Image File:</label>
<input type="file" name="file" id="image-file" required>
<p class="text-xs text-gray-500 mt-1">Max 10MB; WebP conversion.</p>
<div class="flex items-center space-x-2 text-xs text-gray-500 mt-1">
<label class="inline-flex items-center space-x-1 cursor-pointer" title="EXIF data includes details like camera model, date, and location. It is stripped by default for your privacy.">
<input type="checkbox" name="keep_exif" class="w-3 h-3 accent-blue-500 focus:ring-blue-500">
<span>Keep EXIF</span>
</label>
<span>·</span>
<span>Max 10MB; WebP conversion.</span>
</div>
</div>
<div class="mb-6">
@ -161,32 +180,36 @@
<option value="48h">48 hours</option>
</select>
</div>
<div class="flex mb-6 items-center">
<div style="width: 50%;">
<div class="flex items-center">
<label class="label-with-icon">
<input type="checkbox" id="image-pw-protect" name="password_protect">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11c1.657 0 3-1.343 3-3V6a3 3 0 10-6 0v2c0 1.657 1.343 3 3 3z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 11h14a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2z"/></svg>
<span>Password</span>
</label>
<div id="image-pw-options" class="reveal ml-2">
<input type="password" name="password" id="image-password" class="p-2 w-48 rounded-md border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" disabled>
</div>
</div>
</div>
<div class="mb-6 text-gray-300" style="display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem;align-items:start;">
<label class="label-with-icon">
<input type="checkbox" name="keep_exif">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6M7 7h10M4 6h16M4 6a2 2 0 012-2h8l2 2h6a2 2 0 012 2v12a2 2 0 01-2 2H6a2 2 0 01-2-2V6z"/></svg>
<span>Keep EXIF Data</span>
</label>
<label class="label-with-icon">
<input type="checkbox" id="image-pw-protect" name="password_protect">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11c1.657 0 3-1.343 3-3V6a3 3 0 10-6 0v2c0 1.657 1.343 3 3 3z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 11h14a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2z"/></svg>
<span>Password</span>
</label>
<label class="label-with-icon" title="Removed after this many successful views">
<input type="checkbox" id="image-views-protect" name="views_protect">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.477 0 8.268 2.943 9.542 7-1.274 4.057-5.065 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
<span>Max Views</span>
</label>
</div>
<div id="image-pw-options" class="reveal mb-6">
<label for="image-password" class="block text-gray-300 text-sm font-bold mb-1">Password:</label>
<input type="password" name="password" id="image-password" class="w-full p-2 rounded-md border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div id="image-views-options" class="reveal mb-6">
<label for="image-max-views" class="block text-gray-300 text-sm font-bold mb-1">Max views:</label>
<input type="number" name="max_views" id="image-max-views" min="1" class="w-full p-2 rounded-md border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500">
<div style="width: 50%; text-align: right;">
<div class="inline-flex items-center">
<label for="image-max-views-select" class="label-with-icon mr-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.477 0 8.268 2.943 9.542 7-1.274 4.057-5.065 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
<span>Max Views:</span>
</label>
<select name="max_views" id="image-max-views-select" class="p-2 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="" selected>Unlimited</option>
<option value="1">1</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="50">50</option>
</select>
</div>
</div>
</div>
<button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md focus:shadow-outline">Upload Image</button>
@ -222,26 +245,38 @@
<option value="48h">48 hours</option>
</select>
</div>
<div class="mb-6 text-gray-300" style="display:grid;grid-template-columns:repeat(2,1fr);gap:2rem;align-items:start;">
<label class="label-with-icon">
<input type="checkbox" id="paste-pw-protect" name="password_protect">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11c1.657 0 3-1.343 3-3V6a3 3 0 10-6 0v2c0 1.657 1.343 3 3 3z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 11h14a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2z"/></svg>
<span>Password</span>
</label>
<label class="label-with-icon" title="Removed after this many successful views">
<input type="checkbox" id="paste-views-protect" name="views_protect">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.477 0 8.268 2.943 9.542 7-1.274 4.057-5.065 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
<span>Max Views</span>
</label>
</div>
<div id="paste-pw-options" class="reveal mb-6">
<label for="paste-password" class="block text-gray-300 text-sm font-bold mb-1">Password:</label>
<input type="password" name="password" id="paste-password" class="w-full p-2 rounded-md border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div id="paste-views-options" class="reveal mb-6">
<label for="paste-max-views" class="block text-gray-300 text-sm font-bold mb-1">Max views:</label>
<input type="number" name="max_views" id="paste-max-views" min="1" class="w-full p-2 rounded-md border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500">
<div class="flex mb-6 items-center">
<div style="width: 50%;">
<div class="flex items-center">
<label class="label-with-icon">
<input type="checkbox" id="paste-pw-protect" name="password_protect" class="mr-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11c1.657 0 3-1.343 3-3V6a3 3 0 10-6 0v2c0 1.657 1.343 3 3 3z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 11h14a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2v-8a2 2 0 012-2z"/></svg>
<span>Password</span>
</label>
<div id="paste-pw-options" class="reveal ml-2">
<input type="password" name="password" id="paste-password" placeholder="Enter password..." class="p-2 w-48 rounded-md border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" disabled>
</div>
</div>
</div>
<div style="width: 50%; text-align: right;">
<div class="inline-flex items-center">
<label for="paste-max-views-select" class="label-with-icon mr-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.477 0 8.268 2.943 9.542 7-1.274 4.057-5.065 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>
<span>Max Views:</span>
</label>
<select name="max_views" id="paste-max-views-select" class="p-2 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="" selected>Unlimited</option>
<option value="1">1</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="50">50</option>
</select>
</div>
</div>
</div>
<button type="submit" class="btn w-full text-white font-bold py-3 px-5 rounded-md focus:shadow-outline">Create Paste</button>
</form>
</div>
@ -313,7 +348,7 @@ http://{{ request.host }}/api/upload/paste</pre>
</div>
<div class="text-center text-xs text-gray-500 mt-6 mb-8">
<a href="http://git.idk.i2p/stormycloud/drop.i2p/releases/tag/v1.1" target="_blank" rel="noopener noreferrer" class="hover:text-gray-400 transition-colors">
<a href="https://github.com/your-username/your-repo-name" target="_blank" rel="noopener noreferrer" class="hover:text-gray-400 transition-colors">
Version 1.1
</a>
</div>
@ -389,15 +424,29 @@ http://{{ request.host }}/api/upload/paste</pre>
showTab(window.location.hash);
function toggle(cbId, tgtId) {
const cb = document.getElementById(cbId), tgt = document.getElementById(tgtId);
if (!cb||!tgt) return;
cb.addEventListener('change', () => tgt.style.display = cb.checked ? 'block' : 'none');
tgt.style.display = cb.checked ? 'block' : 'none';
const cb = document.getElementById(cbId);
const tgt = document.getElementById(tgtId);
if (!cb || !tgt) return;
const input = tgt.querySelector('input[type="password"]');
const toggleState = () => {
// Use inline-block for side-by-side layout
tgt.style.display = cb.checked ? 'inline-block' : 'none';
if (input) {
input.disabled = !cb.checked;
if (!cb.checked) {
input.value = ''; // Clear input if checkbox is unchecked
}
}
};
cb.addEventListener('change', toggleState);
toggleState(); // Set initial state on page load
}
toggle('image-pw-protect','image-pw-options');
toggle('image-views-protect','image-views-options');
toggle('paste-pw-protect','paste-pw-options');
toggle('paste-views-protect','paste-views-options');
const closeBtn = document.getElementById('close-announcement');
if (closeBtn) closeBtn.addEventListener('click', ()=>