linkify game, edition, purchase, session references
Django CI/CD / test (push) Successful in 1m0s Details
Django CI/CD / build-and-push (push) Has been cancelled Details

also add link styles for links in a table row
This commit is contained in:
Lukáš Kucharczyk 2024-09-02 20:04:21 +02:00
parent b8258e2937
commit e067e65bce
Signed by: lukas
SSH Key Fingerprint: SHA256:vMuSwvwAvcT6htVAioMP7rzzwMQNi3roESyhv+nAxeg
7 changed files with 174 additions and 85 deletions

View File

@ -27,6 +27,20 @@ def Popover(
return result
HTMLAttribute = tuple[str, str]
HTMLTag = str
def A(attributes: list[HTMLAttribute], children: list[HTMLTag] | HTMLTag) -> HTMLTag:
if isinstance(children, str):
children = [children]
childrenBlob = "\n".join(children)
attributesList = [f'{name} = "{value}"' for name, value in attributes]
attributesBlob = " ".join(attributesList)
tag: str = f"<a {attributesBlob}>{childrenBlob}</a>"
return mark_safe(tag)
def safe_division(numerator: int | float, denominator: int | float) -> int | float:
"""
Divides without triggering division by zero exception.

View File

@ -1386,6 +1386,10 @@ input:checked + .toggle-bg {
margin-bottom: 1rem;
}
.mb-6 {
margin-bottom: 1.5rem;
}
.mb-8 {
margin-bottom: 2rem;
}
@ -1394,10 +1398,6 @@ input:checked + .toggle-bg {
margin-inline-end: 0.5rem;
}
.ml-1 {
margin-left: 0.25rem;
}
.mr-4 {
margin-right: 1rem;
}
@ -1422,14 +1422,6 @@ input:checked + .toggle-bg {
margin-top: 1rem;
}
.mb-5 {
margin-bottom: 1.25rem;
}
.mb-6 {
margin-bottom: 1.5rem;
}
.block {
display: block;
}
@ -1479,10 +1471,6 @@ input:checked + .toggle-bg {
height: 0.625rem;
}
.h-3 {
height: 0.75rem;
}
.h-4 {
height: 1rem;
}
@ -1543,10 +1531,6 @@ input:checked + .toggle-bg {
width: 16rem;
}
.w-7 {
width: 1.75rem;
}
.w-full {
width: 100%;
}
@ -1705,12 +1689,6 @@ input:checked + .toggle-bg {
margin-left: calc(-1px * calc(1 - var(--tw-space-x-reverse)));
}
.space-x-1 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.25rem * var(--tw-space-x-reverse));
margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
}
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
@ -1764,10 +1742,6 @@ input:checked + .toggle-bg {
border-radius: 0.25rem;
}
.rounded-full {
border-radius: 9999px;
}
.rounded-lg {
border-radius: 0.5rem;
}
@ -1886,11 +1860,6 @@ input:checked + .toggle-bg {
background-color: rgb(5 122 85 / var(--tw-bg-opacity));
}
.bg-violet-600 {
--tw-bg-opacity: 1;
background-color: rgb(124 58 237 / var(--tw-bg-opacity));
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@ -2000,10 +1969,6 @@ input:checked + .toggle-bg {
vertical-align: top;
}
.font-condensed {
font-family: IBM Plex Sans Condensed, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
.font-mono {
font-family: IBM Plex Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
@ -2174,6 +2139,18 @@ input:checked + .toggle-bg {
text-decoration-color: #64748b;
}
.decoration-wavy {
text-decoration-style: wavy;
}
.underline-offset-2 {
text-underline-offset: 2px;
}
.underline-offset-4 {
text-underline-offset: 4px;
}
.opacity-0 {
opacity: 0;
}
@ -2239,6 +2216,12 @@ input:checked + .toggle-bg {
transition-duration: 150ms;
}
.transition-all {
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-200 {
transition-duration: 200ms;
}
@ -2247,6 +2230,14 @@ input:checked + .toggle-bg {
transition-duration: 300ms;
}
.duration-1000 {
transition-duration: 1000ms;
}
.duration-500 {
transition-duration: 500ms;
}
.ease-in {
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
@ -2573,11 +2564,6 @@ textarea:disabled:is(.dark *) {
background-color: rgb(240 82 82 / var(--tw-bg-opacity));
}
.hover\:bg-violet-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(109 40 217 / var(--tw-bg-opacity));
}
.hover\:bg-white:hover {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@ -2613,6 +2599,10 @@ textarea:disabled:is(.dark *) {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.hover\:decoration-red-600:hover {
text-decoration-color: #E02424;
}
.focus\:z-10:focus {
z-index: 10;
}
@ -2664,11 +2654,6 @@ textarea:disabled:is(.dark *) {
--tw-ring-color: rgb(4 108 78 / var(--tw-ring-opacity));
}
.focus\:ring-violet-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(139 92 246 / var(--tw-ring-opacity));
}
.focus\:ring-offset-2:focus {
--tw-ring-offset-width: 2px;
}
@ -2677,10 +2662,6 @@ textarea:disabled:is(.dark *) {
--tw-ring-offset-color: #C3DDFD;
}
.focus\:ring-offset-violet-200:focus {
--tw-ring-offset-color: #ddd6fe;
}
.group:hover .group-hover\:absolute {
position: absolute;
}
@ -2848,11 +2829,6 @@ textarea:disabled:is(.dark *) {
color: rgb(148 163 184 / var(--tw-text-opacity));
}
.dark\:text-slate-500:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(100 116 139 / var(--tw-text-opacity));
}
.dark\:text-slate-600:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(71 85 105 / var(--tw-text-opacity));
@ -2979,14 +2955,6 @@ textarea:disabled:is(.dark *) {
padding-right: 1rem;
}
.sm\:pl-2 {
padding-left: 0.5rem;
}
.sm\:pl-4 {
padding-left: 1rem;
}
.sm\:decoration-2 {
text-decoration-thickness: 2px;
}
@ -3058,11 +3026,6 @@ textarea:disabled:is(.dark *) {
padding-bottom: 0.5rem;
}
.md\:text-5xl {
font-size: 3rem;
line-height: 1;
}
.md\:text-blue-700 {
--tw-text-opacity: 1;
color: rgb(26 86 219 / var(--tw-text-opacity));
@ -3113,11 +3076,6 @@ textarea:disabled:is(.dark *) {
.lg\:max-w-lg {
max-width: 32rem;
}
.lg\:text-6xl {
font-size: 3.75rem;
line-height: 1;
}
}
@media (min-width: 1536px) {
@ -3152,3 +3110,76 @@ textarea:disabled:is(.dark *) {
border-start-end-radius: 0.5rem;
border-end-end-radius: 0.5rem;
}
.\[\&\>a\]\:underline>a {
text-decoration-line: underline;
}
.\[\&_a\]\:underline a {
text-decoration-line: underline;
}
.\[\&_a\]\:decoration-double a {
text-decoration-style: double;
}
.\[\&_a\]\:decoration-dashed a {
text-decoration-style: dashed;
}
.\[\&_a\]\:decoration-wavy a {
text-decoration-style: wavy;
}
.\[\&_a\]\:decoration-2 a {
text-decoration-thickness: 2px;
}
.\[\&_a\]\:underline-offset-4 a {
text-underline-offset: 4px;
}
.\[\&_a\]\:hover\:bg-purple-800:hover a {
--tw-bg-opacity: 1;
background-color: rgb(85 33 181 / var(--tw-bg-opacity));
}
.\[\&_a\]\:hover\:p-5:hover a {
padding: 1.25rem;
}
.\[\&_a\]\:hover\:p-1:hover a {
padding: 0.25rem;
}
.\[\&_a\]\:hover\:decoration-red-600:hover a {
text-decoration-color: #E02424;
}
.\[\&_a\]\:hover\:decoration-purple-600:hover a {
text-decoration-color: #7E3AF2;
}
.\[\&_a\]\:hover\:decoration-purple-300:hover a {
text-decoration-color: #CABFFD;
}
.\[\&_a\]\:hover\:decoration-purple-400:hover a {
text-decoration-color: #AC94FA;
}
.\[\&_a\]\:hover\:decoration-purple-500:hover a {
text-decoration-color: #9061F9;
}
.\[\&_a\]\:hover\:decoration-purple-900:hover a {
text-decoration-color: #4A1D96;
}
.\[\&_a\]\:hover\:decoration-gray-800:hover a {
text-decoration-color: #1F2937;
}
.\[\&_a\]\:hover\:underline-offset-8:hover a {
text-underline-offset: 8px;
}

View File

@ -1,4 +1,4 @@
<tr class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border-b">
<tr class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border-b [&_a]:underline [&_a]:underline-offset-4 [&_a]:decoration-2">
{% if slot %}
{{ slot }}
{% else %}

View File

@ -7,7 +7,7 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse
from common.utils import truncate_with_popover
from common.utils import A, truncate_with_popover
from games.forms import EditionForm
from games.models import Edition, Game
from games.views.general import dateformat
@ -48,7 +48,18 @@ def list_editions(request: HttpRequest) -> HttpResponse:
],
"rows": [
[
truncate_with_popover(edition.game.name),
A(
[
(
"href",
reverse(
"view_game",
args=[edition.game.pk],
),
)
],
truncate_with_popover(edition.game.name),
),
truncate_with_popover(
edition.name
if edition.game.name != edition.name

View File

@ -9,7 +9,7 @@ from django.template.loader import render_to_string
from django.urls import reverse
from common.time import format_duration
from common.utils import safe_division, truncate_with_popover
from common.utils import A, safe_division, truncate_with_popover
from games.forms import GameForm
from games.models import Edition, Game, Purchase, Session
from games.views.general import (
@ -55,7 +55,18 @@ def list_games(request: HttpRequest) -> HttpResponse:
],
"rows": [
[
truncate_with_popover(game.name),
A(
[
(
"href",
reverse(
"view_game",
args=[game.pk],
),
)
],
truncate_with_popover(game.name),
),
truncate_with_popover(
game.sort_name
if game.sort_name is not None and game.name != game.sort_name

View File

@ -13,7 +13,7 @@ from django.template.loader import render_to_string
from django.urls import reverse
from django.utils import timezone
from common.utils import truncate_with_popover
from common.utils import A, truncate_with_popover
from games.forms import PurchaseForm
from games.models import Edition, Purchase
from games.views.general import dateformat, use_custom_redirect
@ -57,7 +57,18 @@ def list_purchases(request: HttpRequest) -> HttpResponse:
],
"rows": [
[
truncate_with_popover(purchase.edition.name),
A(
[
(
"href",
reverse(
"view_game",
args=[purchase.edition.game.pk],
),
),
],
truncate_with_popover(purchase.edition.game.name),
),
purchase.platform,
purchase.price,
purchase.price_currency,

View File

@ -9,7 +9,7 @@ from django.urls import reverse
from django.utils import timezone
from common.time import format_duration
from common.utils import truncate_with_popover
from common.utils import A, truncate_with_popover
from games.forms import SessionForm
from games.models import Purchase, Session
from games.views.general import (
@ -56,7 +56,18 @@ def list_sessions(request: HttpRequest) -> HttpResponse:
],
"rows": [
[
truncate_with_popover(session.purchase.edition.name),
A(
[
(
"href",
reverse(
"view_game",
args=[session.purchase.edition.game.pk],
),
)
],
truncate_with_popover(session.purchase.edition.name),
),
f"{session.timestamp_start.strftime(datetimeformat)}{f"{session.timestamp_end.strftime(timeformat)}" if session.timestamp_end else ""}",
(
format_duration(session.duration_calculated, durationformat)