Refactoring: views now use api for ajax

This commit is contained in:
Stepan Zhukovsky 2023-08-13 16:31:40 +09:00
parent e05319ec3c
commit 2e648ac4fe
8 changed files with 46 additions and 127 deletions

View File

@ -12,7 +12,7 @@ $(function () {
const archiveListElement = $(this).attr("data-jq-archive-target"); const archiveListElement = $(this).attr("data-jq-archive-target");
const delUrl = $(this).attr("href"); const delUrl = $(this).attr("href");
$.ajax({ $.ajax({
type: "delete", type: "DELETE",
url: delUrl, url: delUrl,
headers: { headers: {
"X-CSRFToken":CSRF, "X-CSRFToken":CSRF,
@ -21,12 +21,12 @@ $(function () {
// beforeSend: function(xhr) { // beforeSend: function(xhr) {
// xhr.setRequestHeader("X-CSRFToken", csrf); // xhr.setRequestHeader("X-CSRFToken", csrf);
// }, // },
success: function (response) { success: function (data, textStatus, jqXHR) {
console.log(response.status); console.log(jqXHR.status);
$(archiveListElement).hide(1500); $(archiveListElement).hide(1500);
}, },
error: function (response) { error: function (data, textStatus, jqXHR) {
console.log(response.status); console.log(jqXHR.status);
} }
}); });
}); });
@ -37,16 +37,13 @@ $(function () {
let resolved = false; let resolved = false;
let ticketStateUrl = $(this).attr("ticket-state-url") let ticketStateUrl = $(this).attr("ticket-state-url")
if ($(this).attr("ticket-state-switch") === "1") { if ($(this).attr("ticket-state-switch") === "1") {
console.log('Find it!!!')
resolved = true;
$(this).attr("ticket-state-switch", "0"); // disable $(this).attr("ticket-state-switch", "0"); // disable
} else { } else {
resolved = false; resolved = true;
$(this).attr("ticket-state-switch", "1"); // enable $(this).attr("ticket-state-switch", "1"); // enable
} }
console.log(resolved)
$.ajax({ $.ajax({
type: "POST", type: "PATCH",
url: ticketStateUrl, url: ticketStateUrl,
headers: { headers: {
"X-CSRFToken":CSRF, "X-CSRFToken":CSRF,
@ -57,11 +54,12 @@ $(function () {
data: JSON.stringify({ data: JSON.stringify({
resolved: resolved, resolved: resolved,
}), }),
success: function (response) { success: function (data, textStatus, jqXHR) {
console.log(response.resolved) console.log(jqXHR.status)
}, },
error: function (response) { error: function (data, textStatus, jqXHR) {
console.log(response.resolved) console.log(data)
console.log(jqXHR.status)
} }
}); });
}); });
@ -80,16 +78,16 @@ $(function () {
'X-CSRFToken':CSRF, 'X-CSRFToken':CSRF,
'Content-Type':'application/json' 'Content-Type':'application/json'
}, },
success: function (response) { success: function (data, textStatus, jqXHR) {
console.log(response.status); console.log(jqXHR.status);
if (delDiv.length) { if (delDiv.length) {
delDiv.hide(1500); delDiv.hide(1500);
} else { } else {
window.location.href = redirectUrl; window.location.href = redirectUrl;
} }
}, },
error: function (response) { error: function (data, textStatus, jqXHR) {
console.log(response.status); console.log(jqXHR.status);
} }
}); });
}); });

View File

@ -30,7 +30,7 @@
>Cancel >Cancel
</button> </button>
<a <a
href="{% url 'collector:download' archive.file %}" href="{% url 'collector:archive-detail' archive.id %}"
type="button" type="button"
class="btn btn-danger btn-archive-eraser" class="btn btn-danger btn-archive-eraser"
data-bs-dismiss="modal" data-bs-dismiss="modal"

View File

@ -27,7 +27,7 @@
</button> </button>
<a <a
type="button" type="button"
href="{% url 'collector:ajax_delete_ticket' ticket.number %}" href="{% url 'collector:ticket-detail' ticket.number %}"
class="btn btn-danger btn-ticket-del" class="btn btn-danger btn-ticket-del"
data-bs-dismiss="modal" data-bs-dismiss="modal"
data-jq-ticket-del-target="#div-ticket-{{ ticket.number }}" data-jq-ticket-del-target="#div-ticket-{{ ticket.number }}"

View File

@ -105,9 +105,13 @@
{% if request.user.is_staff %} {% if request.user.is_staff %}
<li> <li>
<a class="dropdown-item" type="button" href="{% url 'admin:index' %}" <a class="dropdown-item" type="button" href="{% url 'admin:index' %}"
><i class="bi bi-shield-shaded"></i></i> Admin</a> ><i class="bi bi-shield-shaded"></i> Admin</a>
</li> </li>
{% endif %} {% endif %}
<li>
<a class="dropdown-item" type="button" href="{% url 'swagger-ui' %}"
><i class="bi bi-braces-asterisk"></i> Swagger</a>
</li>
<li><button class="dropdown-item" type="button"><i class="bi bi-gear"></i> Settings</button></li> <li><button class="dropdown-item" type="button"><i class="bi bi-gear"></i> Settings</button></li>
<li><hr class="dropdown-divider" /></li> <li><hr class="dropdown-divider" /></li>
<li><button class="dropdown-item" type="button"><i class="bi bi-door-closed"></i> Logout</button></li> <li><button class="dropdown-item" type="button"><i class="bi bi-door-closed"></i> Logout</button></li>

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.name ticket.number %}" ticket-state-url="{% url 'collector:ticket-detail' 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

@ -6,17 +6,11 @@ from . import views
app_name = 'collector' app_name = 'collector'
router = routers.DefaultRouter()
router.register(r'archives', views.ArchiveViewSet)
router.register(r'platforms', views.PlatformViewSet)
router.register(r'tickets', views.TicketViewSet)
urlpatterns = [
# █░█░█ █▀▀ █▄▄ # █░█░█ █▀▀ █▄▄
# ▀▄▀▄▀ ██▄ █▄█ # ▀▄▀▄▀ ██▄ █▄█
# -- -- -- -- -- # -- -- -- -- --
urlpatterns = [
# CREATE: # CREATE:
path( path(
'tickets/create/', 'tickets/create/',
@ -55,28 +49,18 @@ urlpatterns = [
views.UpdateTicket.as_view(), views.UpdateTicket.as_view(),
name='update' name='update'
), ),
]
# ▄▀█ ░░█ ▄▀█ ▀▄▀
# █▀█ █▄█ █▀█ █░█
# -- -- -- -- --
# UPDATE:
path(
'ajax/tickets/update/<slug:platform>/<int:ticket>/',
views.UpdateTicketStateHandler.as_view(),
name='ajax_update_state_ticket'
),
# DELETE:
path(
'ajax/tickets/delete/<int:ticket>/',
views.DeleteTicketHandler.as_view(),
name='ajax_delete_ticket'
),
# ▄▀█ █▀█ █ # ▄▀█ █▀█ █
# █▀█ █▀▀ █ # █▀█ █▀▀ █
# -- -- -- # -- -- --
router = routers.DefaultRouter()
router.register(r'archives', views.ArchiveViewSet)
router.register(r'platforms', views.PlatformViewSet)
router.register(r'tickets', views.TicketViewSet)
urlpatterns += [
# CRUD: # CRUD:
path('api/v1/', include(router.urls)), path('api/v1/', include(router.urls)),
] ]

View File

@ -1,10 +1,8 @@
import json
from django.core.exceptions import ValidationError, ObjectDoesNotExist from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import FileResponse, JsonResponse from django.http import FileResponse
from django.views import generic from django.views import generic
from django.views.generic.detail import SingleObjectMixin from django.views.generic.detail import SingleObjectMixin
from django.urls import reverse_lazy
from django.db.models import Q from django.db.models import Q
from rest_framework import status from rest_framework import status
@ -20,7 +18,7 @@ from django_filters.rest_framework import DjangoFilterBackend
from .models import Archive, Ticket, Platform from .models import Archive, Ticket, Platform
from .forms import TicketForm from .forms import TicketForm
from .filters import ArchiveFilter, TicketFilter from .filters import ArchiveFilter, TicketFilter
from .utils import PageTitleViewMixin, is_ajax from .utils import PageTitleViewMixin
from .permissions import IsGuestUpload from .permissions import IsGuestUpload
from .serializers import ( from .serializers import (
@ -40,12 +38,6 @@ class ArchiveHandlerView(LoginRequiredMixin, SingleObjectMixin, generic.View):
self.object = self.get_object() self.object = self.get_object()
return FileResponse(self.object.file) return FileResponse(self.object.file)
def delete(self, request, path):
if is_ajax(request):
self.object = self.get_object()
self.object.delete()
return JsonResponse({'file': path}, status=status.HTTP_200_OK)
class CreateTicket(LoginRequiredMixin, PageTitleViewMixin, generic.CreateView): class CreateTicket(LoginRequiredMixin, PageTitleViewMixin, generic.CreateView):
model = Ticket model = Ticket
@ -71,7 +63,6 @@ class UpdateTicket(LoginRequiredMixin, PageTitleViewMixin, generic.UpdateView):
return f'{self.title} - {self.kwargs.get("ticket", "update")}' return f'{self.title} - {self.kwargs.get("ticket", "update")}'
def form_valid(self, form): def form_valid(self, form):
print(self.request.user)
form.instance.user = self.request.user form.instance.user = self.request.user
return super().form_valid(form) return super().form_valid(form)
@ -95,13 +86,17 @@ class ListAllTickets(PageTitleViewMixin, generic.ListView):
queryset = self.model.objects.filter( queryset = self.model.objects.filter(
Q(number__in=query_list) | Q(number__icontains=query_list[0]) Q(number__in=query_list) | Q(number__icontains=query_list[0])
) )
self.paginate_by = 100 # fake disable pagination) self.paginate_by = 100 # ? fake disable pagination)
return queryset return queryset
return super().get_queryset() return super().get_queryset()
class ListPlatformTickets(PageTitleViewMixin, generic.ListView): class ListPlatformTickets(
LoginRequiredMixin,
PageTitleViewMixin,
generic.ListView
):
model = Ticket model = Ticket
template_name = 'collector/tickets.html' template_name = 'collector/tickets.html'
context_object_name = 'tickets' context_object_name = 'tickets'
@ -117,7 +112,7 @@ class ListPlatformTickets(PageTitleViewMixin, generic.ListView):
) )
class DetailTicket(PageTitleViewMixin, generic.DetailView): class DetailTicket(LoginRequiredMixin, PageTitleViewMixin, generic.DetailView):
model = Ticket model = Ticket
template_name = 'collector/ticket.html' template_name = 'collector/ticket.html'
context_object_name = 'ticket' context_object_name = 'ticket'
@ -128,62 +123,6 @@ class DetailTicket(PageTitleViewMixin, generic.DetailView):
return f'{self.title} - {self.kwargs.get("ticket", "show")}' return f'{self.title} - {self.kwargs.get("ticket", "show")}'
class DeleteTicket(PageTitleViewMixin, generic.DeleteView):
model = Ticket
template_name = 'collector/ticket_delete.html'
context_object_name = 'ticket'
slug_field = 'number'
slug_url_kwarg = 'ticket'
success_url = reverse_lazy('tickets')
class UpdateTicketStateHandler(SingleObjectMixin, generic.View):
model = Ticket
slug_field = 'number'
slug_url_kwarg = 'ticket'
def post(self, request, **kwargs):
if is_ajax(request):
self.object = self.get_object()
if request.body:
data = json.loads(request.body)
resolved_field = data.get('resolved')
if isinstance(resolved_field, bool):
self.object.resolved = not resolved_field
self.object.save()
return JsonResponse(
{'resolved': not resolved_field},
status=status.HTTP_201_CREATED
)
return JsonResponse(
{'resolved': 'must be a boolean'},
status=status.HTTP_400_BAD_REQUEST
)
return JsonResponse(
{'error': 'header XMLHttpRequest is required'},
status=status.HTTP_406_NOT_ACCEPTABLE
)
class DeleteTicketHandler(SingleObjectMixin, generic.View):
model = Ticket
slug_field = 'number'
slug_url_kwarg = 'ticket'
def delete(self, request, ticket):
if is_ajax(request):
self.object = self.get_object()
self.object.delete()
return JsonResponse(
{'status': status.HTTP_200_OK},
status=status.HTTP_200_OK
)
return JsonResponse(
{'error': 'header XMLHttpRequest is required'},
status=status.HTTP_406_NOT_ACCEPTABLE
)
class ArchiveViewSet(viewsets.ModelViewSet): class ArchiveViewSet(viewsets.ModelViewSet):
queryset = Archive.objects.order_by('-time_create') queryset = Archive.objects.order_by('-time_create')
serializer_class = ArchiveSerializer serializer_class = ArchiveSerializer
@ -210,7 +149,7 @@ class ArchiveViewSet(viewsets.ModelViewSet):
) )
bound_ticket.attempts -= 1 bound_ticket.attempts -= 1
bound_ticket.save() bound_ticket.save()
# ? mixin bound ticket to request.data from user # ? mixin bound ticket number to request.data from user
request.data['ticket'] = bound_ticket.number request.data['ticket'] = bound_ticket.number
# ? change serializer for guest user # ? change serializer for guest user
self.serializer_class = PublicArchiveUploadSerializer self.serializer_class = PublicArchiveUploadSerializer

View File

@ -173,12 +173,6 @@ SPECTACULAR_SETTINGS = {
'VERSION': '0.1.0', 'VERSION': '0.1.0',
'SERVE_INCLUDE_SCHEMA': True, 'SERVE_INCLUDE_SCHEMA': True,
'SERVE_PUBLIC': False, 'SERVE_PUBLIC': False,
'SERVERS': [
{
'url': 'http://localhost:8000/api/v1/',
'description': 'main api endpoint'
},
],
} }
# https://django-rest-framework-simplejwt.readthedocs.io/en/latest/ # https://django-rest-framework-simplejwt.readthedocs.io/en/latest/