Compare commits
2
Commits
de611a5a14
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ccd9edc03 | ||
|
|
4f648a1389 |
@@ -34,4 +34,8 @@
|
|||||||
Update the database to use Postgres.
|
Update the database to use Postgres.
|
||||||
** 0.3.9 <2023-07-24 Mon>
|
** 0.3.9 <2023-07-24 Mon>
|
||||||
Add the CI/CD configuration.
|
Add the CI/CD configuration.
|
||||||
|
** 0.3.10 <2023-07-24 Mon>
|
||||||
|
Add the Tasks model to manage tasks.
|
||||||
|
** 0.4.0 <2023-07-24 Mon>
|
||||||
|
Add the detailed item for a Task model.
|
||||||
|
|
||||||
|
|||||||
@@ -45,3 +45,8 @@ class Task(models.Model):
|
|||||||
self.status = self.circular_next_status()
|
self.status = self.circular_next_status()
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
class Tasks:
|
||||||
|
@staticmethod
|
||||||
|
def get_count_by_status(status: str):
|
||||||
|
return Task.objects.filter(status=status).count()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from tasks.models import Task, Tasks
|
from tasks.models import Task
|
||||||
|
|
||||||
class TaskTestCase(TestCase):
|
class TaskTestCase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
from tasks.models import Task, Tasks
|
||||||
|
|
||||||
|
class TasksTestCase(TestCase):
|
||||||
|
todo_count = 2
|
||||||
|
doing_count = 3
|
||||||
|
done_count = 4
|
||||||
|
cancel_count = 1
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
names = [f"Test Task {i}" for i in range(10)]
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
statuses = ["TODO"] * self.todo_count
|
||||||
|
statuses += ["DOING"] * self.doing_count
|
||||||
|
statuses += ["DONE"] * self.done_count
|
||||||
|
statuses += ["CANCELED"] * self.cancel_count
|
||||||
|
|
||||||
|
tasks = [
|
||||||
|
Task(name=name, description=description, status=status)
|
||||||
|
for name, status in zip(names, statuses)
|
||||||
|
]
|
||||||
|
|
||||||
|
Task.objects.bulk_create(tasks)
|
||||||
|
|
||||||
|
def test_done_count(self):
|
||||||
|
count = Tasks.get_count_by_status("DONE")
|
||||||
|
self.assertEqual(count, self.done_count)
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@ urlpatterns = [
|
|||||||
path('', views.index, name='index'),
|
path('', views.index, name='index'),
|
||||||
path('htmx/create-task-form/', views.create_task_form, name='create-task-form'),
|
path('htmx/create-task-form/', views.create_task_form, name='create-task-form'),
|
||||||
path('htmx/task-item/<id>/', views.task_item, name='task-item'),
|
path('htmx/task-item/<id>/', views.task_item, name='task-item'),
|
||||||
|
path('htmx/task-item/<id>/detailed/', views.task_detailed, name='task-detailed'),
|
||||||
path('htmx/task-item/<id>/update/', views.task_update, name='task-update'),
|
path('htmx/task-item/<id>/update/', views.task_update, name='task-update'),
|
||||||
path('htmx/task-item/<id>/set-circular-next-status/',
|
path('htmx/task-item/<id>/set-circular-next-status/',
|
||||||
views.task_set_circular_next_status,
|
views.task_set_circular_next_status,
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ def task_item(request, id):
|
|||||||
|
|
||||||
return render(request, "partials/task_item.html", context)
|
return render(request, "partials/task_item.html", context)
|
||||||
|
|
||||||
|
def task_detailed(request, id):
|
||||||
|
task = get_object_or_404(Task, id=id)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"task": task
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, "partials/task_detailed.html", context)
|
||||||
|
|
||||||
def task_update(request, id):
|
def task_update(request, id):
|
||||||
task = get_object_or_404(Task, id=id)
|
task = get_object_or_404(Task, id=id)
|
||||||
task_form = TaskForm(request.POST or None, instance=task)
|
task_form = TaskForm(request.POST or None, instance=task)
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<div hx-target="this" class="p-2 border rounded-lg inline-flex gap-2 my-2 bg-gray-200">
|
||||||
|
<div class="grid grid-cols-3 gap-2 justify-center w-full max-w-2xl mx-auto">
|
||||||
|
<div class="col-span-3">
|
||||||
|
<dl class="row flex flex-inline">
|
||||||
|
<dt class="col-sm-3 font-bold mr-2">Status:</dt>
|
||||||
|
{% if task.status == "TODO" %}
|
||||||
|
<dd class="font-semibold text-green-500"
|
||||||
|
{% elif task.status == "DOING" %}
|
||||||
|
<dd class="font-semibold text-yellow-500"
|
||||||
|
{% elif task.status == "DONE" or task.status == "CANCELED" %}
|
||||||
|
<dd class="font-semibold text-gray-500"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
{{ task.status }}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="row flex flex-inline flex-wrap">
|
||||||
|
<dt class="col-sm-3 font-bold mr-2">Name:</dt>
|
||||||
|
<dd class="col-sm-9 whitespace-pre-line">{{ task.name }}</dd>
|
||||||
|
</dl>
|
||||||
|
<dl class="flex flex-col flex-inline">
|
||||||
|
<dt class="col-sm-3 font-bold mr-2">Description:</dt>
|
||||||
|
<dd class="col-sm-9 whitespace-pre-line">{{ task.description }}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
hx-post="{% url 'tasks:task-item' task.id %}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
class="inline-block px-5 py-1.5 bg-green-600 text-white font-medium text-xs leading-tight
|
||||||
|
uppercase rounded shadow-md hover:bg-green-700 hover:shadow-lg focus:bg-green-700
|
||||||
|
focus:shadow-lg focus:outline-none focus:ring-0 active:bg-green-800 active:shadow-lg
|
||||||
|
transition duration-150 ease-in-out">
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
hx-post="{% url 'tasks:task-update' task.id %}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
class="inline-block px-5 py-1.5 bg-blue-600 text-white font-medium text-xs leading-tight
|
||||||
|
uppercase rounded shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700
|
||||||
|
focus:shadow-lg focus:outline-none focus:ring-0 active:bg-blue-800 active:shadow-lg
|
||||||
|
transition duration-150 ease-in-out">
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
hx-post="{% url 'tasks:task-delete' task.id %}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
class="inline-block px-5 py-1.5 bg-red-600 text-white font-medium text-xs leading-tight
|
||||||
|
uppercase rounded shadow-md hover:bg-red-700 hover:shadow-lg focus:bg-red-700
|
||||||
|
focus:shadow-lg focus:outline-none focus:ring-0 active:bg-red-800 active:shadow-lg
|
||||||
|
transition duration-150 ease-in-out">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -10,8 +10,14 @@
|
|||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
{{ task.status }}
|
{{ task.status }}
|
||||||
</p>
|
</p>
|
||||||
<p class="font-semibold">{{ task.name }}</p>
|
|
||||||
<p>{{ task.description | truncatewords:10 }}</p>
|
<p class="font-semibold"
|
||||||
|
hx-post="{% url 'tasks:task-detailed' task.id %}"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
{{ task.name }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>{{ task.description | truncatechars:40 }}</p>
|
||||||
|
|
||||||
<button type="button"
|
<button type="button"
|
||||||
hx-post="{% url 'tasks:task-update' task.id %}"
|
hx-post="{% url 'tasks:task-update' task.id %}"
|
||||||
|
|||||||
Reference in New Issue
Block a user