Improve session list

This commit is contained in:
Lukáš Kucharczyk 2023-01-05 22:00:08 +01:00
parent e6b5804e37
commit 76bf03b482
Signed by: lukas
SSH Key Fingerprint: SHA256:vMuSwvwAvcT6htVAioMP7rzzwMQNi3roESyhv+nAxeg
4 changed files with 201 additions and 74 deletions

View File

@ -6,7 +6,7 @@ RUN npm install && \
FROM python:3.10-slim-bullseye
ENV VERSION_NUMBER 0.1.0-35-g2807c5e
ENV VERSION_NUMBER 0.1.0-36-ge6b5804
ENV PROD 1
RUN useradd --create-home --uid 1000 timetracker

View File

@ -3,13 +3,20 @@
@tailwind utilities;
form label {
@apply dark:text-slate-400;
@apply dark:text-slate-400;
}
form input,select,textarea {
@apply dark:bg-slate-500 dark:border dark:border-slate-900 dark:text-slate-100;
form input,
select,
textarea {
@apply dark:border dark:border-slate-900 dark:bg-slate-500 dark:text-slate-100;
}
form input[type=submit] {
@apply p-2 bg-purple-900;
}
#session-table {
display: grid;
grid-template-columns: repeat(3, 2fr) 0.5fr 1fr;
}
#button-container button {
@apply mx-1;
}

View File

@ -750,8 +750,12 @@ select {
display: flex;
}
.grid {
display: grid;
.h-4 {
height: 1rem;
}
.h-5 {
height: 1.25rem;
}
.min-h-screen {
@ -762,12 +766,20 @@ select {
width: 100%;
}
.max-w-screen-lg {
max-width: 1024px;
.w-7 {
width: 1.75rem;
}
.grid-cols-5 {
grid-template-columns: repeat(5, minmax(0, 1fr));
.w-4 {
width: 1rem;
}
.w-5 {
width: 1.25rem;
}
.max-w-screen-lg {
max-width: 1024px;
}
.flex-col {
@ -782,6 +794,10 @@ select {
align-items: center;
}
.justify-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
@ -810,8 +826,8 @@ select {
border-radius: 0.75rem;
}
.border {
border-width: 1px;
.rounded-lg {
border-radius: 0.5rem;
}
.border-gray-200 {
@ -819,19 +835,24 @@ select {
border-color: rgb(229 231 235 / var(--tw-border-opacity));
}
.border-red-900 {
--tw-border-opacity: 1;
border-color: rgb(127 29 29 / var(--tw-border-opacity));
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.bg-red-700 {
.bg-green-600 {
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
}
.bg-blue-600 {
--tw-bg-opacity: 1;
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
}
.bg-red-600 {
--tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
}
.p-4 {
@ -842,15 +863,21 @@ select {
padding: 0.5rem;
}
.p-1 {
padding: 0.25rem;
}
.py-2 {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
.py-1 {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.pl-3 {
padding-left: 0.75rem;
}
@ -863,6 +890,10 @@ select {
text-align: center;
}
.text-right {
text-align: right;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
@ -883,9 +914,9 @@ select {
line-height: 1.75rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
.text-base {
font-size: 1rem;
line-height: 1.5rem;
}
.font-semibold {
@ -902,18 +933,47 @@ select {
color: rgb(203 213 225 / var(--tw-text-opacity));
}
.text-red-400 {
--tw-text-opacity: 1;
color: rgb(248 113 113 / var(--tw-text-opacity));
}
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.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-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.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, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
.duration-200 {
transition-duration: 200ms;
}
.ease-in {
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
.dark form label {
--tw-text-opacity: 1;
color: rgb(148 163 184 / var(--tw-text-opacity));
}
.dark form input,.dark select,.dark textarea {
.dark form input,.dark
select,.dark
textarea {
border-width: 1px;
--tw-border-opacity: 1;
border-color: rgb(15 23 42 / var(--tw-border-opacity));
@ -923,30 +983,69 @@ select {
color: rgb(241 245 249 / var(--tw-text-opacity));
}
form input[type=submit] {
#session-table {
display: grid;
grid-template-columns: repeat(3, 2fr) 0.5fr 1fr;
}
#button-container button {
margin-left: 0.25rem;
margin-right: 0.25rem;
}
.hover\:bg-green-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(88 28 135 / var(--tw-bg-opacity));
padding: 0.5rem;
background-color: rgb(21 128 61 / var(--tw-bg-opacity));
}
.hover\:border-dotted:hover {
border-style: dotted;
}
.hover\:border-white:hover {
--tw-border-opacity: 1;
border-color: rgb(255 255 255 / var(--tw-border-opacity));
}
.hover\:bg-orange-700:hover {
.hover\:bg-blue-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(194 65 12 / var(--tw-bg-opacity));
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
}
.hover\:bg-red-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
}
.hover\:underline:hover {
text-decoration-line: underline;
}
.focus\:outline-none:focus {
outline: 2px solid transparent;
outline-offset: 2px;
}
.focus\:ring-2: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(2px + 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-green-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity));
}
.focus\:ring-blue-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
}
.focus\:ring-red-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity));
}
.focus\:ring-offset-2:focus {
--tw-ring-offset-width: 2px;
}
.focus\:ring-offset-blue-200:focus {
--tw-ring-offset-color: #bfdbfe;
}
.dark .dark\:border-white {
--tw-border-opacity: 1;
border-color: rgb(255 255 255 / var(--tw-border-opacity));
@ -999,4 +1098,4 @@ form input[type=submit] {
.md\:flex-row {
flex-direction: row;
}
}
}

View File

@ -3,34 +3,55 @@
{% block title %}Sessions{% endblock title %}
{% block content %}
{% if purchase %}
<div class="text-center text-xl mb-4 dark:text-slate-400">
<h1>Listing sessions only for purchase "{{ purchase }}"</h1>
<a class="dark:text-white hover:underline" href="{% url 'list_sessions' %}">View all sessions</a>
</div>
{% endif %}
<div class="grid grid-cols-5 gap-4 shadow rounded-xl max-w-screen-lg mx-auto dark:bg-slate-700 p-2 justify-center">
<div class="dark:border-white dark:text-slate-300 text-lg">Name</div>
<div class="dark:border-white dark:text-slate-300 text-lg">Start</div>
<div class="dark:border-white dark:text-slate-300 text-lg">End</div>
<div class="dark:border-white dark:text-slate-300 text-lg">Duration</div>
<div></div>
{% for data in dataset %}
<div class=""><a class="dark:text-white hover:underline" href="{% url 'list_sessions' data.purchase.id %}">{{ data.purchase }}</a></div>
<div class="dark:text-slate-400">{{ data.timestamp_start | date:"d/m/Y H:i" }}</div>
<div class="dark:text-slate-400">
{% if data.unfinished %}
Not finished yet. <a href="{% url 'update_session' data.id %}"><button class="bg-red-700 hover:bg-orange-700 border border-red-900 hover:border-dotted hover:border-white rounded p-1 text-white text-sm">Finish now?</button></a>
{% elif data.duration_manual %}
MANUAL
{% else %}
{{ data.timestamp_end | date:"d/m/Y H:i" }}
{% endif %}
{% if purchase %}
<div class="text-center text-xl mb-4 dark:text-slate-400">
<h1>Listing sessions only for purchase "{{ purchase }}"</h1>
<a class="dark:text-white hover:underline" href="{% url 'list_sessions' %}">View all sessions</a>
</div>
{% endif %}
<div id="session-table" class="gap-4 shadow rounded-xl max-w-screen-lg mx-auto dark:bg-slate-700 p-2 justify-center">
<div class="dark:border-white dark:text-slate-300 text-lg">Name</div>
<div class="dark:border-white dark:text-slate-300 text-lg text-center">Start</div>
<div class="dark:border-white dark:text-slate-300 text-lg text-center">End</div>
<div class="dark:border-white dark:text-slate-300 text-lg">Duration</div>
<div class="dark:border-white dark:text-slate-300 text-lg text-right">Manage</div>
{% for data in dataset %}
<div><a class="dark:text-white hover:underline" href="{% url 'list_sessions' data.purchase.id %}">{{ data.purchase }}</a></div>
<div class="dark:text-slate-400 text-center">{{ data.timestamp_start | date:"d/m/Y H:i" }}</div>
<div class="dark:text-slate-400 text-center">
{% if data.unfinished %}
<span class="text-red-400">Not finished yet.</span>
{% elif data.duration_manual %}
--
{% else %}
{{ data.timestamp_end | date:"d/m/Y H:i" }}
{% endif %}
</div>
<div class="dark:text-slate-400">{{ data.duration_formatted }}{% if data.duration_manual %} (M){% endif %}</div>
<div id="button-container" class="flex justify-end">
{% if data.unfinished %}
<a href="{% url 'update_session' data.id %}">
<button type="button" title="Set to finished" class="py-1 px-2 flex justify-center items-center 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 w-7 h-4 rounded-lg ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4">
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd" />
</svg>
</button>
</a>
{% endif %}
<button type="button" title="Edit" class="py-1 px-2 flex justify-center items-center bg-blue-600 hover:bg-blue-700 focus:ring-blue-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 w-7 h-4 rounded-lg ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<path d="M5.433 13.917l1.262-3.155A4 4 0 017.58 9.42l6.92-6.918a2.121 2.121 0 013 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 01-.65-.65z" />
<path d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0010 3H4.75A2.75 2.75 0 002 5.75v9.5A2.75 2.75 0 004.75 18h9.5A2.75 2.75 0 0017 15.25V10a.75.75 0 00-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5z" />
</svg>
</button>
<a href="{% url 'delete_session' data.id %}">
<button type="button" edit="Delete" class="py-1 px-2 flex justify-center items-center bg-red-600 hover:bg-red-700 focus:ring-red-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 w-7 h-4 rounded-lg ">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M8.75 1A2.75 2.75 0 006 3.75v.443c-.795.077-1.584.176-2.365.298a.75.75 0 10.23 1.482l.149-.022.841 10.518A2.75 2.75 0 007.596 19h4.807a2.75 2.75 0 002.742-2.53l.841-10.52.149.023a.75.75 0 00.23-1.482A41.03 41.03 0 0014 4.193V3.75A2.75 2.75 0 0011.25 1h-2.5zM10 4c.84 0 1.673.025 2.5.075V3.75c0-.69-.56-1.25-1.25-1.25h-2.5c-.69 0-1.25.56-1.25 1.25v.325C8.327 4.025 9.16 4 10 4zM8.58 7.72a.75.75 0 00-1.5.06l.3 7.5a.75.75 0 101.5-.06l-.3-7.5zm4.34.06a.75.75 0 10-1.5-.06l-.3 7.5a.75.75 0 101.5.06l.3-7.5z" clip-rule="evenodd" />
</svg>
</button>
</a>
</div>
{% endfor %}
</div>
<div class="dark:text-slate-400">{{ data.duration_formatted }}{% if data.duration_manual %} (M){% endif %}</div>
<div>
<a href="{% url 'delete_session' data.id %}"><button></button></a>
</div>
{% endfor %}
</div>
{% endblock content %}