Compare commits
No commits in common. "666dee33ba87dfc722ab8ac4c5598bc6cd50146d" and "4552cf7616fa2ce179b30e34e6f8c62420a5934f" have entirely different histories.
666dee33ba
...
4552cf7616
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -1,22 +1,3 @@
|
||||||
## Unreleased
|
|
||||||
|
|
||||||
### New
|
|
||||||
* More fields are now optional. This is to make it easier to add new items in bulk.
|
|
||||||
* Game: Wikidata ID
|
|
||||||
* Edition: Platform, Year
|
|
||||||
* Purchase: Platform
|
|
||||||
* Platform: Group
|
|
||||||
* Session: Device
|
|
||||||
* New fields:
|
|
||||||
* Game: Year Released
|
|
||||||
* To record original year of release
|
|
||||||
* Upon migration, this will be set to a year of any of the game's edition that has it set
|
|
||||||
* Purchase: Date Finished
|
|
||||||
* Editions are now unique combination of name and platform
|
|
||||||
|
|
||||||
### Improved
|
|
||||||
* game overview: simplify playtime range display
|
|
||||||
|
|
||||||
## 1.3.0 / 2023-11-05 15:09+01:00
|
## 1.3.0 / 2023-11-05 15:09+01:00
|
||||||
|
|
||||||
### New
|
### New
|
||||||
|
|
|
@ -50,7 +50,6 @@ class PurchaseForm(forms.ModelForm):
|
||||||
widgets = {
|
widgets = {
|
||||||
"date_purchased": custom_date_widget,
|
"date_purchased": custom_date_widget,
|
||||||
"date_refunded": custom_date_widget,
|
"date_refunded": custom_date_widget,
|
||||||
"date_finished": custom_date_widget,
|
|
||||||
}
|
}
|
||||||
model = Purchase
|
model = Purchase
|
||||||
fields = [
|
fields = [
|
||||||
|
@ -58,7 +57,6 @@ class PurchaseForm(forms.ModelForm):
|
||||||
"platform",
|
"platform",
|
||||||
"date_purchased",
|
"date_purchased",
|
||||||
"date_refunded",
|
"date_refunded",
|
||||||
"date_finished",
|
|
||||||
"price",
|
"price",
|
||||||
"price_currency",
|
"price_currency",
|
||||||
"ownership_type",
|
"ownership_type",
|
||||||
|
@ -69,9 +67,7 @@ class EditionForm(forms.ModelForm):
|
||||||
game = forms.ModelChoiceField(
|
game = forms.ModelChoiceField(
|
||||||
queryset=Game.objects.order_by("name"), widget=autofocus_select_widget
|
queryset=Game.objects.order_by("name"), widget=autofocus_select_widget
|
||||||
)
|
)
|
||||||
platform = forms.ModelChoiceField(
|
platform = forms.ModelChoiceField(queryset=Platform.objects.order_by("name"))
|
||||||
queryset=Platform.objects.order_by("name"), required=False
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Edition
|
model = Edition
|
||||||
|
@ -81,7 +77,7 @@ class EditionForm(forms.ModelForm):
|
||||||
class GameForm(forms.ModelForm):
|
class GameForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Game
|
model = Game
|
||||||
fields = ["name", "year_released", "wikidata"]
|
fields = ["name", "wikidata"]
|
||||||
widgets = {"name": autofocus_input_widget}
|
widgets = {"name": autofocus_input_widget}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 11:10
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("games", "0015_edition_wikidata_edition_year_released"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="edition",
|
|
||||||
name="platform",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="games.platform",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="edition",
|
|
||||||
name="year_released",
|
|
||||||
field=models.IntegerField(blank=True, default=None, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="game",
|
|
||||||
name="wikidata",
|
|
||||||
field=models.CharField(blank=True, default=None, max_length=50, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="platform",
|
|
||||||
name="group",
|
|
||||||
field=models.CharField(blank=True, default=None, max_length=255, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="session",
|
|
||||||
name="device",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="games.device",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,141 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 18:14
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
def rename_duplicates(apps, schema_editor):
|
|
||||||
Edition = apps.get_model("games", "Edition")
|
|
||||||
|
|
||||||
duplicates = (
|
|
||||||
Edition.objects.values("name", "platform")
|
|
||||||
.annotate(name_count=models.Count("id"))
|
|
||||||
.filter(name_count__gt=1)
|
|
||||||
)
|
|
||||||
|
|
||||||
for duplicate in duplicates:
|
|
||||||
counter = 1
|
|
||||||
duplicate_editions = Edition.objects.filter(
|
|
||||||
name=duplicate["name"], platform_id=duplicate["platform"]
|
|
||||||
).order_by("id")
|
|
||||||
|
|
||||||
for edition in duplicate_editions[1:]: # Skip the first one
|
|
||||||
edition.name = f"{edition.name} {counter}"
|
|
||||||
edition.save()
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
|
|
||||||
def update_game_year(apps, schema_editor):
|
|
||||||
Game = apps.get_model("games", "Game")
|
|
||||||
Edition = apps.get_model("games", "Edition")
|
|
||||||
|
|
||||||
for game in Game.objects.filter(year__isnull=True):
|
|
||||||
# Try to get the first related edition with a non-null year_released
|
|
||||||
edition = Edition.objects.filter(game=game, year_released__isnull=False).first()
|
|
||||||
if edition:
|
|
||||||
# If an edition is found, update the game's year
|
|
||||||
game.year = edition.year_released
|
|
||||||
game.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
replaces = [
|
|
||||||
("games", "0016_alter_edition_platform_alter_edition_year_released_and_more"),
|
|
||||||
("games", "0017_alter_device_type_alter_purchase_platform"),
|
|
||||||
("games", "0018_auto_20231106_1825"),
|
|
||||||
("games", "0019_alter_edition_unique_together"),
|
|
||||||
("games", "0020_game_year"),
|
|
||||||
("games", "0021_auto_20231106_1909"),
|
|
||||||
("games", "0022_rename_year_game_year_released"),
|
|
||||||
]
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("games", "0015_edition_wikidata_edition_year_released"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="edition",
|
|
||||||
name="platform",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="games.platform",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="edition",
|
|
||||||
name="year_released",
|
|
||||||
field=models.IntegerField(blank=True, default=None, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="game",
|
|
||||||
name="wikidata",
|
|
||||||
field=models.CharField(blank=True, default=None, max_length=50, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="platform",
|
|
||||||
name="group",
|
|
||||||
field=models.CharField(blank=True, default=None, max_length=255, null=True),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="session",
|
|
||||||
name="device",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="games.device",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="device",
|
|
||||||
name="type",
|
|
||||||
field=models.CharField(
|
|
||||||
choices=[
|
|
||||||
("pc", "PC"),
|
|
||||||
("co", "Console"),
|
|
||||||
("ha", "Handheld"),
|
|
||||||
("mo", "Mobile"),
|
|
||||||
("sbc", "Single-board computer"),
|
|
||||||
("un", "Unknown"),
|
|
||||||
],
|
|
||||||
default="un",
|
|
||||||
max_length=3,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="purchase",
|
|
||||||
name="platform",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="games.platform",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.RunPython(
|
|
||||||
code=rename_duplicates,
|
|
||||||
),
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name="edition",
|
|
||||||
unique_together={("name", "platform")},
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="game",
|
|
||||||
name="year",
|
|
||||||
field=models.IntegerField(blank=True, default=None, null=True),
|
|
||||||
),
|
|
||||||
migrations.RunPython(
|
|
||||||
code=update_game_year,
|
|
||||||
),
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name="game",
|
|
||||||
old_name="year",
|
|
||||||
new_name="year_released",
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,41 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 16:53
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("games", "0016_alter_edition_platform_alter_edition_year_released_and_more"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="device",
|
|
||||||
name="type",
|
|
||||||
field=models.CharField(
|
|
||||||
choices=[
|
|
||||||
("pc", "PC"),
|
|
||||||
("co", "Console"),
|
|
||||||
("ha", "Handheld"),
|
|
||||||
("mo", "Mobile"),
|
|
||||||
("sbc", "Single-board computer"),
|
|
||||||
("un", "Unknown"),
|
|
||||||
],
|
|
||||||
default="un",
|
|
||||||
max_length=3,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="purchase",
|
|
||||||
name="platform",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
to="games.platform",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,34 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 17:25
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
def rename_duplicates(apps, schema_editor):
|
|
||||||
Edition = apps.get_model("games", "Edition")
|
|
||||||
|
|
||||||
duplicates = (
|
|
||||||
Edition.objects.values("name", "platform")
|
|
||||||
.annotate(name_count=models.Count("id"))
|
|
||||||
.filter(name_count__gt=1)
|
|
||||||
)
|
|
||||||
|
|
||||||
for duplicate in duplicates:
|
|
||||||
counter = 1
|
|
||||||
duplicate_editions = Edition.objects.filter(
|
|
||||||
name=duplicate["name"], platform_id=duplicate["platform"]
|
|
||||||
).order_by("id")
|
|
||||||
|
|
||||||
for edition in duplicate_editions[1:]: # Skip the first one
|
|
||||||
edition.name = f"{edition.name} {counter}"
|
|
||||||
edition.save()
|
|
||||||
counter += 1
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("games", "0017_alter_device_type_alter_purchase_platform"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(rename_duplicates),
|
|
||||||
]
|
|
|
@ -1,17 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 17:26
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("games", "0018_auto_20231106_1825"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name="edition",
|
|
||||||
unique_together={("name", "platform")},
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 18:05
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("games", "0019_alter_edition_unique_together"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="game",
|
|
||||||
name="year",
|
|
||||||
field=models.IntegerField(blank=True, default=None, null=True),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,24 +0,0 @@
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
def update_game_year(apps, schema_editor):
|
|
||||||
Game = apps.get_model("games", "Game")
|
|
||||||
Edition = apps.get_model("games", "Edition")
|
|
||||||
|
|
||||||
for game in Game.objects.filter(year__isnull=True):
|
|
||||||
# Try to get the first related edition with a non-null year_released
|
|
||||||
edition = Edition.objects.filter(game=game, year_released__isnull=False).first()
|
|
||||||
if edition:
|
|
||||||
# If an edition is found, update the game's year
|
|
||||||
game.year = edition.year_released
|
|
||||||
game.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("games", "0020_game_year"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(update_game_year),
|
|
||||||
]
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 18:12
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("games", "0021_auto_20231106_1909"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RenameField(
|
|
||||||
model_name="game",
|
|
||||||
old_name="year",
|
|
||||||
new_name="year_released",
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-06 18:24
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
(
|
|
||||||
"games",
|
|
||||||
"0016_alter_edition_platform_alter_edition_year_released_and_more_squashed_0022_rename_year_game_year_released",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="purchase",
|
|
||||||
name="date_finished",
|
|
||||||
field=models.DateField(blank=True, null=True),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -10,23 +10,17 @@ from django.db.models import F, Manager, Sum
|
||||||
|
|
||||||
class Game(models.Model):
|
class Game(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
year_released = models.IntegerField(null=True, blank=True, default=None)
|
wikidata = models.CharField(max_length=50)
|
||||||
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class Edition(models.Model):
|
class Edition(models.Model):
|
||||||
class Meta:
|
|
||||||
unique_together = [["name", "platform"]]
|
|
||||||
|
|
||||||
game = models.ForeignKey("Game", on_delete=models.CASCADE)
|
game = models.ForeignKey("Game", on_delete=models.CASCADE)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
platform = models.ForeignKey(
|
platform = models.ForeignKey("Platform", on_delete=models.CASCADE)
|
||||||
"Platform", on_delete=models.CASCADE, null=True, blank=True, default=None
|
year_released = models.IntegerField(default=datetime.today().year)
|
||||||
)
|
|
||||||
year_released = models.IntegerField(null=True, blank=True, default=None)
|
|
||||||
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -54,12 +48,9 @@ class Purchase(models.Model):
|
||||||
]
|
]
|
||||||
|
|
||||||
edition = models.ForeignKey("Edition", on_delete=models.CASCADE)
|
edition = models.ForeignKey("Edition", on_delete=models.CASCADE)
|
||||||
platform = models.ForeignKey(
|
platform = models.ForeignKey("Platform", on_delete=models.CASCADE)
|
||||||
"Platform", on_delete=models.CASCADE, default=None, null=True, blank=True
|
|
||||||
)
|
|
||||||
date_purchased = models.DateField()
|
date_purchased = models.DateField()
|
||||||
date_refunded = models.DateField(blank=True, null=True)
|
date_refunded = models.DateField(blank=True, null=True)
|
||||||
date_finished = models.DateField(blank=True, null=True)
|
|
||||||
price = models.IntegerField(default=0)
|
price = models.IntegerField(default=0)
|
||||||
price_currency = models.CharField(max_length=3, default="USD")
|
price_currency = models.CharField(max_length=3, default="USD")
|
||||||
ownership_type = models.CharField(
|
ownership_type = models.CharField(
|
||||||
|
@ -75,7 +66,7 @@ class Purchase(models.Model):
|
||||||
|
|
||||||
class Platform(models.Model):
|
class Platform(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
group = models.CharField(max_length=255, null=True, blank=True, default=None)
|
group = models.CharField(max_length=255)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -98,13 +89,7 @@ class Session(models.Model):
|
||||||
timestamp_end = models.DateTimeField(blank=True, null=True)
|
timestamp_end = models.DateTimeField(blank=True, null=True)
|
||||||
duration_manual = models.DurationField(blank=True, null=True, default=timedelta(0))
|
duration_manual = models.DurationField(blank=True, null=True, default=timedelta(0))
|
||||||
duration_calculated = models.DurationField(blank=True, null=True)
|
duration_calculated = models.DurationField(blank=True, null=True)
|
||||||
device = models.ForeignKey(
|
device = models.ForeignKey("Device", on_delete=models.CASCADE, null=True)
|
||||||
"Device",
|
|
||||||
on_delete=models.CASCADE,
|
|
||||||
null=True,
|
|
||||||
blank=True,
|
|
||||||
default=None,
|
|
||||||
)
|
|
||||||
note = models.TextField(blank=True, null=True)
|
note = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
objects = SessionQuerySet.as_manager()
|
objects = SessionQuerySet.as_manager()
|
||||||
|
@ -141,12 +126,6 @@ class Session(models.Model):
|
||||||
self.duration_calculated = self.timestamp_end - self.timestamp_start
|
self.duration_calculated = self.timestamp_end - self.timestamp_start
|
||||||
else:
|
else:
|
||||||
self.duration_calculated = timedelta(0)
|
self.duration_calculated = timedelta(0)
|
||||||
|
|
||||||
if not self.device:
|
|
||||||
default_device, _ = Device.objects.get_or_create(
|
|
||||||
type=Device.UNKNOWN, defaults={"name": "Unknown"}
|
|
||||||
)
|
|
||||||
self.device = default_device
|
|
||||||
super(Session, self).save(*args, **kwargs)
|
super(Session, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,17 +135,15 @@ class Device(models.Model):
|
||||||
HANDHELD = "ha"
|
HANDHELD = "ha"
|
||||||
MOBILE = "mo"
|
MOBILE = "mo"
|
||||||
SBC = "sbc"
|
SBC = "sbc"
|
||||||
UNKNOWN = "un"
|
|
||||||
DEVICE_TYPES = [
|
DEVICE_TYPES = [
|
||||||
(PC, "PC"),
|
(PC, "PC"),
|
||||||
(CONSOLE, "Console"),
|
(CONSOLE, "Console"),
|
||||||
(HANDHELD, "Handheld"),
|
(HANDHELD, "Handheld"),
|
||||||
(MOBILE, "Mobile"),
|
(MOBILE, "Mobile"),
|
||||||
(SBC, "Single-board computer"),
|
(SBC, "Single-board computer"),
|
||||||
(UNKNOWN, "Unknown"),
|
|
||||||
]
|
]
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
type = models.CharField(max_length=3, choices=DEVICE_TYPES, default=UNKNOWN)
|
type = models.CharField(max_length=3, choices=DEVICE_TYPES, default=PC)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name} ({self.get_type_display()})"
|
return f"{self.name} ({self.get_type_display()})"
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
<h2 class="text-lg my-2 ml-2">
|
<h2 class="text-lg my-2 ml-2">
|
||||||
{{ total_hours }} <span class="dark:text-slate-500">total</span>
|
{{ total_hours }} <span class="dark:text-slate-500">total</span>
|
||||||
{{ session_average }} <span class="dark:text-slate-500">avg</span>
|
{{ session_average }} <span class="dark:text-slate-500">avg</span>
|
||||||
({{ playrange }}) </h2>
|
({{ first_session.timestamp_start | date:"M Y"}}
|
||||||
|
—
|
||||||
|
{{ last_session.timestamp_start | date:"M Y"}}) </h2>
|
||||||
<hr class="border-slate-500">
|
<hr class="border-slate-500">
|
||||||
<h1 class="text-3xl mt-4 mb-1">Editions <span class="dark:text-slate-500">({{ editions.count }})</span></h1>
|
<h1 class="text-3xl mt-4 mb-1">Editions <span class="dark:text-slate-500">({{ editions.count }})</span></h1>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -137,15 +137,8 @@ def view_game(request, game_id=None):
|
||||||
# here first and last is flipped
|
# here first and last is flipped
|
||||||
# because sessions are ordered from newest to oldest
|
# because sessions are ordered from newest to oldest
|
||||||
# so the most recent are on top
|
# so the most recent are on top
|
||||||
playrange_start = context["sessions"].last().timestamp_start.strftime("%b %Y")
|
context["last_session"] = context["sessions"].first()
|
||||||
playrange_end = context["sessions"].first().timestamp_start.strftime("%b %Y")
|
context["first_session"] = context["sessions"].last()
|
||||||
|
|
||||||
context["playrange"] = (
|
|
||||||
playrange_start
|
|
||||||
if playrange_start == playrange_end
|
|
||||||
else f"{playrange_start} — {playrange_end}"
|
|
||||||
)
|
|
||||||
|
|
||||||
context["sessions_with_notes"] = context["sessions"].exclude(note="")
|
context["sessions_with_notes"] = context["sessions"].exclude(note="")
|
||||||
request.session["return_path"] = request.path
|
request.session["return_path"] = request.path
|
||||||
return render(request, "view_game.html", context)
|
return render(request, "view_game.html", context)
|
||||||
|
|
Loading…
Reference in New Issue