Refactoring: views now use api for ajax
This commit is contained in:
		
							parent
							
								
									e05319ec3c
								
							
						
					
					
						commit
						2e648ac4fe
					
				| @ -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); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -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" | ||||||
|  | |||||||
| @ -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 }}" | ||||||
|  | |||||||
| @ -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>            | ||||||
|  | |||||||
| @ -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> | ||||||
|  | |||||||
| @ -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: | router = routers.DefaultRouter() | ||||||
|     path( | router.register(r'archives', views.ArchiveViewSet) | ||||||
|         'ajax/tickets/update/<slug:platform>/<int:ticket>/', | router.register(r'platforms', views.PlatformViewSet) | ||||||
|         views.UpdateTicketStateHandler.as_view(), | router.register(r'tickets', views.TicketViewSet) | ||||||
|         name='ajax_update_state_ticket' |  | ||||||
|     ), |  | ||||||
|     # DELETE: |  | ||||||
|     path( |  | ||||||
|         'ajax/tickets/delete/<int:ticket>/', |  | ||||||
|         views.DeleteTicketHandler.as_view(), |  | ||||||
|         name='ajax_delete_ticket' |  | ||||||
|     ), |  | ||||||
| 
 |  | ||||||
|     # ▄▀█ █▀█ █ |  | ||||||
|     # █▀█ █▀▀ █ |  | ||||||
|     # -- -- -- |  | ||||||
| 
 | 
 | ||||||
|  | urlpatterns += [ | ||||||
|     # CRUD: |     # CRUD: | ||||||
|     path('api/v1/', include(router.urls)), |     path('api/v1/', include(router.urls)), | ||||||
| ] | ] | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -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/ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user