Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 176 additions & 1 deletion src/bepasty/static/app/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ body {
margin: 0;
-webkit-font-smoothing: antialiased;
font-size: 100%;
background-color: #fff;
background-color: #f5f5f7; /* macOS light gray background */
color: #1d1d1f; /* macOS text color */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
}

#footer {
Expand Down Expand Up @@ -136,3 +138,176 @@ table.highlighttable {
.ui-autocomplete {
z-index: 1065;
}

/* Minimal visual enhancements */
.container {
padding-top: 1.25rem;
padding-bottom: 2rem;
}

.navbar {
box-shadow: 0 0.25rem 0.5rem rgba(0,0,0,.05);
}

.navbar-brand {
font-weight: 600;
}

.card {
border: 1px solid rgba(0,0,0,.075);
box-shadow: 0 .125rem .25rem rgba(0,0,0,.075);
border-radius: .5rem;
}

.card-header {
background-color: #ffffff;
border-bottom: 1px solid rgba(0,0,0,.075);
}

.btn-info,
.btn-primary,
.btn-danger,
.btn-outline-secondary,
.btn-success {
border-radius: .375rem;
}

.form-control {
border-radius: .375rem;
}

#formupload {
border: 1px solid #dee2e6;
border-radius: .375rem;
background: #fff;
}

.dropzone {
border: 2px dashed #ced4da;
background-color: #ffffff;
border-radius: .5rem;
text-align: center;
color: #6c757d;
}

#fileupload-progress.progress {
height: .75rem;
background-color: #e9ecef;
}

.progress-bar {
background-color: #0d6efd;
}

#footer {
background-color: transparent;
}

/* CSS variables consolidated into a single :root block (macOS-inspired palette) */
:root {
--primary: #0A84FF;
--secondary: #BF5AF2;
--success: #30D158;
--info: #64D2FF;
--warning: #FFD60A;
--danger: #FF453A;
--accent-1: #64D2FF;
--accent-2: #30D158;
--primary-08: rgba(10,132,255,.08);
--secondary-08: rgba(191,90,242,.08);
--macos-blue: #0A84FF;
--macos-blue-20: rgba(10,132,255,.35);
}



/* Minimal macOS-inspired tweaks (condensed) */

.navbar.navbar-light.bg-light { background: rgba(255,255,255,.72); border-bottom: 1px solid rgba(0,0,0,.06); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); }

.card { border: 1px solid rgba(0,0,0,.08); border-radius: .75rem; box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.08); }
.card-header { background: #fff; border-bottom: 1px solid rgba(0,0,0,.06); }

.btn-info, .btn-primary, .btn-danger, .btn-outline-secondary, .btn-success, .form-control { border-radius: .5rem; }
.form-control { border-color: #d2d2d7; }
.form-control:focus, .btn:focus { box-shadow: 0 0 0 .2rem var(--macos-blue-20); outline: 0; border-color: var(--macos-blue); }

.progress-bar { background-image: linear-gradient(90deg, var(--macos-blue), #64D2FF); }
.dropzone:hover { border-color: var(--macos-blue); background-color: rgba(10,132,255,.06); }

a { color: var(--macos-blue); }
a:hover, a:focus { color: #0060df; }


/* Ensure variables are defined with correct selector for macOS theme (override last) */


/* macOS link and button color overrides (independent of CSS variables) */
a { color: #0A84FF; }
a:hover, a:focus { color: #0060df; }

.btn-primary {
background-color: #0A84FF;
border-color: #0A84FF;
}
.btn-primary:hover,
.btn-primary:focus {
background-color: #0060df;
border-color: #0060df;
}

.btn-info {
background-color: #64D2FF;
border-color: #64D2FF;
color: #052039;
}
.btn-info:hover,
.btn-info:focus {
background-color: #2bb7ff;
border-color: #2bb7ff;
color: #03111f;
}


/* Display view polishing */
.display-view .card-header { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }
.display-view .card-header h1 { font-size: 1.5rem; line-height: 1.3; margin: 0; flex: 1 1 auto; }
.display-view .card-header .btn-group .btn { margin: .25rem .25rem 0 0; }

.display-view .card-body > p { color: #6c757d; background: #fff; border: 1px solid rgba(0,0,0,.06); border-radius: .5rem; padding: .75rem 1rem; }
.display-view code { background: rgba(0,0,0,.06); padding: .1rem .35rem; border-radius: .25rem; }

.display-view .data { background: #fff; border: 1px solid rgba(0,0,0,.08); border-radius: .5rem; padding: 1rem; box-shadow: inset 0 1px 2px rgba(0,0,0,.04); }
.display-view .data pre { margin: 0; border: none; background: transparent; }
.display-view table.highlighttable { background: #fbfbfc; border-color: rgba(0,0,0,.08); }


/* List view polishing */
.list-view .table { background: #fff; border: 1px solid rgba(0,0,0,.08); border-radius: .5rem; box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.06); border-collapse: separate; border-spacing: 0; overflow: hidden; }
.list-view .table thead th { background: #fbfbfc; border-bottom: 1px solid rgba(0,0,0,.06); color: #6c757d; font-weight: 600; vertical-align: middle; }
.list-view .table tbody tr { transition: background-color .15s ease; }
.list-view .table tbody tr:hover { background-color: rgba(10,132,255,.06); }
.list-view .table td, .list-view .table th { border-top: 1px solid rgba(0,0,0,.06); }
.list-view .table tbody tr:first-child td { border-top: 0; }
.list-view td img { max-width: 96px; height: auto; border-radius: .375rem; box-shadow: 0 2px 8px rgba(0,0,0,.08); }
.list-view .btn-group .btn { margin: .125rem .25rem .125rem 0; }
.list-view a { text-decoration: none; }


/* List cards layout (one item per rounded box) */
.list-cards { display: grid; grid-template-columns: 1fr; gap: .75rem; margin-top: .5rem; }
.list-item { border-radius: .75rem; overflow: hidden; }
.list-item .card-header { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; padding: .5rem .75rem; }
.list-item .card-header h2 { font-size: 1.125rem; line-height: 1.3; margin: 0; }
.list-item .btn-group .btn { margin: .125rem .25rem .125rem 0; }
.list-item .card-body { background: #fff; padding: .75rem 1rem; }
.list-item .list-thumb { width: 96px; max-width: 100%; height: auto; border-radius: .375rem; box-shadow: 0 2px 8px rgba(0,0,0,.08); border: 1px solid rgba(0,0,0,.06); margin-right: 1rem; }
.list-item .card-body .small { color: #6c757d; }

@media (min-width: 992px) {
.list-item .card-body { padding: 1rem 1.25rem; }
}


/* Equalize thumbnail vertical spacing in list cards */
.list-item .card-body a.mb-3 { margin-bottom: 0 !important; }
144 changes: 57 additions & 87 deletions src/bepasty/templates/_utils.html
Original file line number Diff line number Diff line change
@@ -1,92 +1,62 @@
{% macro filelist(files) %}
<table class="table table-hover">
<thead>
<tr>
<th class="text-right">
Filename
<br />
Type
<br />
Size [B]
</th>
<th>
Thumbnail
</th>
<th>
Upload [UTC]
<br />
Download [UTC]
</th>
<th>
Actions
</th>
</tr>
</thead>
<tbody>
{% for file in files %}
<tr>
<td class="text-right">
<a href="{{ url_for('bepasty.display', name=file['id']) }}">
{{ file['filename'] }}
</a>
<br />
{{ file['type'] }}
<br />
{{ file['size'] }}
</td>
<td>
<a href="{{ url_for('bepasty.display', name=file['id']) }}">
<img src="{{ url_for('bepasty.thumbnail', name=file['id']) }}">
</a>
</td>
<td>
{{ file['timestamp-upload'] | datetime }}
<br />
{% if file['timestamp-download'] %}
{{ file['timestamp-download'] | datetime }}
{% else %}
never
{% endif %}
</td>
<td>
<div class="btn-group flex-wrap flex-md-nowrap" role="group">
<a href="{{ url_for('bepasty.display', name=file['id']) }}" class="btn btn-sm btn-info" role="button">
Display
</a>
<a href="{{ url_for('bepasty.download', name=file['id']) }}" class="btn btn-sm btn-info" role="button">
Download
</a>
<a href="{{ url_for('bepasty.inline', name=file['id']) }}" class="btn btn-sm btn-info" role="button">
Inline
</a>
{% if may(DELETE) %}
<form action="{{ url_for('bepasty.delete', name=file['id']) }}" method="post" class="btn-group">
<button type="submit" class="btn btn-sm btn-danger">
Delete
</button>
</form>
{% endif %}
{% if may(ADMIN) %}
{% if not file['locked'] %}
<form action="{{ url_for('bepasty.lock', name=file['id']) }}" method="post" class="btn-group">
<button type="submit" class="btn btn-sm btn-danger">
Lock
</button>
</form>
{% else %}
<form action="{{ url_for('bepasty.unlock', name=file['id']) }}" method="post" class="btn-group">
<button type="submit" class="btn btn-sm btn-info">
Unlock
</button>
</form>
{% endif %}
{% endif %}
<div class="list-cards">
{% for file in files %}
<div class="card list-item">
<div class="card-body d-flex align-items-start">
<a href="{{ url_for('bepasty.display', name=file['id']) }}" class="me-3 mb-3">
<img src="{{ url_for('bepasty.thumbnail', name=file['id']) }}" class="list-thumb" alt="thumbnail">
</a>
<div class="flex-grow-1 d-flex flex-column">
<div class="mb-2">
<h2 class="h5 m-0">
<a href="{{ url_for('bepasty.display', name=file['id']) }}">{{ file['filename'] }}</a>
</h2>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="d-flex justify-content-between align-items-end flex-wrap">
<div class="small text-muted me-3">
<div>
<strong>Type:</strong> {{ file['type'] }}
<span class="ms-3"><strong>Size:</strong> {{ file['size'] }} B</span>
</div>
<div class="mt-1">
<strong>Uploaded (UTC):</strong> {{ file['timestamp-upload'] | datetime }}
</div>
<div>
<strong>Downloaded (UTC):</strong>
{% if file['timestamp-download'] %}
{{ file['timestamp-download'] | datetime }}
{% else %}
never
{% endif %}
</div>
</div>
<div class="btn-group flex-wrap flex-md-nowrap" role="group">
<a href="{{ url_for('bepasty.display', name=file['id']) }}" class="btn btn-sm btn-info" role="button">Display</a>
<a href="{{ url_for('bepasty.download', name=file['id']) }}" class="btn btn-sm btn-info" role="button">Download</a>
<a href="{{ url_for('bepasty.inline', name=file['id']) }}" class="btn btn-sm btn-info" role="button">Inline</a>
{% if may(DELETE) %}
<form action="{{ url_for('bepasty.delete', name=file['id']) }}" method="post" class="btn-group">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
{% endif %}
{% if may(ADMIN) %}
{% if not file['locked'] %}
<form action="{{ url_for('bepasty.lock', name=file['id']) }}" method="post" class="btn-group">
<button type="submit" class="btn btn-sm btn-danger">Lock</button>
</form>
{% else %}
<form action="{{ url_for('bepasty.unlock', name=file['id']) }}" method="post" class="btn-group">
<button type="submit" class="btn btn-sm btn-info">Unlock</button>
</form>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endmacro %}

{% macro input_filename(value) -%}
Expand Down
2 changes: 1 addition & 1 deletion src/bepasty/templates/display.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{% set page_title = item.meta['filename'] or name %}

{% block content %}
<div class="card">
<div class="card display-view">
<div class="card-header">
<h1>
{{ item.meta['filename'] }}
Expand Down
2 changes: 1 addition & 1 deletion src/bepasty/templates/filelist.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{% set page_title = 'All items' %}

{% block content %}
<div class="row">
<div class="row list-view">
<div class="col-md-12">
{{ utils.filelist(files) }}
</div>
Expand Down