Files
vrobbler/vrobbler/templates/base.html
Colin Powell ea1b43d1b8
Some checks failed
build / test (push) Has been cancelled
[sports] Big sports structure revamp
This should make scrobbling sports more like tasks.

The root scrobbled items are a little more generic, but
it's easier to see viewing patterns.
2026-06-06 23:32:21 -04:00

374 lines
12 KiB
HTML

{% load static %}
{% load humanize %}
<!doctype html>
<html class="no-js" lang="">
<head>
<title>{% block page_title %}Scrobble all the things{% endblock %} @ Vrobbler</title>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type="image/png" href="{% static 'images/favicon.ico' %}"/>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.10/clipboard.min.js"></script>
<style type="text/css">
dl {
display: flex;
flex-flow: column wrap;
border: 1px solid #777;
}
dt {
padding: 2px 4px;
background: #000;
color: #fff;
}
dd {
margin: 0;
padding: 4px;
min-height: 3em;
border-right: 1px solid #777;
}
.now-playing { margin-right:20px;}
.now-playing p { margin:0; }
.now-playing .right { float:right; margin-right:10px; }
.latest-scrobble {
width: 50%;
}
.now-playing img { height:75px; width: 75px; object-fit: cover; }
.progress-bar {
width: 100%;
background-color: #e0e0e0;
padding: 3px;
border-radius: 3px;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);
}
.progress-bar-fill {
display: block;
height: 22px;
background-color: #659cef;
border-radius: 3px;
transition: width 500ms ease-in-out;
}
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
body {
font-size: .875rem;
}
.feather {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
/*
* Sidebar
*/
.sidebar {
position: fixed;
top: 0;
/* rtl:raw:
right: 0;
*/
bottom: 0;
/* rtl:remove */
left: 0;
z-index: 100; /* Behind the navbar */
padding: 48px 0 0; /* Height of navbar */
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
}
@media (max-width: 767.98px) {
.sidebar {
top: 5rem;
}
}
.sidebar-sticky {
position: relative;
top: 0;
height: calc(100vh - 48px);
padding-top: .5rem;
overflow-x: hidden;
overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
}
.sidebar .nav-link {
font-weight: 500;
color: #333;
}
.sidebar .nav-link .feather {
margin-right: 4px;
color: #727272;
}
.sidebar .nav-link.active {
color: #2470dc;
}
.sidebar .nav-link:hover .feather,
.sidebar .nav-link.active .feather {
color: inherit;
}
.sidebar-heading {
font-size: .75rem;
text-transform: uppercase;
}
/*
* Navbar
*/
.navbar-brand {
padding-top: .5rem;
padding-bottom: .5rem;
font-size: 1.3rem;
background-color: rgba(0, 0, 0, .25);
box-shadow: inset -1px 0 0 rgba(0, 0, 0, .25);
}
.navbar .navbar-toggler {
top: .25rem;
right: 1rem;
}
.navbar .form-control {
padding: .75rem 1rem;
border-width: 0;
border-radius: 0;
}
.form-control-dark {
color: #fff;
background-color: rgba(255, 255, 255, .1);
border-color: rgba(255, 255, 255, .1);
}
.form-control-dark:focus {
border-color: transparent;
box-shadow: 0 0 0 3px rgba(255, 255, 255, .25);
}
#scrobble-form { width: 100% }
.notes-list {
max-width: 600px;
}
.note-item {
padding: 4px 0;
}
.note-timestamp {
font-size: 0.8em;
color: #666;
margin: 0 0 4px;
}
.note-content {
font-size: 0.95em;
line-height: 1.5;
}
.note-content p:last-child {
margin-bottom: 0;
}
.note-divider {
margin: 8px 0;
border: 0;
border-top: 1px solid #ddd;
}
.sticky-notes-container {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.sticky-note {
padding: 8px;
border: 1px solid #ccc;
max-width: 200px;
font-size: 0.9em;
line-height: 1.3;
background: #fff9c4;
}
.sticky-note:nth-child(even) {
background: #ffccbc;
}
.sticky-note:nth-child(3n) {
background: #b3e5fc;
}
.sticky-note:nth-child(4n) {
background: #c8e6c9;
}
.sticky-note:nth-child(5n) {
background: #e1bee7;
}
.sidebar {
background-color: color-mix(in srgb, var(--accent) 8%, #f8f9fa) !important;
}
.sidebar .nav-link.active {
color: var(--accent) !important;
}
.navbar-brand {
background-color: color-mix(in srgb, var(--accent) 70%, #000) !important;
color: var(--accent) !important;
}
.sidebar .nav-link:hover {
color: var(--accent);
}
a:not(.nav-link):not(.btn):not(.page-link) {
color: color-mix(in srgb, var(--accent) 70%, #000);
}
a:not(.nav-link):not(.btn):not(.page-link):hover {
color: var(--accent);
}
a.badge {
color: #fff !important;
}
.table-striped > tbody > tr:nth-of-type(odd) {
background-color: color-mix(in srgb, var(--accent) 6%, #fff);
}
.table > tbody > tr:hover {
background-color: color-mix(in srgb, var(--accent) 10%, #fff);
}
</style>
{% block head_extra %}{% endblock %}
<link rel="apple-touch-icon" href="{% static 'images/apple-touch-icon.png' %}">
</head>
<body style="--accent:{{ month_color|default:'#db7a7a' }}">
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="/">Vrobbler</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
{% if user.is_authenticated %}
<form id="scrobble-form" action="{% url 'scrobbles:lookup-manual-scrobble' %}" method="post">
{% csrf_token %}
{{ imdb_form }}
</form>
{% endif %}
{% if user.is_authenticated %}
<div class="navbar-nav flex-row">
<div class="nav-item text-nowrap">
<a class="nav-link px-3" href="{% url "moods:checkin" %}">Check-in</a>
</div>
<div class="nav-item text-nowrap">
<a class="nav-link px-3" href="{% url "profiles:profile_settings" %}">Settings</a>
</div>
<div class="nav-item text-nowrap">
<a class="nav-link px-3" href="{% url "account_logout" %}">Sign out</a>
</div>
</div>
{% else %}
<div class="navbar-nav flex-row">
<div class="nav-item text-nowrap">
<a class="nav-link px-3" href="{% url "account_login" %}">Sign in</a>
</div>
</div>
{% endif %}
</header>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="position-sticky pt-3">
{% if messages %}
<ul style="padding-right:10px;">
{% for message in messages %}
<li {% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% block extra_nav %}
{% endblock %}
{% if now_playing_list and user.is_authenticated %}
<ul>
<b>Now playing</b>
{% for scrobble in now_playing_list %}
<div class="now-playing">
{% if scrobble.media_obj.primary_image_url %}<div style="float:left;padding-right:10px;padding-bottom:10px;"><img src="{{scrobble.media_obj.primary_image_url}}" /></div>{% endif %}
<p><a href="{{scrobble.get_absolute_url}}">{{scrobble.media_obj}}</a></p>
{% if scrobble.logdata %}{% if scrobble.logdata.title%}<p><em>{{scrobble.logdata.title}}</em></p>{% endif %}{% endif %}
<p><small>{{scrobble.local_timestamp|naturaltime}} from {{scrobble.source}}</small></p>
<div class="progress-bar" style="margin-right:5px;">
<span class="progress-bar-fill" style="width: {{scrobble.percent_played}}%;"></span>
</div>
<p class="action-buttons">
<a href="{% url "scrobbles:cancel" scrobble.uuid %}">Cancel</a>
<a class="right" href="{% url "scrobbles:finish" scrobble.uuid %}">Finish</a>
</p>
{% if not forloop.last %}<hr/>{% endif %}
</div>
{% endfor %}
</ul>
{% if now_playing_list|length > 1 %}<hr/>{% endif %}
{% endif %}
{% if active_imports %}
{% for import in active_imports %}
<ul style="padding-right:10px;">
<li>Import in progress ({{import.processing_started|naturaltime}})</li>
</ul>
{% endfor %}
{% endif %}
</div>
</nav>
{% block content %}
{% endblock %}
</div>
</div>
{% block extra_js %}{% endblock %}
<script>
(() => {
'use strict'
const forms = document.querySelectorAll('.needs-validation')
Array.from(forms).forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
<footer class="mt-4 py-2 text-center text-muted border-top">
<small>v{{ app_version }} ({{ git_commit }})</small>
</footer>
</body>
</html>