Compare commits
2 Commits
7177cdb9ab
...
2539f82868
| Author | SHA1 | Date | |
|---|---|---|---|
| 2539f82868 | |||
| 7784da495b |
@@ -39,10 +39,34 @@
|
|||||||
|
|
||||||
.content-grid {
|
.content-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 2fr 1fr;
|
/* 3fr/1fr (not 2fr/1fr) so the 9-column playlist table gets enough room;
|
||||||
|
at 2fr/1fr it was ~50px too narrow and looped with a scrollbar.
|
||||||
|
minmax(0, …) removes the track's automatic min-content floor, without
|
||||||
|
which the table's intrinsic width would widen the track itself. */
|
||||||
|
grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The table needs ~830px and side by side it cannot get that below ~1440px.
|
||||||
|
Stack the cards instead of forcing a horizontal scrollbar on the table. */
|
||||||
|
@media (max-width: 1439px) {
|
||||||
|
.content-grid {
|
||||||
|
/* minmax(0, 1fr) matters here too: a bare 1fr keeps the min-content
|
||||||
|
floor, which let the 830px table widen the track and push the
|
||||||
|
page into horizontal overflow. */
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last-resort containment: on a genuinely narrow screen the table cannot
|
||||||
|
fit, and an unclipped table is painted straight over the Add Content
|
||||||
|
card, because that card is later in the DOM and therefore paints on top.
|
||||||
|
Clip here so the table scrolls inside its own card instead. */
|
||||||
|
.playlist-table-scroll {
|
||||||
|
overflow-x: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.playlist-table {
|
.playlist-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
@@ -50,13 +74,13 @@
|
|||||||
|
|
||||||
.playlist-table th {
|
.playlist-table th {
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
padding: 12px;
|
padding: 8px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 2px solid #dee2e6;
|
border-bottom: 2px solid #dee2e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-table td {
|
.playlist-table td {
|
||||||
padding: 12px;
|
padding: 8px;
|
||||||
border-bottom: 1px solid #dee2e6;
|
border-bottom: 1px solid #dee2e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +111,56 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
/* On a narrow viewport the thumbnail + name + button no longer fit on
|
||||||
|
one line; wrapping drops the Add button below instead of squeezing
|
||||||
|
the name under it. */
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left group: thumbnail + name/size. min-width:0 lets long names ellipsise
|
||||||
|
instead of pushing the Add button out of the card. */
|
||||||
|
.avail-main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.avail-thumb {
|
||||||
|
width: 52px;
|
||||||
|
height: 52px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #e9ecef;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.avail-thumb img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.avail-info {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.avail-name {
|
||||||
|
font-size: 14px;
|
||||||
|
/* Long media filenames carry the meaningful part at the END
|
||||||
|
(…_slide_003.png), so breaking mid-word is better than ellipsis,
|
||||||
|
which would hide the distinguishing characters. `anywhere` allows
|
||||||
|
breaks inside the unbroken run and keeps min-content width tiny. */
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.avail-meta {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Audio toggle styles */
|
/* Audio toggle styles */
|
||||||
@@ -216,6 +290,15 @@
|
|||||||
color: #e2e8f0;
|
color: #e2e8f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.dark-mode .avail-thumb {
|
||||||
|
background: #2d3748;
|
||||||
|
border-color: #4a5568;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.dark-mode .avail-meta {
|
||||||
|
color: #a0aec0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Dark mode for duration spinner */
|
/* Dark mode for duration spinner */
|
||||||
body.dark-mode .duration-display {
|
body.dark-mode .duration-display {
|
||||||
background: #2d3748;
|
background: #2d3748;
|
||||||
@@ -245,11 +328,18 @@
|
|||||||
body.dark-mode .duration-spinner button.btn-decrease {
|
body.dark-mode .duration-spinner button.btn-decrease {
|
||||||
color: #f56565;
|
color: #f56565;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The page needs more than base.html's 1200px container to show the
|
||||||
|
playlist table and the Add Content card side by side. This template
|
||||||
|
already declared max-width:1400px on its own wrapper, but a child cannot
|
||||||
|
widen its parent, so it had no effect. Widen the base container instead. */
|
||||||
|
body > .container {
|
||||||
|
max-width: 1400px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="container" style="max-width: 1400px;">
|
<div class="container" style="max-width: 1400px;">
|
||||||
<div class="playlist-header">
|
<div class="playlist-header"> <h1>🎬 {{ playlist.name }}</h1>
|
||||||
<h1>🎬 {{ playlist.name }}</h1>
|
|
||||||
{% if playlist.description %}
|
{% if playlist.description %}
|
||||||
<p style="margin: 5px 0; opacity: 0.9;">{{ playlist.description }}</p>
|
<p style="margin: 5px 0; opacity: 0.9;">{{ playlist.description }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -290,6 +380,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if playlist_content %}
|
{% if playlist_content %}
|
||||||
|
<div class="playlist-table-scroll">
|
||||||
<table class="playlist-table" id="playlist-table">
|
<table class="playlist-table" id="playlist-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -397,6 +488,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div style="text-align: center; padding: 40px; color: #999;">
|
<div style="text-align: center; padding: 40px; color: #999;">
|
||||||
<div style="font-size: 48px;">📭</div>
|
<div style="font-size: 48px;">📭</div>
|
||||||
@@ -428,21 +520,32 @@
|
|||||||
<div class="available-content">
|
<div class="available-content">
|
||||||
{% for content in available_content %}
|
{% for content in available_content %}
|
||||||
<div class="content-item">
|
<div class="content-item">
|
||||||
<div>
|
<div class="avail-main">
|
||||||
<div>
|
<div class="avail-thumb">
|
||||||
{% if content.content_type == 'image' %}📷
|
{% if content.content_type == 'image' %}
|
||||||
{% elif content.content_type == 'video' %}🎥
|
{# Preview the real image so the user can see what
|
||||||
{% elif content.content_type == 'pdf' %}📄
|
is being added. Falls back to the camera icon
|
||||||
{% else %}📁{% endif %}
|
if the file is missing or fails to load. #}
|
||||||
{{ content.original_display_name }}
|
<img src="{{ url_for('static', filename='uploads/' + content.current_media_path) }}"
|
||||||
|
alt="{{ content.original_display_name }}"
|
||||||
|
loading="lazy"
|
||||||
|
onerror="this.parentElement.innerHTML='<span>📷</span>';">
|
||||||
|
{% elif content.content_type == 'video' %}<span>🎥</span>
|
||||||
|
{% elif content.content_type == 'pdf' %}<span>📄</span>
|
||||||
|
{% else %}<span>📁</span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div style="font-size: 12px; color: #999;">
|
<div class="avail-info">
|
||||||
{{ content.file_size_mb }} MB
|
<div class="avail-name" title="{{ content.original_display_name }}">
|
||||||
|
{{ content.original_display_name }}
|
||||||
|
</div>
|
||||||
|
<div class="avail-meta">
|
||||||
|
{{ content.file_size_mb }} MB
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form method="POST"
|
<form method="POST"
|
||||||
action="{{ url_for('content.add_content_to_playlist', playlist_id=playlist.id) }}"
|
action="{{ url_for('content.add_content_to_playlist', playlist_id=playlist.id) }}"
|
||||||
style="display: inline;">
|
style="display: inline; flex: 0 0 auto;">
|
||||||
<input type="hidden" name="content_id" value="{{ content.id }}">
|
<input type="hidden" name="content_id" value="{{ content.id }}">
|
||||||
<input type="hidden" name="duration" value="{{ content.duration }}">
|
<input type="hidden" name="duration" value="{{ content.duration }}">
|
||||||
<button type="submit" class="btn btn-success btn-sm">
|
<button type="submit" class="btn btn-success btn-sm">
|
||||||
|
|||||||
Reference in New Issue
Block a user