Compare commits
6 Commits
d78139a5b3
...
f9b53da19c
Author | SHA1 | Date |
---|---|---|
Lukáš Kucharczyk | f9b53da19c | |
Lukáš Kucharczyk | 9a0e505aae | |
Lukáš Kucharczyk | c9deba7d65 | |
Lukáš Kucharczyk | c55fbe86b5 | |
Lukáš Kucharczyk | 0e93993498 | |
Lukáš Kucharczyk | 9fccdfbff0 |
|
@ -23,6 +23,12 @@
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration-color: #ff4400;
|
||||
color: rgb(254, 185, 160);
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
form label {
|
||||
@apply dark:text-slate-400;
|
||||
}
|
||||
|
|
|
@ -1173,6 +1173,12 @@ select {
|
|||
font-style: normal;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration-color: #ff4400;
|
||||
color: rgb(254, 185, 160);
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
:is(.dark form label) {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(148 163 184 / var(--tw-text-opacity));
|
||||
|
@ -1477,10 +1483,6 @@ th label {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.md\:w-1\/2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.md\:w-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
</select>
|
||||
</form>
|
||||
</div>
|
||||
<div class="flex flex-column flex-wrap justify-center">
|
||||
<div class="md:w-1/2">
|
||||
<h1 class="text-5xl text-center my-6">Playtime</h1>
|
||||
<table class="responsive-table">
|
||||
<tbody>
|
||||
|
@ -51,10 +49,16 @@
|
|||
<td class="px-2 sm:px-4 md:px-6 md:py-2">Finished ({{ year }})</td>
|
||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ this_year_finished_this_year.count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-2 sm:px-4 md:px-6 md:py-2">Longest session</td>
|
||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ longest_session_time }} ({{ longest_session_game }})</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="px-2 sm:px-4 md:px-6 md:py-2">Most sessions</td>
|
||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ highest_session_count }} ({{ highest_session_count_game }})</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="md:w-1/2">
|
||||
<h1 class="text-5xl text-center my-6">Purchases</h1>
|
||||
<table class="responsive-table">
|
||||
<tbody>
|
||||
|
|
|
@ -2,8 +2,8 @@ from datetime import datetime, timedelta
|
|||
from typing import Any, Callable
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Count, F, Prefetch, Q, Sum
|
||||
from django.db.models.functions import TruncDate
|
||||
from django.db.models import Count, ExpressionWrapper, F, Prefetch, Q, Sum, fields
|
||||
from django.db.models.functions import Extract, TruncDate
|
||||
from django.http import (
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
|
@ -30,11 +30,11 @@ from .models import Edition, Game, Platform, Purchase, Session
|
|||
|
||||
def model_counts(request):
|
||||
return {
|
||||
"game_available": Game.objects.count() != 0,
|
||||
"edition_available": Edition.objects.count() != 0,
|
||||
"platform_available": Platform.objects.count() != 0,
|
||||
"purchase_available": Purchase.objects.count() != 0,
|
||||
"session_count": Session.objects.count(),
|
||||
"game_available": Game.objects.exists(),
|
||||
"edition_available": Edition.objects.exists(),
|
||||
"platform_available": Platform.objects.exists(),
|
||||
"purchase_available": Purchase.objects.exists(),
|
||||
"session_count": Session.objects.exists(),
|
||||
}
|
||||
|
||||
|
||||
|
@ -321,6 +321,22 @@ def stats(request, year: int = 0):
|
|||
if year == 0:
|
||||
year = timezone.now().year
|
||||
this_year_sessions = Session.objects.filter(timestamp_start__year=year)
|
||||
this_year_sessions_with_durations = this_year_sessions.annotate(
|
||||
duration=ExpressionWrapper(
|
||||
F("timestamp_end") - F("timestamp_start"),
|
||||
output_field=fields.DurationField(),
|
||||
)
|
||||
)
|
||||
longest_session = this_year_sessions_with_durations.order_by("-duration").first()
|
||||
this_year_games_with_session_counts = Game.objects.annotate(
|
||||
session_count=Count(
|
||||
"edition__purchase__session",
|
||||
filter=Q(edition__purchase__session__timestamp_start__year=year),
|
||||
)
|
||||
)
|
||||
game_highest_session_count = this_year_games_with_session_counts.order_by(
|
||||
"-session_count"
|
||||
).first()
|
||||
selected_currency = "CZK"
|
||||
unique_days = (
|
||||
this_year_sessions.annotate(date=TruncDate("timestamp_start"))
|
||||
|
@ -444,6 +460,13 @@ def stats(request, year: int = 0):
|
|||
"date_purchased"
|
||||
),
|
||||
"backlog_decrease_count": backlog_decrease_count,
|
||||
"longest_session_time": format_duration(
|
||||
longest_session.duration if longest_session else timedelta(0),
|
||||
"%2.0Hh%2.0mm",
|
||||
),
|
||||
"longest_session_game": longest_session.purchase.edition.name,
|
||||
"highest_session_count": game_highest_session_count.session_count,
|
||||
"highest_session_count_game": game_highest_session_count.name,
|
||||
}
|
||||
|
||||
request.session["return_path"] = request.path
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.7.2"
|
||||
description = "ASGI specs, helper code, and adapters"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -18,6 +19,7 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
|||
name = "black"
|
||||
version = "22.12.0"
|
||||
description = "The uncompromising code formatter."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -51,6 +53,7 @@ uvloop = ["uvloop (>=0.15.2)"]
|
|||
name = "cfgv"
|
||||
version = "3.4.0"
|
||||
description = "Validate configuration and produce human readable error messages."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -62,6 +65,7 @@ files = [
|
|||
name = "click"
|
||||
version = "8.1.7"
|
||||
description = "Composable command line interface toolkit"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -76,6 +80,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
files = [
|
||||
|
@ -87,6 +92,7 @@ files = [
|
|||
name = "cssbeautifier"
|
||||
version = "1.14.11"
|
||||
description = "CSS unobfuscator and beautifier."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
|
@ -102,6 +108,7 @@ six = ">=1.13.0"
|
|||
name = "distlib"
|
||||
version = "0.3.7"
|
||||
description = "Distribution utilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
|
@ -113,6 +120,7 @@ files = [
|
|||
name = "django"
|
||||
version = "4.2.7"
|
||||
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -129,10 +137,27 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
|||
argon2 = ["argon2-cffi (>=19.1.0)"]
|
||||
bcrypt = ["bcrypt"]
|
||||
|
||||
[[package]]
|
||||
name = "django-debug-toolbar"
|
||||
version = "4.2.0"
|
||||
description = "A configurable set of panels that display various debug information about the current request/response."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "django_debug_toolbar-4.2.0-py3-none-any.whl", hash = "sha256:af99128c06e8e794479e65ab62cc6c7d1e74e1c19beb44dcbf9bad7a9c017327"},
|
||||
{file = "django_debug_toolbar-4.2.0.tar.gz", hash = "sha256:bc7fdaafafcdedefcc67a4a5ad9dac96efd6e41db15bc74d402a54a2ba4854dc"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
django = ">=3.2.4"
|
||||
sqlparse = ">=0.2"
|
||||
|
||||
[[package]]
|
||||
name = "django-extensions"
|
||||
version = "3.2.3"
|
||||
description = "Extensions for Django"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
|
@ -147,6 +172,7 @@ Django = ">=3.2"
|
|||
name = "djhtml"
|
||||
version = "1.5.2"
|
||||
description = "Django/Jinja template indenter"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
|
@ -160,6 +186,7 @@ dev = ["black", "flake8", "isort", "nox", "pre-commit"]
|
|||
name = "djlint"
|
||||
version = "1.34.0"
|
||||
description = "HTML Template Linter and Formatter"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8.0,<4.0.0"
|
||||
files = [
|
||||
|
@ -184,6 +211,7 @@ tqdm = ">=4.62.2,<5.0.0"
|
|||
name = "editorconfig"
|
||||
version = "0.12.3"
|
||||
description = "EditorConfig File Locator and Interpreter for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
|
@ -195,6 +223,7 @@ files = [
|
|||
name = "filelock"
|
||||
version = "3.13.1"
|
||||
description = "A platform independent file lock."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -211,6 +240,7 @@ typing = ["typing-extensions (>=4.8)"]
|
|||
name = "gunicorn"
|
||||
version = "20.1.0"
|
||||
description = "WSGI HTTP Server for UNIX"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
|
@ -231,6 +261,7 @@ tornado = ["tornado (>=0.2)"]
|
|||
name = "h11"
|
||||
version = "0.14.0"
|
||||
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -242,6 +273,7 @@ files = [
|
|||
name = "html-tag-names"
|
||||
version = "0.1.2"
|
||||
description = "List of known HTML tag names"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
files = [
|
||||
|
@ -253,6 +285,7 @@ files = [
|
|||
name = "html-void-elements"
|
||||
version = "0.1.0"
|
||||
description = "List of HTML void tag names."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
files = [
|
||||
|
@ -264,6 +297,7 @@ files = [
|
|||
name = "identify"
|
||||
version = "2.5.31"
|
||||
description = "File identification library for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -278,6 +312,7 @@ license = ["ukkonen"]
|
|||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
description = "brain-dead simple config-ini parsing"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -289,6 +324,7 @@ files = [
|
|||
name = "isort"
|
||||
version = "5.12.0"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8.0"
|
||||
files = [
|
||||
|
@ -306,6 +342,7 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"]
|
|||
name = "jsbeautifier"
|
||||
version = "1.14.11"
|
||||
description = "JavaScript unobfuscator and beautifier."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
|
@ -320,6 +357,7 @@ six = ">=1.13.0"
|
|||
name = "json5"
|
||||
version = "0.9.14"
|
||||
description = "A Python implementation of the JSON5 data format."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
|
@ -334,6 +372,7 @@ dev = ["hypothesis"]
|
|||
name = "markupsafe"
|
||||
version = "2.1.3"
|
||||
description = "Safely add untrusted strings to HTML/XML markup."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -403,6 +442,7 @@ files = [
|
|||
name = "mypy"
|
||||
version = "0.991"
|
||||
description = "Optional static typing for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -452,6 +492,7 @@ reports = ["lxml"]
|
|||
name = "mypy-extensions"
|
||||
version = "1.0.0"
|
||||
description = "Type system extensions for programs checked with the mypy type checker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
|
@ -463,6 +504,7 @@ files = [
|
|||
name = "nodeenv"
|
||||
version = "1.8.0"
|
||||
description = "Node.js virtual environment builder"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
||||
files = [
|
||||
|
@ -477,6 +519,7 @@ setuptools = "*"
|
|||
name = "packaging"
|
||||
version = "23.2"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -488,6 +531,7 @@ files = [
|
|||
name = "pathspec"
|
||||
version = "0.11.2"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -499,6 +543,7 @@ files = [
|
|||
name = "platformdirs"
|
||||
version = "3.11.0"
|
||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -514,6 +559,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co
|
|||
name = "pluggy"
|
||||
version = "1.3.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -529,6 +575,7 @@ testing = ["pytest", "pytest-benchmark"]
|
|||
name = "pre-commit"
|
||||
version = "3.5.0"
|
||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -547,6 +594,7 @@ virtualenv = ">=20.10.0"
|
|||
name = "pytest"
|
||||
version = "7.4.3"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -567,6 +615,7 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no
|
|||
name = "pyyaml"
|
||||
version = "6.0.1"
|
||||
description = "YAML parser and emitter for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
|
@ -626,6 +675,7 @@ files = [
|
|||
name = "regex"
|
||||
version = "2023.10.3"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -723,6 +773,7 @@ files = [
|
|||
name = "setuptools"
|
||||
version = "68.2.2"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -739,6 +790,7 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar
|
|||
name = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
files = [
|
||||
|
@ -750,6 +802,7 @@ files = [
|
|||
name = "sqlparse"
|
||||
version = "0.4.4"
|
||||
description = "A non-validating SQL parser."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
|
@ -766,6 +819,7 @@ test = ["pytest", "pytest-cov"]
|
|||
name = "tqdm"
|
||||
version = "4.66.1"
|
||||
description = "Fast, Extensible Progress Meter"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -786,6 +840,7 @@ telegram = ["requests"]
|
|||
name = "typing-extensions"
|
||||
version = "4.8.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -797,6 +852,7 @@ files = [
|
|||
name = "tzdata"
|
||||
version = "2023.3"
|
||||
description = "Provider of IANA time zone data"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2"
|
||||
files = [
|
||||
|
@ -808,6 +864,7 @@ files = [
|
|||
name = "uvicorn"
|
||||
version = "0.20.0"
|
||||
description = "The lightning-fast ASGI server."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -826,6 +883,7 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
|
|||
name = "virtualenv"
|
||||
version = "20.24.6"
|
||||
description = "Virtual Python Environment builder"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
|
@ -846,6 +904,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess
|
|||
name = "werkzeug"
|
||||
version = "2.3.8"
|
||||
description = "The comprehensive WSGI web application library."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
|
@ -862,4 +921,4 @@ watchdog = ["watchdog (>=2.3)"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.12"
|
||||
content-hash = "32e7c40e7148530effb10ebd5d67a4f1c8fe30794a4d3b5d213d4f30048c79ea"
|
||||
content-hash = "498b3358998a9f3bbfb74fae7d6a90de7b55b9bdc76845bce52f65785afd0c1e"
|
||||
|
|
|
@ -24,6 +24,7 @@ djhtml = "^1.5.2"
|
|||
djlint = "^1.19.11"
|
||||
isort = "^5.11.4"
|
||||
pre-commit = "^3.5.0"
|
||||
django-debug-toolbar = "^4.2.0"
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
|
|
|
@ -43,6 +43,7 @@ INSTALLED_APPS = [
|
|||
if DEBUG:
|
||||
INSTALLED_APPS.append("django_extensions")
|
||||
INSTALLED_APPS.append("django.contrib.admin")
|
||||
INSTALLED_APPS.append("debug_toolbar")
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
|
@ -54,6 +55,11 @@ MIDDLEWARE = [
|
|||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
]
|
||||
|
||||
if DEBUG:
|
||||
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
|
||||
INTERNAL_IPS = ["127.0.0.1"]
|
||||
DEBUG_TOOLBAR_CONFIG = {"ROOT_TAG_EXTRA_ATTRS": "hx-preserve"}
|
||||
|
||||
ROOT_URLCONF = "timetracker.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
|
|
|
@ -25,3 +25,4 @@ urlpatterns = [
|
|||
|
||||
if settings.DEBUG:
|
||||
urlpatterns.append(path("admin/", admin.site.urls))
|
||||
urlpatterns.append(path("__debug__/", include("debug_toolbar.urls")))
|
||||
|
|
Loading…
Reference in New Issue