Improve game links
Django CI/CD / test (push) Successful in 1m6s Details
Django CI/CD / build-and-push (push) Successful in 1m56s Details

This commit is contained in:
Lukáš Kucharczyk 2024-07-09 19:40:47 +02:00
parent 86f8fde8fa
commit ba44814474
Signed by: lukas
SSH Key Fingerprint: SHA256:vMuSwvwAvcT6htVAioMP7rzzwMQNi3roESyhv+nAxeg
11 changed files with 263 additions and 54 deletions

View File

@ -15,6 +15,7 @@
* ignore manual sessions when calculating session average * ignore manual sessions when calculating session average
* stats: improve purchase name consistency * stats: improve purchase name consistency
* session list: use display name instead of sort name * session list: use display name instead of sort name
* unify the appearance of game links, and make them expand to full size on hover
## Fixed ## Fixed
* Fix title not being displayed on the Recent sessions page * Fix title not being displayed on the Recent sessions page

View File

@ -23,18 +23,18 @@
font-style: normal; font-style: normal;
} }
a:hover { /* a:hover {
text-decoration-color: #ff4400; text-decoration-color: #ff4400;
color: rgb(254, 185, 160); color: rgb(254, 185, 160);
transition: all 0.2s ease-out; transition: all 0.2s ease-out;
} } */
form label { form label {
@apply dark:text-slate-400; @apply dark:text-slate-400;
} }
.responsive-table { .responsive-table {
@apply dark:text-white mx-auto; @apply dark:text-white mx-auto table-fixed;
} }
.responsive-table tr:nth-child(even) { .responsive-table tr:nth-child(even) {
@ -58,8 +58,11 @@ form label {
.max-w-20char { .max-w-20char {
max-width: 20ch; max-width: 20ch;
} }
.max-w-30char {
max-width: 30ch;
}
.max-w-35char { .max-w-35char {
max-width: 40ch; max-width: 35ch;
} }
.max-w-40char { .max-w-40char {
max-width: 40ch; max-width: 40ch;
@ -145,3 +148,13 @@ th label {
margin-bottom: 0.5em; margin-bottom: 0.5em;
padding-left: 1em; padding-left: 1em;
} }
.truncate-container {
@apply inline-block relative transition-all;
a {
@apply inline-block truncate max-w-20char;
&:hover {
@apply absolute max-w-none -top-8 -left-6 min-w-60 px-6 py-3.5 bg-purple-600 rounded-sm outline-dashed outline-purple-400 outline-4;
}
}
}

View File

@ -1,5 +1,5 @@
/* /*
! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com ! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com
*/ */
/* /*
@ -783,6 +783,18 @@ select {
} }
} }
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
.invisible { .invisible {
visibility: hidden; visibility: hidden;
} }
@ -819,6 +831,14 @@ select {
top: 0.75rem; top: 0.75rem;
} }
.-left-6 {
left: -1.5rem;
}
.-top-\[31\.5px\] {
top: -31.5px;
}
.mx-2 { .mx-2 {
margin-left: 0.5rem; margin-left: 0.5rem;
margin-right: 0.5rem; margin-right: 0.5rem;
@ -860,6 +880,10 @@ select {
margin-bottom: 2rem; margin-bottom: 2rem;
} }
.me-2 {
margin-inline-end: 0.5rem;
}
.ml-1 { .ml-1 {
margin-left: 0.25rem; margin-left: 0.25rem;
} }
@ -892,6 +916,10 @@ select {
display: flex; display: flex;
} }
.inline-flex {
display: inline-flex;
}
.table { .table {
display: table; display: table;
} }
@ -900,12 +928,12 @@ select {
display: none; display: none;
} }
.h-24 { .h-12 {
height: 6rem; height: 3rem;
} }
.h-3 { .h-24 {
height: 0.75rem; height: 6rem;
} }
.h-4 { .h-4 {
@ -924,6 +952,10 @@ select {
min-height: 100vh; min-height: 100vh;
} }
.w-24 {
width: 6rem;
}
.w-5 { .w-5 {
width: 1.25rem; width: 1.25rem;
} }
@ -944,6 +976,10 @@ select {
width: 100%; width: 100%;
} }
.min-w-60 {
min-width: 15rem;
}
.max-w-screen-lg { .max-w-screen-lg {
max-width: 1024px; max-width: 1024px;
} }
@ -1036,6 +1072,11 @@ select {
border-color: rgb(100 116 139 / var(--tw-border-opacity)); border-color: rgb(100 116 139 / var(--tw-border-opacity));
} }
.bg-blue-700 {
--tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
}
.bg-gray-200 { .bg-gray-200 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(229 231 235 / var(--tw-bg-opacity)); background-color: rgb(229 231 235 / var(--tw-bg-opacity));
@ -1051,6 +1092,14 @@ select {
background-color: rgb(124 58 237 / var(--tw-bg-opacity)); background-color: rgb(124 58 237 / var(--tw-bg-opacity));
} }
.p-2 {
padding: 0.5rem;
}
.p-2\.5 {
padding: 0.625rem;
}
.p-4 { .p-4 {
padding: 1rem; padding: 1rem;
} }
@ -1075,6 +1124,16 @@ select {
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
} }
.px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.py-\[13\.5px\] {
padding-top: 13.5px;
padding-bottom: 13.5px;
}
.pb-16 { .pb-16 {
padding-bottom: 4rem; padding-bottom: 4rem;
} }
@ -1099,6 +1158,10 @@ select {
text-align: center; text-align: center;
} }
.align-top {
vertical-align: top;
}
.font-mono { .font-mono {
font-family: IBM Plex Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-family: IBM Plex Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
} }
@ -1128,6 +1191,11 @@ select {
line-height: 1.75rem; line-height: 1.75rem;
} }
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
.text-xl { .text-xl {
font-size: 1.25rem; font-size: 1.25rem;
line-height: 1.75rem; line-height: 1.75rem;
@ -1138,6 +1206,10 @@ select {
line-height: 1rem; line-height: 1rem;
} }
.font-medium {
font-weight: 500;
}
.font-semibold { .font-semibold {
font-weight: 600; font-weight: 600;
} }
@ -1244,11 +1316,11 @@ select {
font-style: normal; font-style: normal;
} }
a:hover { /* a:hover {
text-decoration-color: #ff4400; text-decoration-color: #ff4400;
color: rgb(254, 185, 160); color: rgb(254, 185, 160);
transition: all 0.2s ease-out; transition: all 0.2s ease-out;
} } */
form label:is(.dark *) { form label:is(.dark *) {
--tw-text-opacity: 1; --tw-text-opacity: 1;
@ -1258,6 +1330,7 @@ form label:is(.dark *) {
.responsive-table { .responsive-table {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
table-layout: fixed;
} }
.responsive-table:is(.dark *) { .responsive-table:is(.dark *) {
@ -1448,6 +1521,71 @@ th label {
padding-left: 1em; padding-left: 1em;
} }
.truncate-container {
position: relative;
display: inline-block;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
a {
display: inline-block;
}
a {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
a {
max-width: 20ch;
}
a {
&:hover {
position: absolute;
}
&:hover {
top: -2rem;
}
&:hover {
left: -1.5rem;
}
&:hover {
min-width: 15rem;
}
&:hover {
max-width: none;
}
&:hover {
border-radius: 0.125rem;
}
&:hover {
--tw-bg-opacity: 1;
background-color: rgb(147 51 234 / var(--tw-bg-opacity));
}
&:hover {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
&:hover {
padding-top: 0.875rem;
padding-bottom: 0.875rem;
}
&:hover {
outline-style: dashed;
}
&:hover {
outline-width: 4px;
}
&:hover {
outline-color: #c084fc;
}
}
}
.hover\:bg-blue-800:hover {
--tw-bg-opacity: 1;
background-color: rgb(30 64 175 / var(--tw-bg-opacity));
}
.hover\:bg-gray-400:hover { .hover\:bg-gray-400:hover {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(156 163 175 / var(--tw-bg-opacity)); background-color: rgb(156 163 175 / var(--tw-bg-opacity));
@ -1478,6 +1616,17 @@ th label {
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
} }
.focus\:ring-4:focus {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.focus\:ring-blue-300:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity));
}
.focus\:ring-green-500:focus { .focus\:ring-green-500:focus {
--tw-ring-opacity: 1; --tw-ring-opacity: 1;
--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity)); --tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity));
@ -1504,6 +1653,11 @@ th label {
display: block; display: block;
} }
.dark\:bg-blue-600:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
}
.dark\:bg-gray-800:is(.dark *) { .dark\:bg-gray-800:is(.dark *) {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity)); background-color: rgb(31 41 55 / var(--tw-bg-opacity));
@ -1534,6 +1688,16 @@ th label {
color: rgb(255 255 255 / var(--tw-text-opacity)); color: rgb(255 255 255 / var(--tw-text-opacity));
} }
.dark\:hover\:bg-blue-700:hover:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
}
.dark\:focus\:ring-blue-800:focus:is(.dark *) {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(30 64 175 / var(--tw-ring-opacity));
}
@media (min-width: 640px) { @media (min-width: 640px) {
.sm\:inline { .sm\:inline {
display: inline; display: inline;
@ -1599,10 +1763,6 @@ th label {
padding-top: 0.5rem; padding-top: 0.5rem;
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
} }
.md\:max-w-40char {
max-width: 40ch;
}
} }
@media (min-width: 1024px) { @media (min-width: 1024px) {

View File

@ -0,0 +1,2 @@
components:
gamelink: "components/game_link.html"

View File

@ -0,0 +1,9 @@
<span class="truncate-container">
<a class="underline decoration-slate-500 sm:decoration-2" href="{% url 'view_game' game_id %}">
{% if children %}
{{ children }}
{% else %}
{{ name }}
{% endif %}
</a>
</span>

View File

@ -33,11 +33,8 @@
{% for session in dataset %} {% for session in dataset %}
{% partialdef session-row inline=True %} {% partialdef session-row inline=True %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 purchase-name truncate max-w-20char md:max-w-40char"> <td class="px-2 sm:px-4 md:px-6 md:py-2 purchase-name relative align-top w-24 h-12">
<a class="underline decoration-slate-500 sm:decoration-2" {% gamelink game_id=session.purchase.edition.game.id name=session.purchase.edition.name %}
href="{% url 'view_game' session.purchase.edition.game.id %}">
{{ session.purchase.edition.name }}
</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono hidden sm:table-cell"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono hidden sm:table-cell">
{{ session.timestamp_start | date:"d/m/Y H:i" }} {{ session.timestamp_start | date:"d/m/Y H:i" }}

View File

@ -6,9 +6,11 @@
{% partialdef purchase-name %} {% partialdef purchase-name %}
{% if purchase.type != 'game' %} {% if purchase.type != 'game' %}
{{ purchase.name }} ({{ purchase.edition.name }} {{ purchase.get_type_display }}) {% #gamelink game_id=purchase.edition.game.id %}
{{ purchase.name }} ({{ purchase.edition.name }} {{ purchase.get_type_display }})
{% /gamelink %}
{% else %} {% else %}
{{ purchase.edition.name }} {% gamelink game_id=purchase.edition.game.id name=purchase.edition.name %}
{% endif %} {% endif %}
{% endpartialdef %} {% endpartialdef %}
@ -60,25 +62,25 @@
</tr> </tr>
<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">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> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ longest_session_time }} ({% gamelink game_id=longest_session_game.id name=longest_session_game.name %})</td>
</tr> </tr>
<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">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> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ highest_session_count }} ({% gamelink game_id=highest_session_count_game.id name=highest_session_count_game.name %})</td>
</tr> </tr>
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Highest session average</td> <td class="px-2 sm:px-4 md:px-6 md:py-2">Highest session average</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
{{ highest_session_average }} ({{ highest_session_average_game }}) {{ highest_session_average }} ({% gamelink game_id=highest_session_average_game.id name=highest_session_average_game.name %})
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">First play</td> <td class="px-2 sm:px-4 md:px-6 md:py-2">First play</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ first_play_name }} ({{ first_play_date }})</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{% gamelink game_id=first_play_game.id name=first_play_game.name %} ({{ first_play_date }})</td>
</tr> </tr>
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Last play</td> <td class="px-2 sm:px-4 md:px-6 md:py-2">Last play</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ last_play_name }} ({{ last_play_date }})</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{% gamelink game_id=last_play_game.id name=last_play_game.name %} ({{ last_play_date }})</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -142,8 +144,7 @@
{% for game in top_10_games_by_playtime %} {% for game in top_10_games_by_playtime %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
<a class="underline decoration-slate-500 sm:decoration-2" {% gamelink game_id=game.id name=game.name %}
href="{% url 'view_game' game.id %}">{{ game.name }}</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ game.formatted_playtime }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ game.formatted_playtime }}</td>
</tr> </tr>
@ -179,10 +180,7 @@
{% for purchase in all_finished_this_year %} {% for purchase in all_finished_this_year %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
<a class="underline decoration-slate-500 sm:decoration-2" {% partial purchase-name %}
href="{% url 'edit_purchase' purchase.id %}">
{% partial purchase-name %}
</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
</tr> </tr>
@ -201,8 +199,7 @@
{% for purchase in this_year_finished_this_year %} {% for purchase in this_year_finished_this_year %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
<a class="underline decoration-slate-500 sm:decoration-2" {% partial purchase-name %}
href="{% url 'edit_purchase' purchase.id %}">{{ purchase.edition.name }}</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
</tr> </tr>
@ -221,8 +218,7 @@
{% for purchase in purchased_this_year_finished_this_year %} {% for purchase in purchased_this_year_finished_this_year %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
<a class="underline decoration-slate-500 sm:decoration-2" {% partial purchase-name %}
href="{% url 'edit_purchase' purchase.id %}">{{ purchase.edition.name }}</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
</tr> </tr>
@ -243,10 +239,7 @@
{% for purchase in purchased_unfinished %} {% for purchase in purchased_unfinished %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
<a class="underline decoration-slate-500 sm:decoration-2" {% partial purchase-name %}
href="{% url 'edit_purchase' purchase.id %}">
{% partial purchase-name %}
</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.price }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.price }}</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_purchased | date:"d/m/Y" }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_purchased | date:"d/m/Y" }}</td>
@ -268,10 +261,7 @@
{% for purchase in all_purchased_this_year %} {% for purchase in all_purchased_this_year %}
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
<a class="underline decoration-slate-500 sm:decoration-2" {% partial purchase-name %}
href="{% url 'edit_purchase' purchase.id %}">
{% partial purchase-name %}
</a>
</td> </td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.price }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.price }}</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_purchased | date:"d/m/Y" }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_purchased | date:"d/m/Y" }}</td>

View File

@ -504,10 +504,10 @@ def stats(request, year: int = 0):
last_play_date = "N/A" last_play_date = "N/A"
if this_year_sessions: if this_year_sessions:
first_session = this_year_sessions.earliest() first_session = this_year_sessions.earliest()
first_play_name = first_session.purchase.edition.name first_play_game = first_session.purchase.edition.game
first_play_date = first_session.timestamp_start.strftime("%x") first_play_date = first_session.timestamp_start.strftime("%x")
last_session = this_year_sessions.latest() last_session = this_year_sessions.latest()
last_play_name = last_session.purchase.edition.name last_play_game = last_session.purchase.edition.game
last_play_date = last_session.timestamp_start.strftime("%x") last_play_date = last_session.timestamp_start.strftime("%x")
all_purchased_this_year_count = this_year_purchases_with_currency.count() all_purchased_this_year_count = this_year_purchases_with_currency.count()
@ -578,7 +578,7 @@ def stats(request, year: int = 0):
else 0 else 0
), ),
"longest_session_game": ( "longest_session_game": (
longest_session.purchase.edition.name if longest_session else "N/A" longest_session.purchase.edition.game if longest_session else None
), ),
"highest_session_count": ( "highest_session_count": (
game_highest_session_count.session_count game_highest_session_count.session_count
@ -586,7 +586,7 @@ def stats(request, year: int = 0):
else 0 else 0
), ),
"highest_session_count_game": ( "highest_session_count_game": (
game_highest_session_count.name if game_highest_session_count else "N/A" game_highest_session_count if game_highest_session_count else None
), ),
"highest_session_average": ( "highest_session_average": (
format_duration( format_duration(
@ -596,9 +596,9 @@ def stats(request, year: int = 0):
else 0 else 0
), ),
"highest_session_average_game": highest_session_average_game, "highest_session_average_game": highest_session_average_game,
"first_play_name": first_play_name, "first_play_game": first_play_game,
"first_play_date": first_play_date, "first_play_date": first_play_date,
"last_play_name": last_play_name, "last_play_game": last_play_game,
"last_play_date": last_play_date, "last_play_date": last_play_date,
"title": f"{year} Stats", "title": f"{year} Stats",
"month_playtimes": month_playtimes, "month_playtimes": month_playtimes,

34
poetry.lock generated
View File

@ -829,6 +829,23 @@ files = [
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
] ]
[[package]]
name = "slippers"
version = "0.6.2"
description = "Build reusable components in Django without writing a single line of Python."
optional = false
python-versions = ">=3.8.0"
files = [
{file = "slippers-0.6.2-py3-none-any.whl", hash = "sha256:739e05f85354becbf0a65daab831eea62557d89e7512042209ab629af4378bca"},
{file = "slippers-0.6.2.tar.gz", hash = "sha256:4cb555b8822ba0d404e5405723f5d723994022c29046008ee917081031bc0cf1"},
]
[package.dependencies]
Django = ">=3.2"
PyYAML = ">=5.4.0"
typeguard = ">=2.13.3,<3.0.0"
typing-extensions = ">=4.4.0"
[[package]] [[package]]
name = "sqlparse" name = "sqlparse"
version = "0.5.0" version = "0.5.0"
@ -875,6 +892,21 @@ notebook = ["ipywidgets (>=6)"]
slack = ["slack-sdk"] slack = ["slack-sdk"]
telegram = ["requests"] telegram = ["requests"]
[[package]]
name = "typeguard"
version = "2.13.3"
description = "Run-time type checker for Python"
optional = false
python-versions = ">=3.5.3"
files = [
{file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"},
{file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"},
]
[package.extras]
doc = ["sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
test = ["mypy", "pytest", "typing-extensions"]
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.12.2" version = "4.12.2"
@ -938,4 +970,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = "^3.11"
content-hash = "f82f589e57bb158d66df005669003bd51084d5eac795ca66201d8b991d1a8b61" content-hash = "ca9188453f62ec4470e2b2f8bc1e4a17ad421272f401328f82d6fede231dc737"

View File

@ -31,6 +31,7 @@ django-template-partials = "^24.2"
markdown = "^3.6" markdown = "^3.6"
slippers = "^0.6.2"
[tool.isort] [tool.isort]
profile = "black" profile = "black"

View File

@ -41,6 +41,7 @@ INSTALLED_APPS = [
"template_partials", "template_partials",
"graphene_django", "graphene_django",
"django_htmx", "django_htmx",
"slippers",
] ]
GRAPHENE = {"SCHEMA": "games.schema.schema"} GRAPHENE = {"SCHEMA": "games.schema.schema"}
@ -85,7 +86,10 @@ TEMPLATES = [
"games.views.model_counts", "games.views.model_counts",
"games.views.stats_dropdown_year_range", "games.views.stats_dropdown_year_range",
], ],
"builtins": ["template_partials.templatetags.partials"], "builtins": [
"template_partials.templatetags.partials",
"slippers.templatetags.slippers",
],
}, },
}, },
] ]