Compare commits
No commits in common. "55c2693f32bcbcf5c5e3ef91a213966aa596aeb3" and "2760068cde9c0d037015b90a206c026b50d043ba" have entirely different histories.
55c2693f32
...
2760068cde
|
@ -1,11 +1,7 @@
|
||||||
## 0.2.5 / 2023-01-18 17:01+01:00
|
## Unreleased
|
||||||
|
|
||||||
* New
|
* New
|
||||||
* When adding session, pre-select game with the last session
|
* When adding session, pre-select game with the last session
|
||||||
* Fixed
|
|
||||||
* Start session now button would take up 100% width, leading to accidental clicks (https://git.kucharczyk.xyz/lukas/timetracker/issues/37)
|
|
||||||
* Removed
|
|
||||||
* Session model property `last` is already implemented by Django method `last()`, thus it was removed (https://git.kucharczyk.xyz/lukas/timetracker/issues/38)
|
|
||||||
|
|
||||||
## 0.2.4 / 2023-01-16 19:39+01:00
|
## 0.2.4 / 2023-01-16 19:39+01:00
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ RUN npm install && \
|
||||||
|
|
||||||
FROM python:3.10.9-slim-bullseye
|
FROM python:3.10.9-slim-bullseye
|
||||||
|
|
||||||
ENV VERSION_NUMBER 0.2.5
|
ENV VERSION_NUMBER 0.2.4
|
||||||
ENV PROD 1
|
ENV PROD 1
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "timetracker"
|
name = "timetracker"
|
||||||
version = "0.2.5"
|
version = "0.2.4"
|
||||||
description = "A simple time tracker."
|
description = "A simple time tracker."
|
||||||
authors = ["Lukáš Kucharczyk <lukas@kucharczyk.xyz>"]
|
authors = ["Lukáš Kucharczyk <lukas@kucharczyk.xyz>"]
|
||||||
license = "GPL"
|
license = "GPL"
|
||||||
|
|
|
@ -79,6 +79,10 @@ class Session(models.Model):
|
||||||
def duration_sum(self) -> str:
|
def duration_sum(self) -> str:
|
||||||
return Session.objects.all().total_duration()
|
return Session.objects.all().total_duration()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last(self) -> Manager[Any]:
|
||||||
|
return Session.objects.all().order_by("timestamp_start")[0]
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.timestamp_start != None and self.timestamp_end != None:
|
if self.timestamp_start != None and self.timestamp_end != None:
|
||||||
self.duration_calculated = self.timestamp_end - self.timestamp_start
|
self.duration_calculated = self.timestamp_end - self.timestamp_start
|
||||||
|
|
|
@ -683,34 +683,66 @@ select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
@media (min-width: 640px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
max-width: 640px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 768px;
|
max-width: 768px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
max-width: 768px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 1024px;
|
max-width: 1024px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
max-width: 1024px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1280px) {
|
@media (min-width: 1280px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 1280px;
|
max-width: 1280px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
max-width: 1280px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1536px) {
|
@media (min-width: 1536px) {
|
||||||
.container {
|
.container {
|
||||||
max-width: 1536px;
|
max-width: 1536px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
max-width: 1536px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visible {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse {
|
||||||
|
visibility: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.static {
|
.static {
|
||||||
|
@ -721,6 +753,26 @@ select {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.\!fixed {
|
||||||
|
position: fixed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky {
|
||||||
|
position: sticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!sticky {
|
||||||
|
position: sticky !important;
|
||||||
|
}
|
||||||
|
|
||||||
.left-2 {
|
.left-2 {
|
||||||
left: 0.5rem;
|
left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -729,15 +781,16 @@ select {
|
||||||
bottom: 0.5rem;
|
bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-both {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx-auto {
|
.mx-auto {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my-5 {
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mb-4 {
|
.mb-4 {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
@ -750,18 +803,30 @@ select {
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-10 {
|
|
||||||
margin-top: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ml-1 {
|
.ml-1 {
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mt-5 {
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-10 {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inline-block {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.inline {
|
.inline {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
@ -770,6 +835,30 @@ select {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-caption {
|
||||||
|
display: table-caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell {
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.h-6 {
|
.h-6 {
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
}
|
}
|
||||||
|
@ -810,6 +899,10 @@ select {
|
||||||
max-width: 1024px;
|
max-width: 1024px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.resize {
|
||||||
|
resize: both;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-col {
|
.flex-col {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
@ -846,6 +939,12 @@ select {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.truncate {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.text-ellipsis {
|
.text-ellipsis {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
@ -866,6 +965,10 @@ select {
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.border-gray-200 {
|
.border-gray-200 {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
||||||
|
@ -959,6 +1062,14 @@ select {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uppercase {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lowercase {
|
||||||
|
text-transform: lowercase;
|
||||||
|
}
|
||||||
|
|
||||||
.text-white {
|
.text-white {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
|
@ -974,6 +1085,11 @@ select {
|
||||||
color: rgb(248 113 113 / var(--tw-text-opacity));
|
color: rgb(248 113 113 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-red-700 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(185 28 28 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.shadow-md {
|
.shadow-md {
|
||||||
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||||
|
@ -986,6 +1102,29 @@ select {
|
||||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blur {
|
||||||
|
--tw-blur: blur(8px);
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.invert {
|
||||||
|
--tw-invert: invert(100%);
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!invert {
|
||||||
|
--tw-invert: invert(100%) !important;
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter {
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!filter {
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.transition {
|
.transition {
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
{% if purchase %}<a class="dark:text-white hover:underline block" href="{% url 'list_sessions_by_game' purchase.game.id %}">See all platforms</a>{% endif %}
|
{% if purchase %}<a class="dark:text-white hover:underline block" href="{% url 'list_sessions_by_game' purchase.game.id %}">See all platforms</a>{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if dataset.count >= 1 %}
|
{% if dataset.count >= 1 %}
|
||||||
<a class="clear-both" href="{% url 'start_session' dataset.last.purchase.id %}">
|
<a class="block" href="{% url 'start_session' dataset.last.purchase.id %}">
|
||||||
<button type="button" title="Track last tracked" class="mt-10 py-1 px-2 bg-green-600 hover:bg-green-700 focus:ring-green-500 focus:ring-offset-blue-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg ">
|
<button type="button" title="Track last tracked" class="mt-10 py-1 px-2 bg-green-600 hover:bg-green-700 focus:ring-green-500 focus:ring-offset-blue-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 rounded-lg ">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="self-center w-6 h-6 inline">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="self-center w-6 h-6 inline">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z" />
|
||||||
|
|
|
@ -66,7 +66,6 @@ def list_sessions(request, filter="", purchase_id="", platform_id="", game_id=""
|
||||||
dataset = Session.objects.filter(purchase__game=game_id)
|
dataset = Session.objects.filter(purchase__game=game_id)
|
||||||
context["game"] = Game.objects.get(id=game_id)
|
context["game"] = Game.objects.get(id=game_id)
|
||||||
else:
|
else:
|
||||||
# by default, sort from newest to oldest
|
|
||||||
dataset = Session.objects.all().order_by("-timestamp_start")
|
dataset = Session.objects.all().order_by("-timestamp_start")
|
||||||
|
|
||||||
for session in dataset:
|
for session in dataset:
|
||||||
|
@ -76,8 +75,7 @@ def list_sessions(request, filter="", purchase_id="", platform_id="", game_id=""
|
||||||
|
|
||||||
context["total_duration"] = dataset.total_duration()
|
context["total_duration"] = dataset.total_duration()
|
||||||
context["dataset"] = dataset
|
context["dataset"] = dataset
|
||||||
# cannot use dataset[0] here because that might be only partial QuerySet
|
context["last"] = Session.objects.all().last()
|
||||||
context["last"] = Session.objects.all().order_by("timestamp_start").last()
|
|
||||||
# charts are always oldest->newest
|
# charts are always oldest->newest
|
||||||
context["chart"] = playtime_over_time_chart(dataset.order_by("timestamp_start"))
|
context["chart"] = playtime_over_time_chart(dataset.order_by("timestamp_start"))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue