Compare commits

...

4 Commits

Author SHA1 Message Date
138b8f26ad Add: CreateTicket view and form 2023-08-05 20:18:20 +09:00
eb80d72153 Add: crispy-bootstrap5 2023-08-05 15:54:33 +09:00
f8218bdfd6 Add: django-crispy-forms 2023-08-05 15:45:21 +09:00
38f1cb14ae Add: prototype create ticket view 2023-08-05 15:43:48 +09:00
12 changed files with 149 additions and 25 deletions

View File

@ -0,0 +1,27 @@
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Div
from crispy_bootstrap5.bootstrap5 import FloatingField
from .models import Ticket
class CreateTicketForm(forms.ModelForm):
class Meta:
model = Ticket
fields = ['number', 'platform', 'note']
widgets = {
'platform': forms.RadioSelect()
}
def __init__(self, *args, **kwargs):
super(CreateTicketForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
# self.helper.attrs = {"novalidate": ''}
self.helper.layout = Layout(
Div(FloatingField('number'), 'platform', css_class='col-md-2'),
Div('note', css_class='col-md-6'),
Submit('submit', 'Create', css_class='btn btn-success'),
)

View File

@ -0,0 +1,27 @@
# Generated by Django 4.2 on 2023-08-05 11:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('collector', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='ticket',
options={'ordering': ['-time_create']},
),
migrations.AlterField(
model_name='archive',
name='size',
field=models.CharField(blank=True, editable=False, max_length=50),
),
migrations.AlterField(
model_name='ticket',
name='number',
field=models.IntegerField(db_index=True, unique=True),
),
]

View File

@ -60,11 +60,11 @@ class Platform(models.Model):
return reverse('collector:platform', kwargs={'platform': self.name}) return reverse('collector:platform', kwargs={'platform': self.name})
def __str__(self): def __str__(self):
return self.name return self.pretty_name
class Ticket(models.Model): class Ticket(models.Model):
number = models.IntegerField() number = models.IntegerField(unique=True, db_index=True)
resolved = models.BooleanField(default=False) resolved = models.BooleanField(default=False)
note = models.TextField(blank=True) note = models.TextField(blank=True)
time_create = models.DateTimeField(auto_now_add=True) time_create = models.DateTimeField(auto_now_add=True)

View File

@ -52,10 +52,18 @@
</li> </li>
{% endfor %} {% endfor %}
<li><hr class="dropdown-divider" /></li> <li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="{% url 'collector:tickets' %}"><i class="bi bi-funnel"></i> Reset filter</a></li> <li>
<a class="dropdown-item" href="{% url 'collector:tickets' %}">
<i class="bi bi-funnel"></i> Reset filter
</a>
</li>
</ul> </ul>
</li> </li>
<li class="nav-item"><a class="nav-link" aria-current="page" href="#"><i class="bi bi-pencil-square"></i> New</a></li> <li class="nav-item">
<a class="nav-link" aria-current="page" href="{% url 'collector:create' %}">
<i class="bi bi-pencil-square"></i> New
</a>
</li>
</ul> </ul>
<!-- Search --> <!-- Search -->
<ul class="navbar-nav flex-row flex-wrap me-md-auto"> <ul class="navbar-nav flex-row flex-wrap me-md-auto">

View File

@ -9,7 +9,7 @@
type="checkbox" type="checkbox"
role="switch" role="switch"
name="ticket-state" name="ticket-state"
ticket-state-url="{% url 'collector:ajax_update_state_ticket' ticket.platform ticket.number %}" ticket-state-url="{% url 'collector:ajax_update_state_ticket' ticket.platform.name ticket.number %}"
{% if ticket.resolved %} ticket-state-switch="1" {% endif %} {% if ticket.resolved %} ticket-state-switch="1" {% endif %}
{% if ticket.resolved %} checked {% endif %}> {% if ticket.resolved %} checked {% endif %}>
</div> </div>

View File

@ -0,0 +1,16 @@
{% extends 'collector/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}<title>Collector - create</title>{% endblock title %}
{% block main %}
<div class="container mt-3">
<div class="card">
<div class="card-header">
<h4>New ticket:</h4>
</div>
<div class="card-body">
{% crispy form %}
</div>
</div>
</div>
{% endblock main %}

View File

@ -4,7 +4,7 @@
{% include 'collector/includes/navbar.html' %} {% include 'collector/includes/navbar.html' %}
<div class="container mt-5"> <div class="container mt-5">
<div class="row"> <div class="row">
<form method="post" action="{% url 'delete' ticket.number %}"> <form method="post" action="{% url 'collector:delete' ticket.number %}">
{% csrf_token %} {% csrf_token %}
<button <button
type="button" type="button"
@ -12,7 +12,7 @@
data-bs-dismiss="modal" data-bs-dismiss="modal"
>Cancel</button> >Cancel</button>
<button <button
type="button" type="submit"
class="btn btn-danger btn-archive-eraser" class="btn btn-danger btn-archive-eraser"
data-bs-dismiss="modal" data-bs-dismiss="modal"
>Delete</button> >Delete</button>

View File

@ -9,6 +9,13 @@ urlpatterns = [
# ▀▄▀▄▀ ██▄ █▄█ # ▀▄▀▄▀ ██▄ █▄█
# -- -- -- -- -- # -- -- -- -- --
# CREATE:
path(
'tickets/create/',
views.CreateTicket.as_view(),
name='create'
),
# READ: # READ:
path( path(
'', '',

View File

@ -8,7 +8,8 @@ from django.urls import reverse_lazy
from rest_framework import status from rest_framework import status
# from rest_framework.response import Response # from rest_framework.response import Response
from .models import Archive, Ticket, Platform from .models import Archive, Ticket
from .forms import CreateTicketForm
from .utils import is_ajax from .utils import is_ajax
@ -28,17 +29,22 @@ class ArchiveHandlerView(LoginRequiredMixin, SingleObjectMixin, generic.View):
return JsonResponse({'file': path}, status=status.HTTP_200_OK) return JsonResponse({'file': path}, status=status.HTTP_200_OK)
class CreateTicket(LoginRequiredMixin, generic.CreateView):
model = Ticket
form_class = CreateTicketForm
template_name = 'collector/ticket_create.html'
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
class ListAllTickets(generic.ListView): class ListAllTickets(generic.ListView):
model = Ticket model = Ticket
template_name = 'collector/tickets.html' template_name = 'collector/tickets.html'
context_object_name = 'tickets' context_object_name = 'tickets'
paginate_by = 5 paginate_by = 5
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# context['platforms'] = Platform.objects.all()
# return context
class ListPlatformTickets(generic.ListView): class ListPlatformTickets(generic.ListView):
model = Ticket model = Ticket
@ -52,11 +58,6 @@ class ListPlatformTickets(generic.ListView):
platform__name=self.kwargs.get('platform') platform__name=self.kwargs.get('platform')
) )
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['platforms'] = Platform.objects.all()
return context
class DetailTicket(generic.DetailView): class DetailTicket(generic.DetailView):
model = Ticket model = Ticket
@ -65,15 +66,10 @@ class DetailTicket(generic.DetailView):
slug_field = 'number' slug_field = 'number'
slug_url_kwarg = 'ticket' slug_url_kwarg = 'ticket'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['platforms'] = Platform.objects.all()
return context
class DeleteTicket(generic.DeleteView): class DeleteTicket(generic.DeleteView):
model = Ticket model = Ticket
template_name = 'collector/delete_ticket.html' template_name = 'collector/ticket_delete.html'
context_object_name = 'ticket' context_object_name = 'ticket'
slug_field = 'number' slug_field = 'number'
slug_url_kwarg = 'ticket' slug_url_kwarg = 'ticket'

View File

@ -35,6 +35,8 @@ INSTALLED_APPS = [
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'collector.apps.CollectorConfig', # main app 'collector.apps.CollectorConfig', # main app
'rest_framework', 'rest_framework',
"crispy_forms",
"crispy_bootstrap5",
'django_cleanup.apps.CleanupConfig', # required bottom 'django_cleanup.apps.CleanupConfig', # required bottom
] ]
@ -126,3 +128,10 @@ MEDIA_URL = 'media/'
MEDIA_ROOT_FOR_SENSITIVE_FILES = BASE_DIR / 'archives' MEDIA_ROOT_FOR_SENSITIVE_FILES = BASE_DIR / 'archives'
MEDIA_URL_FOR_SENSITIVE_FILES = '/archives/' MEDIA_URL_FOR_SENSITIVE_FILES = '/archives/'
# django-crispy-forms and crispy-bootstrap5
# https://django-crispy-forms.readthedocs.io/en/latest/
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"

34
poetry.lock generated
View File

@ -17,6 +17,24 @@ typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
[package.extras] [package.extras]
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
[[package]]
name = "crispy-bootstrap5"
version = "0.7"
description = "Bootstrap5 template pack for django-crispy-forms"
optional = false
python-versions = ">=3.7"
files = [
{file = "crispy-bootstrap5-0.7.tar.gz", hash = "sha256:0745a67199619149b7feca87dab7a45664876ed50fb582b38fd2aeb3f8a8d869"},
{file = "crispy_bootstrap5-0.7-py3-none-any.whl", hash = "sha256:f3ff1ef5cb379fe80b1b02e245008f276444098a4bdb8d855bed84c623798a85"},
]
[package.dependencies]
django = ">=3.2"
django-crispy-forms = ">=1.13.0"
[package.extras]
test = ["pytest", "pytest-django"]
[[package]] [[package]]
name = "django" name = "django"
version = "4.2" version = "4.2"
@ -48,6 +66,20 @@ files = [
{file = "django_cleanup-8.0.0-py2.py3-none-any.whl", hash = "sha256:8cd8872d67fe1501b19a843d006cdb5673cfbb74ac3d6d8f2c60e8e7723a7f5b"}, {file = "django_cleanup-8.0.0-py2.py3-none-any.whl", hash = "sha256:8cd8872d67fe1501b19a843d006cdb5673cfbb74ac3d6d8f2c60e8e7723a7f5b"},
] ]
[[package]]
name = "django-crispy-forms"
version = "2.0"
description = "Best way to have Django DRY forms"
optional = false
python-versions = ">=3.7"
files = [
{file = "django-crispy-forms-2.0.tar.gz", hash = "sha256:90193b068bf948d9c68449bc8260afed1a8e2afe11ee0bac8c4ebfaeb175b322"},
{file = "django_crispy_forms-2.0-py3-none-any.whl", hash = "sha256:d1d4e585929058a9ab3b797666ea5b69320b9ba7937f9d146d32173246a6fd13"},
]
[package.dependencies]
django = ">=3.2"
[[package]] [[package]]
name = "django-environ" name = "django-environ"
version = "0.10.0" version = "0.10.0"
@ -221,4 +253,4 @@ files = [
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.10" python-versions = "^3.10"
content-hash = "82580779974f9b9a09d2b46c9d92491e870b66363e634d34252a31338da1aeff" content-hash = "23169e9f6f71a2b23a984051083562a0b5cc0eb95a224bcd6dbef2b3dffe7b7b"

View File

@ -13,6 +13,8 @@ djangorestframework = "^3.14.0"
djangorestframework-simplejwt = "^5.2.2" djangorestframework-simplejwt = "^5.2.2"
django-environ = "^0.10.0" django-environ = "^0.10.0"
django-cleanup = "^8.0.0" django-cleanup = "^8.0.0"
django-crispy-forms = "^2.0"
crispy-bootstrap5 = "^0.7"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
flake8 = "^6.0.0" flake8 = "^6.0.0"