Major redesign #73
|
@ -6,6 +6,7 @@
|
||||||
* Add stats for dropped purchases, monthly playtimes
|
* Add stats for dropped purchases, monthly playtimes
|
||||||
* Allow deleting purchases
|
* Allow deleting purchases
|
||||||
* Add all-time stats
|
* Add all-time stats
|
||||||
|
* Manage purchases
|
||||||
|
|
||||||
## Improved
|
## Improved
|
||||||
* mark refunded purchases red on game overview
|
* mark refunded purchases red on game overview
|
||||||
|
|
|
@ -120,14 +120,6 @@ textarea:disabled {
|
||||||
@apply mx-1;
|
@apply mx-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
|
||||||
@apply text-right;
|
|
||||||
}
|
|
||||||
|
|
||||||
th label {
|
|
||||||
@apply mr-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.basic-button-container {
|
.basic-button-container {
|
||||||
@apply flex space-x-2 justify-center;
|
@apply flex space-x-2 justify-center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.db.models.manager import BaseManager
|
||||||
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from games.models import Purchase
|
||||||
|
from games.views import dateformat
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def list_purchases(request: HttpRequest) -> HttpResponse:
|
||||||
|
context: dict[Any, Any] = {}
|
||||||
|
purchases: BaseManager[Purchase] = Purchase.objects.all()[0:10]
|
||||||
|
context = {
|
||||||
|
"title": "Manage purchases",
|
||||||
|
"data": {
|
||||||
|
"columns": [
|
||||||
|
"Name",
|
||||||
|
"Platform",
|
||||||
|
"Price",
|
||||||
|
"Currency",
|
||||||
|
"Infinite",
|
||||||
|
"Purchased",
|
||||||
|
"Refunded",
|
||||||
|
"Finished",
|
||||||
|
"Dropped",
|
||||||
|
"Created",
|
||||||
|
"Actions",
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
purchase.edition.name,
|
||||||
|
purchase.platform,
|
||||||
|
purchase.price,
|
||||||
|
purchase.price_currency,
|
||||||
|
purchase.infinite,
|
||||||
|
purchase.date_purchased.strftime(dateformat),
|
||||||
|
(
|
||||||
|
purchase.date_refunded.strftime(dateformat)
|
||||||
|
if purchase.date_refunded
|
||||||
|
else "-"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
purchase.date_finished.strftime(dateformat)
|
||||||
|
if purchase.date_finished
|
||||||
|
else "-"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
purchase.date_dropped.strftime(dateformat)
|
||||||
|
if purchase.date_dropped
|
||||||
|
else "-"
|
||||||
|
),
|
||||||
|
purchase.created_at.strftime(dateformat),
|
||||||
|
render_to_string(
|
||||||
|
"components/button_group_sm.html",
|
||||||
|
{
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"href": reverse(
|
||||||
|
"edit_purchase", args=[purchase.pk]
|
||||||
|
),
|
||||||
|
"text": "Edit",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": reverse(
|
||||||
|
"delete_purchase", args=[purchase.pk]
|
||||||
|
),
|
||||||
|
"text": "Delete",
|
||||||
|
"color": "red",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for purchase in purchases
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return render(request, "list_purchases.html", context)
|
|
@ -1659,6 +1659,10 @@ input:checked + .toggle-bg {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-x-auto {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.truncate {
|
.truncate {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -1717,6 +1721,10 @@ input:checked + .toggle-bg {
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border-b {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.border-blue-600 {
|
.border-blue-600 {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(28 100 242 / var(--tw-border-opacity));
|
border-color: rgb(28 100 242 / var(--tw-border-opacity));
|
||||||
|
@ -1762,6 +1770,11 @@ input:checked + .toggle-bg {
|
||||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-gray-50 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-gray-800 {
|
.bg-gray-800 {
|
||||||
--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));
|
||||||
|
@ -1822,6 +1835,11 @@ input:checked + .toggle-bg {
|
||||||
padding-right: 1.25rem;
|
padding-right: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.px-6 {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.py-1 {
|
.py-1 {
|
||||||
padding-top: 0.25rem;
|
padding-top: 0.25rem;
|
||||||
padding-bottom: 0.25rem;
|
padding-bottom: 0.25rem;
|
||||||
|
@ -1842,6 +1860,11 @@ input:checked + .toggle-bg {
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.py-4 {
|
||||||
|
padding-top: 1rem;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pb-16 {
|
.pb-16 {
|
||||||
padding-bottom: 4rem;
|
padding-bottom: 4rem;
|
||||||
}
|
}
|
||||||
|
@ -1866,6 +1889,10 @@ input:checked + .toggle-bg {
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
.text-center {
|
.text-center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -1943,6 +1970,10 @@ input:checked + .toggle-bg {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uppercase {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
.leading-6 {
|
.leading-6 {
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
}
|
}
|
||||||
|
@ -2256,13 +2287,13 @@ textarea:disabled:is(.dark *) {
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
/* th {
|
||||||
text-align: right;
|
@apply text-right;
|
||||||
}
|
} */
|
||||||
|
|
||||||
th label {
|
/* th label {
|
||||||
margin-right: 1rem;
|
@apply mr-4;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.basic-button-container {
|
.basic-button-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -2366,11 +2397,26 @@ th label {
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
.odd\:bg-white:nth-child(odd) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.even\:bg-gray-50:nth-child(even) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:border-gray-300:hover {
|
.hover\:border-gray-300:hover {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:border-green-600:hover {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(5 122 85 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-blue-800:hover {
|
.hover\:bg-blue-800:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(30 66 159 / var(--tw-bg-opacity));
|
background-color: rgb(30 66 159 / var(--tw-bg-opacity));
|
||||||
|
@ -2386,6 +2432,16 @@ th label {
|
||||||
background-color: rgb(156 163 175 / var(--tw-bg-opacity));
|
background-color: rgb(156 163 175 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-gray-50:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover\:bg-green-500:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(14 159 110 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-green-700:hover {
|
.hover\:bg-green-700:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(4 108 78 / var(--tw-bg-opacity));
|
background-color: rgb(4 108 78 / var(--tw-bg-opacity));
|
||||||
|
@ -2396,6 +2452,11 @@ th label {
|
||||||
background-color: rgb(253 232 232 / var(--tw-bg-opacity));
|
background-color: rgb(253 232 232 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-red-500:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(240 82 82 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-violet-700:hover {
|
.hover\:bg-violet-700:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(109 40 217 / var(--tw-bg-opacity));
|
background-color: rgb(109 40 217 / var(--tw-bg-opacity));
|
||||||
|
@ -2426,6 +2487,11 @@ th label {
|
||||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:text-white:hover {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:underline:hover {
|
.hover\:underline:hover {
|
||||||
text-decoration-line: underline;
|
text-decoration-line: underline;
|
||||||
}
|
}
|
||||||
|
@ -2476,6 +2542,11 @@ th label {
|
||||||
--tw-ring-color: rgb(14 159 110 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(14 159 110 / var(--tw-ring-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.focus\:ring-green-700:focus {
|
||||||
|
--tw-ring-opacity: 1;
|
||||||
|
--tw-ring-color: rgb(4 108 78 / var(--tw-ring-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.focus\:ring-violet-500:focus {
|
.focus\:ring-violet-500:focus {
|
||||||
--tw-ring-opacity: 1;
|
--tw-ring-opacity: 1;
|
||||||
--tw-ring-color: rgb(139 92 246 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(139 92 246 / var(--tw-ring-opacity));
|
||||||
|
@ -2654,6 +2725,26 @@ th label {
|
||||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.odd\:dark\:bg-gray-900:is(.dark *):nth-child(odd) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.even\:dark\:bg-gray-800:is(.dark *):nth-child(even) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:hover\:border-green-700:hover:is(.dark *) {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(4 108 78 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:hover\:border-red-700:hover:is(.dark *) {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(200 30 30 / var(--tw-border-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.dark\:hover\:bg-blue-700:hover:is(.dark *) {
|
.dark\:hover\:bg-blue-700:hover:is(.dark *) {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(26 86 219 / var(--tw-bg-opacity));
|
background-color: rgb(26 86 219 / var(--tw-bg-opacity));
|
||||||
|
@ -2674,6 +2765,11 @@ th label {
|
||||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark\:hover\:bg-green-600:hover:is(.dark *) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(5 122 85 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.dark\:hover\:bg-red-700:hover:is(.dark *) {
|
.dark\:hover\:bg-red-700:hover:is(.dark *) {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(200 30 30 / var(--tw-bg-opacity));
|
background-color: rgb(200 30 30 / var(--tw-bg-opacity));
|
||||||
|
@ -2704,6 +2800,11 @@ th label {
|
||||||
--tw-ring-color: rgb(63 131 248 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(63 131 248 / var(--tw-ring-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark\:focus\:ring-green-500:focus:is(.dark *) {
|
||||||
|
--tw-ring-opacity: 1;
|
||||||
|
--tw-ring-color: rgb(14 159 110 / var(--tw-ring-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
@media (min-width: 640px) {
|
||||||
.sm\:inline {
|
.sm\:inline {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
@ -2721,6 +2822,10 @@ th label {
|
||||||
max-width: 36rem;
|
max-width: 36rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sm\:rounded-lg {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sm\:px-4 {
|
.sm\:px-4 {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
|
@ -2793,3 +2898,45 @@ th label {
|
||||||
.rtl\:space-x-reverse:where([dir="rtl"], [dir="rtl"] *) > :not([hidden]) ~ :not([hidden]) {
|
.rtl\:space-x-reverse:where([dir="rtl"], [dir="rtl"] *) > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-x-reverse: 1;
|
--tw-space-x-reverse: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rtl\:text-right:where([dir="rtl"], [dir="rtl"] *) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&\:first-of-type_button\]\:rounded-s-lg:first-of-type button {
|
||||||
|
border-start-start-radius: 0.5rem;
|
||||||
|
border-end-start-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&\:last-of-type_button\]\:rounded-e-lg:last-of-type button {
|
||||||
|
border-start-end-radius: 0.5rem;
|
||||||
|
border-end-end-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&_td\:first-of-type\]\:whitespace-nowrap td:first-of-type {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&_td\:first-of-type\]\:px-6 td:first-of-type {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&_td\:first-of-type\]\:py-4 td:first-of-type {
|
||||||
|
padding-top: 1rem;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&_td\:first-of-type\]\:font-medium td:first-of-type {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&_td\:first-of-type\]\:text-gray-900 td:first-of-type {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[\&_td\:first-of-type\]\:dark\:text-white:is(.dark *) td:first-of-type {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
components:
|
components:
|
||||||
gamelink: "components/game_link.html"
|
gamelink: "components/game_link.html"
|
||||||
popover: "components/popover.html"
|
popover: "components/popover.html"
|
||||||
|
table: "components/table.html"
|
||||||
|
table_row: "components/table_row.html"
|
||||||
|
table_td: "components/table_td.html"
|
||||||
|
simple_table: "components/simple_table.html"
|
||||||
|
button_group_sm: "components/button_group_sm.html"
|
||||||
|
button_group_button_sm: "components/button_group_button_sm.html"
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{% var color=color|default:"gray" %}
|
||||||
|
<a href="{{ href }}"
|
||||||
|
class="[&:first-of-type_button]:rounded-s-lg [&:last-of-type_button]:rounded-e-lg">
|
||||||
|
{% if color == "gray" %}
|
||||||
|
<button type="button"
|
||||||
|
class="px-2 py-1 text-xs font-medium text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:hover:text-white dark:hover:bg-gray-700 dark:focus:ring-blue-500 dark:focus:text-white">
|
||||||
|
{{ text }}
|
||||||
|
</button>
|
||||||
|
{% elif color == "red" %}
|
||||||
|
<button type="button"
|
||||||
|
class="px-2 py-1 text-xs font-medium text-gray-900 bg-white border border-gray-200 hover:bg-red-500 hover:text-white focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:hover:text-white dark:hover:border-red-700 dark:hover:bg-red-700 dark:focus:ring-blue-500 dark:focus:text-white">
|
||||||
|
{{ text }}
|
||||||
|
</button>
|
||||||
|
{% elif color == "green" %}
|
||||||
|
<button type="button"
|
||||||
|
class="px-2 py-1 text-xs font-medium text-gray-900 bg-white border border-gray-200 hover:bg-green-500 hover:border-green-600 hover:text-white focus:z-10 focus:ring-2 focus:ring-green-700 focus:text-blue-700 dark:bg-gray-800 dark:border-gray-700 dark:text-white dark:hover:text-white dark:hover:border-green-700 dark:hover:bg-green-600 dark:focus:ring-green-500 dark:focus:text-white">
|
||||||
|
{{ text }}
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</a>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="inline-flex rounded-md shadow-sm" role="group">
|
||||||
|
{% for button in buttons %}
|
||||||
|
{% button_group_button_sm href=button.href text=button.text color=button.color %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="relative overflow-x-auto">
|
||||||
|
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||||
|
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
{% for column in columns %}<th scope="col" class="px-6 py-3">{{ column }}</th>{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for row in rows %}
|
||||||
|
{% table_row data=row %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
|
||||||
|
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
|
||||||
|
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
{% for column in columns %}<th scope="col" class="px-6 py-3">{{ column }}</th>{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ children }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
|
@ -0,0 +1,15 @@
|
||||||
|
{% fragment as default_content %}
|
||||||
|
{% for td in data %}
|
||||||
|
{% if forloop.first %}
|
||||||
|
<th scope="row"
|
||||||
|
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">{{ td }}</th>
|
||||||
|
{% else %}
|
||||||
|
{% #table_td %}
|
||||||
|
{{ td }}
|
||||||
|
{% /table_td %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfragment %}
|
||||||
|
<tr class="[&_td:first-of-type]:px-6 [&_td:first-of-type]:py-4 [&_td:first-of-type]:font-medium [&_td:first-of-type]:text-gray-900 [&_td:first-of-type]:whitespace-nowrap [&_td:first-of-type]:dark:text-white odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 border-b">
|
||||||
|
{{ children|default:default_content }}
|
||||||
|
</tr>
|
|
@ -0,0 +1 @@
|
||||||
|
<td class="px-6 py-4">{{ children }}</td>
|
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% block title %}
|
||||||
|
{{ title }}
|
||||||
|
{% endblock title %}
|
||||||
|
{% block content %}
|
||||||
|
{% simple_table columns=data.columns rows=data.rows %}
|
||||||
|
{% endblock content %}
|
|
@ -1,6 +1,6 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from games import views
|
from games import purchaseviews, views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
|
@ -25,6 +25,11 @@ urlpatterns = [
|
||||||
views.delete_purchase,
|
views.delete_purchase,
|
||||||
name="delete_purchase",
|
name="delete_purchase",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"purchase/list",
|
||||||
|
purchaseviews.list_purchases,
|
||||||
|
name="list_purchases",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"purchase/related-purchase-by-edition",
|
"purchase/related-purchase-by-edition",
|
||||||
views.related_purchase_by_edition,
|
views.related_purchase_by_edition,
|
||||||
|
|
|
@ -27,6 +27,9 @@ from .forms import (
|
||||||
)
|
)
|
||||||
from .models import Edition, Game, Platform, Purchase, Session
|
from .models import Edition, Game, Platform, Purchase, Session
|
||||||
|
|
||||||
|
dateformat: str = "%d/%m/%Y"
|
||||||
|
datetimeformat: str = "%d/%m/%Y %H:%M"
|
||||||
|
|
||||||
|
|
||||||
def model_counts(request):
|
def model_counts(request):
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in New Issue