functional filter + add modal

This commit is contained in:
Corban-Lee Jones 2024-01-10 23:15:43 +00:00
parent 4c7a81e076
commit 690bec9b24
3 changed files with 113 additions and 14 deletions

View File

@ -101,14 +101,23 @@ class Ticket(models.Model):
def clean_description(self):
cleaned_description = bleach.clean(
self.description,
tags=['b', 'i', 'u', 'p', 'br', 'a', 'h3', 'h4', 'h5', 'h6'],
tags=[
'b', 'i', 'u', 'p', 'br', 'a', 'h3', 'h4', 'h5', 'h6', 'strong',
'figure', 'table', 'tbody', 'tr', 'td'
],
attributes={'a': ['href', 'title']}
)
return cleaned_description
def save(self, *args, **kwargs):
self.description = self.clean_description()
# self.edit_timestamp = timezone.now() ## TEMP COMMENT, UNCOMMENT LATER !!
# we must use the same datetime object, otherwise they wont match
now = timezone.now()
if self._state.adding: self.create_timestamp = now
self.edit_timestamp = now
super().save(*args, **kwargs)
@property

View File

@ -10,6 +10,7 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.template import loader
from django.shortcuts import render
from django.urls import reverse
from django.contrib.auth import get_user_model
from ..authentication.models import Department
from .models import Ticket, TicketPriority, TicketTag
@ -57,6 +58,7 @@ def get_tickets(request):
print(key, values)
for value in values:
if value == "all": continue # don't apply a filter if we want all
queryset = queryset.filter(**{key: [value]})
tickets = queryset.order_by("-create_timestamp")
@ -65,6 +67,7 @@ def get_tickets(request):
return JsonResponse(data)
@login_required
@require_POST
def get_filter_counts(request):
@ -96,7 +99,34 @@ def get_filter_counts(request):
@login_required()
@require_POST
def new_ticket(request):
return JsonResponse({"placeholder": "nothing here yet"})
print(request.POST)
get = lambda key: request.POST.get(key)
getlist = lambda key: request.POST.getlist(key)
title = get("title")
description = get("description")
author_id = get("author_id")
priority_id = get("priority_id")
tag_ids = getlist("tag_ids[]")
User = get_user_model()
author = User.objects.get(id=author_id)
priority = TicketPriority.objects.get(id=priority_id)
tags = [
tag for tag in TicketTag.objects.filter(id__in=tag_ids)
]
ticket = Ticket.objects.create(
title=title,
description=description,
author=author,
priority=priority,
)
ticket.tags.set(tags)
return JsonResponse({"success": "ticket created successfully"})
@login_required()

View File

@ -75,7 +75,7 @@
<label for="filterTag-{{ tag.id }}" class="nav-link c-grey-800 cH-blue-500 actived">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<input type="checkbox" id="filterTag-{{ tag.id }}" class="form-check-input me-2" value="{{ priority.id }}">
<input type="checkbox" id="filterTag-{{ tag.id }}" class="form-check-input me-2" value="{{ tag.id }}">
<span>{{ tag.title }}</span>
</div>
<div class="peer">
@ -350,6 +350,20 @@
<script>
var displayedTicketID = -1;
filters = {};
editor = null;
const formControls = [
{
id: "newTitle",
validation: function(element) {
const value = element.val();
return (!element.attr("required") || value.trim() !== "")
},
errorMessage: function(element) {
return "This field is required."
}
}
];
$(document).ready(function() {
// $(".email-list-item").on("click", function() {
@ -358,6 +372,9 @@
ClassicEditor
.create( document.getElementById("newDesc"), {})
.then( newEditor => {
editor = newEditor;
})
.catch( error => {
console.error(error)
});
@ -377,8 +394,8 @@
function setupFilter(selector, key) {
$(selector).each(function () {
var uuid = $(this).val();
var input = $(this).find("input[type=checkbox], input[type=radio]");
var uuid = input.val();
input.on("change", function () {
if (input.is(":checkbox")) {
@ -392,26 +409,64 @@
delete filters[key];
}
}
} else if (input.is(":radio") && input.is(":checked")) {
}
else if (input.is(":radio") && input.is(":checked")) {
filters[key] = [uuid];
}
loadAllTickets();
console.log(JSON.stringify(filters, null, 4));
loadAllTickets();
});
});
}
function validateForm() {
$("#ticketModal form").find(".form-control,.form-select").removeClass("is-valid is-invalid");
$("#ticketModal form .invalid-feedback").text("");
var valid = true;
formControls.forEach(function(control) {
var element = $("#" + control.id);
if (!control.validation(element)) {
element.addClass("is-invalid");
element.siblings(".invalid-feedback").text(control.errorMessage(element));
valid = false;
}
else {
element.addClass("is-valid");
}
});
return valid;
}
$("#ticketModal form").on("submit", function(event) {
event.preventDefault();
if (!validateForm()) {
return;
}
$.ajax({
url: "{% url 'ticket-new' %}",
type: "POST",
dataType: "json",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
title: $("#newTitle").val(),
description: editor.getData(),
author_id: "{{ request.user.id }}",
priority_id: $("#newPriority").val(),
tag_ids: $("#newTags").val()
},
success: function(data) {
loadAllTickets();
loadFilterCounts();
},
error: function(data) {
alert(JSON.stringify(data, null, 4))
}
});
});
@ -431,7 +486,7 @@
function updateFilterCounts(filterType, data) {
$("#filterSidebar .filter-" + filterType).each(function() {
var uuid = $(this).data("uuid");
var uuid = $(this).find("input[type=checkbox],input[type=radio]").val();
var count = data[filterType + '_counts'][uuid];
$(this).find(".badge").text(count);
});
@ -443,7 +498,7 @@
type: "POST",
dataType: "json",
data: {
csrfmiddlewaretoken: "{{ csrf_token }}",
csrfmiddlewaretoken: "{{ csrf_token }}"
},
success: function(data) {
console.log(JSON.stringify(data, null, 4));
@ -544,6 +599,15 @@
// displayTicket(ticketElement);
// });
if (displayedTicketID === ticketID) {
// displayedTicketID = -1;
return;
}
ticket.siblings().removeClass("bgc-grey-100");
ticket.addClass("bgc-grey-100");
$("#ticketTitle").text("")
$("#ticketDesc").empty();
$("#ticketAuthor").text("");
@ -553,10 +617,6 @@
$("#btnGroupDrop2").hide();
$("#ticketBadges").empty().hide();
if (displayedTicketID === ticketID) {
displayedTicketID = -1;
return;
}
displayedTicketID = ticketID;