Fixing long play scrobbles
This commit is contained in:
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.1.5 on 2023-03-06 05:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("books", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="book",
|
||||
name="author_name",
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="book",
|
||||
name="author_openlibrary_id",
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
]
|
||||
20
vrobbler/apps/books/migrations/0003_book_cover.py
Normal file
20
vrobbler/apps/books/migrations/0003_book_cover.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.1.5 on 2023-03-06 05:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("books", "0002_book_author_name_book_author_openlibrary_id"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="book",
|
||||
name="cover",
|
||||
field=models.ImageField(
|
||||
blank=True, null=True, upload_to="books/covers/"
|
||||
),
|
||||
),
|
||||
]
|
||||
19
vrobbler/apps/books/urls.py
Normal file
19
vrobbler/apps/books/urls.py
Normal file
@ -0,0 +1,19 @@
|
||||
from django.urls import path
|
||||
from books import views
|
||||
|
||||
app_name = "books"
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("book/", views.BookListView.as_view(), name="book_list"),
|
||||
path(
|
||||
"book/<slug:slug>/",
|
||||
views.BookDetailView.as_view(),
|
||||
name="book_detail",
|
||||
),
|
||||
path(
|
||||
"author/<slug:slug>/",
|
||||
views.AuthorDetailView.as_view(),
|
||||
name="author_detail",
|
||||
),
|
||||
]
|
||||
17
vrobbler/apps/books/views.py
Normal file
17
vrobbler/apps/books/views.py
Normal file
@ -0,0 +1,17 @@
|
||||
from django.views import generic
|
||||
from books.models import Book, Author
|
||||
|
||||
|
||||
class BookListView(generic.ListView):
|
||||
model = Book
|
||||
paginate_by = 20
|
||||
|
||||
|
||||
class BookDetailView(generic.DetailView):
|
||||
model = Book
|
||||
slug_field = "uuid"
|
||||
|
||||
|
||||
class AuthorDetailView(generic.DetailView):
|
||||
model = Author
|
||||
slug_field = "uuid"
|
||||
@ -0,0 +1,22 @@
|
||||
# Generated by Django 4.1.5 on 2023-03-06 02:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("scrobbles", "0026_scrobble_video_game"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="scrobble",
|
||||
name="videogame_minutes_played",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="scrobble",
|
||||
name="playback_position",
|
||||
field=models.CharField(blank=True, max_length=10, null=True),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,21 @@
|
||||
# Generated by Django 4.1.5 on 2023-03-06 05:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
(
|
||||
"scrobbles",
|
||||
"0027_remove_scrobble_videogame_minutes_played_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="scrobble",
|
||||
name="video_game_minutes_played",
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
BIN
vrobbler/apps/scrobbles/static/images/hltb.webp
Normal file
BIN
vrobbler/apps/scrobbles/static/images/hltb.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 B |
BIN
vrobbler/apps/scrobbles/static/images/igdb-logo.png
Normal file
BIN
vrobbler/apps/scrobbles/static/images/igdb-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.1.5 on 2023-03-06 02:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("videogames", "0005_rename_platform_videogame_platforms"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="videogame",
|
||||
name="summary",
|
||||
field=models.TextField(blank=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="videogame",
|
||||
name="platforms",
|
||||
field=models.ManyToManyField(to="videogames.videogameplatform"),
|
||||
),
|
||||
]
|
||||
0
vrobbler/apps/videogames/templatetags/__init__.py
Normal file
0
vrobbler/apps/videogames/templatetags/__init__.py
Normal file
16
vrobbler/apps/videogames/templatetags/naturalduration.py
Normal file
16
vrobbler/apps/videogames/templatetags/naturalduration.py
Normal file
@ -0,0 +1,16 @@
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def natural_duration(value):
|
||||
value = int(value)
|
||||
hours = int(value / 60)
|
||||
minutes = value - (hours * 60)
|
||||
value_str = ""
|
||||
if minutes:
|
||||
value_str = f"{minutes} minutes"
|
||||
if hours:
|
||||
value_str = f"{hours} hours, " + value_str
|
||||
return value_str
|
||||
57
vrobbler/templates/books/book_detail.html
Normal file
57
vrobbler/templates/books/book_detail.html
Normal file
@ -0,0 +1,57 @@
|
||||
{% extends "base_list.html" %}
|
||||
{% load mathfilters %}
|
||||
{% load static %}
|
||||
{% load naturalduration %}
|
||||
|
||||
{% block title %}{{object.title}}{% endblock %}
|
||||
|
||||
{% block lists %}
|
||||
|
||||
<div class="row">
|
||||
|
||||
{% if object.cover%}
|
||||
<p style="float:left; width:402px; padding:0; border: 1px solid #ccc">
|
||||
<img src="{{object.cover.url}}" width=400 />
|
||||
</p>
|
||||
{% endif %}
|
||||
<div style="float:left; width:600px; margin-left:10px; ">
|
||||
{% if object.summary %}
|
||||
<p>{{object.summary|safe|linebreaks|truncatewords:160}}</p>
|
||||
<hr />
|
||||
{% endif %}
|
||||
<p style="float:right;">
|
||||
<a href="{{object.openlibrary_link}}"><img src="{% static " images/openlibrary-logo.png" %}" width=35></a>
|
||||
<a href="{{object.amazon_link}}"><img src="{% static " images/amazon-logo.png" %}" width=35></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p>{{object.scrobble_set.count}} scrobbles</p>
|
||||
<p><a href="">Start playing</a></p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md">
|
||||
<h3>Last scrobbles</h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Date</th>
|
||||
<th scope="col">Duration</th>
|
||||
<th scope="col">Authors</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for scrobble in object.scrobble_set.all|dictsortreversed:"timestamp" %}
|
||||
<tr>
|
||||
<td>{{scrobble.timestamp}}</td>
|
||||
<td>{% if scrobble.in_progress %}Now playing{% else %}{{scrobble.playback_position|natural_duration}}{% endif %}</td>
|
||||
<td>{% for author in scrobble.book.authors.all %}<a href="{{author.get_absolute_url}}">{{author}}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
57
vrobbler/templates/videogames/videogame_detail.html
Normal file
57
vrobbler/templates/videogames/videogame_detail.html
Normal file
@ -0,0 +1,57 @@
|
||||
{% extends "base_list.html" %}
|
||||
{% load mathfilters %}
|
||||
{% load static %}
|
||||
{% load naturalduration %}
|
||||
|
||||
{% block title %}{{object.title}}{% endblock %}
|
||||
|
||||
{% block lists %}
|
||||
|
||||
<div class="row">
|
||||
|
||||
{% if object.hltb_cover%}
|
||||
<p style="float:left; width:402px; padding:0; border: 1px solid #ccc">
|
||||
<img src="{{object.hltb_cover.url}}" width=400 />
|
||||
</p>
|
||||
{% endif %}
|
||||
<div style="float:left; width:600px; margin-left:10px; ">
|
||||
{% if object.summary %}
|
||||
<p>{{object.summary|safe|linebreaks|truncatewords:160}}</p>
|
||||
<hr/>
|
||||
{% endif %}
|
||||
<p style="float:right;">
|
||||
<a href="{{object.igdb_link}}"><img src="{% static "images/igdb-logo.png" %}" width=35></a>
|
||||
<a href="{{object.hltb_link}}"><img style="background: black;" src="{% static "images/hltb.webp" %}" width=35></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p>{{object.scrobble_set.count}} scrobbles</p>
|
||||
<p><a href="">Start playing</a></p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md">
|
||||
<h3>Last scrobbles</h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Date</th>
|
||||
<th scope="col">Duration</th>
|
||||
<th scope="col">Platforms</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for scrobble in object.scrobble_set.all|dictsortreversed:"timestamp" %}
|
||||
<tr>
|
||||
<td>{{scrobble.timestamp}}</td>
|
||||
<td>{% if scrobble.in_progress %}Now playing{% else %}{{scrobble.playback_position|natural_duration}}{% endif %}</td>
|
||||
<td>{% for platform in scrobble.video_game.platforms.all %}<a href="{{platform.get_absolute_url}}">{{platform}}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user