Compare commits
10 commits
bc3e491b92
...
4d439304f0
Author | SHA1 | Date | |
---|---|---|---|
Thomas Nahuel Rusiecki | 4d439304f0 | ||
Thomas Nahuel Rusiecki | 650184e483 | ||
Thomas Nahuel Rusiecki | d226b875d9 | ||
Thomas Nahuel Rusiecki | ec81f05372 | ||
Thomas Nahuel Rusiecki | 394f02c133 | ||
Thomas Nahuel Rusiecki | e43c3b71e1 | ||
Thomas Nahuel Rusiecki | ef938f6cab | ||
Thomas Nahuel Rusiecki | 83e9daff94 | ||
Thomas Nahuel Rusiecki | 3199862aa1 | ||
Thomas Nahuel Rusiecki | 7b7f83f8e9 |
|
@ -8,4 +8,5 @@ urlpatterns = [
|
||||||
path("new/", views.ChangeStateView.as_view(), name="change_state"),
|
path("new/", views.ChangeStateView.as_view(), name="change_state"),
|
||||||
path('note/add/', views.AddNoteView.as_view(), name='add_note'),
|
path('note/add/', views.AddNoteView.as_view(), name='add_note'),
|
||||||
path('note/edit/<int:pk>', views.UpdateNoteView.as_view(), name='update_note'),
|
path('note/edit/<int:pk>', views.UpdateNoteView.as_view(), name='update_note'),
|
||||||
|
path('note/delete/<int:pk>', views.DeleteNoteView.as_view(), name='delete_note'),
|
||||||
]
|
]
|
||||||
|
|
148
action/views.py
148
action/views.py
|
@ -9,70 +9,73 @@ from action.models import State, StateDefinition, Note, DeviceLog
|
||||||
from device.models import Device
|
from device.models import Device
|
||||||
|
|
||||||
|
|
||||||
class ChangeStateView(View):
|
class ChangeStateView(FormView):
|
||||||
|
form_class = ChangeStateForm
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def form_valid(self, form):
|
||||||
form = ChangeStateForm(request.POST)
|
previous_state = form.cleaned_data['previous_state']
|
||||||
|
new_state = form.cleaned_data['new_state']
|
||||||
if form.is_valid():
|
snapshot_uuid = form.cleaned_data['snapshot_uuid']
|
||||||
previous_state = form.cleaned_data['previous_state']
|
|
||||||
new_state = form.cleaned_data['new_state']
|
|
||||||
snapshot_uuid = form.cleaned_data['snapshot_uuid']
|
|
||||||
|
|
||||||
State.objects.create(
|
State.objects.create(
|
||||||
snapshot_uuid=snapshot_uuid,
|
snapshot_uuid=snapshot_uuid,
|
||||||
state=new_state,
|
state=new_state,
|
||||||
user=self.request.user,
|
user=self.request.user,
|
||||||
institution=self.request.user.institution,
|
institution=self.request.user.institution,
|
||||||
)
|
)
|
||||||
|
|
||||||
message = _("<Created> State '{}'. Previous State: '{}' ".format(new_state, previous_state) )
|
message = _("<Created> State '{}'. Previous State: '{}'").format(new_state, previous_state)
|
||||||
DeviceLog.objects.create(
|
DeviceLog.objects.create(
|
||||||
snapshot_uuid=snapshot_uuid,
|
snapshot_uuid=snapshot_uuid,
|
||||||
event=message,
|
event=message,
|
||||||
user=self.request.user,
|
user=self.request.user,
|
||||||
institution=self.request.user.institution,
|
institution=self.request.user.institution,
|
||||||
)
|
)
|
||||||
|
messages.success(self.request, _("State successfully changed from '{}' to '{}'").format(previous_state, new_state))
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
messages.success(request, _("State succesfuly changed from '{}' to '{}' ".format(previous_state, new_state) ) )
|
def form_invalid(self, form):
|
||||||
else:
|
messages.error(self.request, _("There was an error with your submission."))
|
||||||
messages.error(request, "There was an error with your submission.")
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
return redirect(request.META.get('HTTP_REFERER') )
|
def get_success_url(self):
|
||||||
|
return self.request.META.get('HTTP_REFERER') or reverse_lazy('device:details')
|
||||||
|
|
||||||
|
|
||||||
class AddNoteView(View):
|
class AddNoteView(FormView):
|
||||||
|
form_class = AddNoteForm
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def form_valid(self, form):
|
||||||
form = AddNoteForm(request.POST)
|
note_text = form.cleaned_data['note']
|
||||||
|
snapshot_uuid = form.cleaned_data['snapshot_uuid']
|
||||||
|
Note.objects.create(
|
||||||
|
snapshot_uuid=snapshot_uuid,
|
||||||
|
description=note_text,
|
||||||
|
user=self.request.user,
|
||||||
|
institution=self.request.user.institution,
|
||||||
|
)
|
||||||
|
|
||||||
if form.is_valid():
|
message = _("<Created> Note: '{}'").format(note_text)
|
||||||
note = form.cleaned_data['note']
|
DeviceLog.objects.create(
|
||||||
snapshot_uuid = form.cleaned_data['snapshot_uuid']
|
snapshot_uuid=snapshot_uuid,
|
||||||
Note.objects.create(
|
event=message,
|
||||||
snapshot_uuid=snapshot_uuid,
|
user=self.request.user,
|
||||||
description=note,
|
institution=self.request.user.institution,
|
||||||
user=self.request.user,
|
)
|
||||||
institution=self.request.user.institution,
|
messages.success(self.request, _("Note has been added"))
|
||||||
)
|
return super().form_valid(form)
|
||||||
|
|
||||||
message = _("<Created> Note: '{}' ".format(note) )
|
def form_invalid(self, form):
|
||||||
DeviceLog.objects.create(
|
messages.error(self.request, _("There was an error with your submission."))
|
||||||
snapshot_uuid=snapshot_uuid,
|
return redirect(self.get_success_url())
|
||||||
event=message,
|
|
||||||
user=self.request.user,
|
def get_success_url(self):
|
||||||
institution=self.request.user.institution,
|
return self.request.META.get('HTTP_REFERER') or reverse_lazy('device:details')
|
||||||
)
|
|
||||||
messages.success(request, _("Note has been added"))
|
|
||||||
else:
|
|
||||||
messages.error(request, "There was an error with your submission.")
|
|
||||||
|
|
||||||
return redirect(request.META.get('HTTP_REFERER') )
|
|
||||||
|
|
||||||
class UpdateNoteView(UpdateView):
|
class UpdateNoteView(UpdateView):
|
||||||
model = Note
|
model = Note
|
||||||
fields = ['description']
|
fields = ['description']
|
||||||
template_name = 'device/templates/details.html'
|
|
||||||
pk_url_kwarg = 'pk'
|
pk_url_kwarg = 'pk'
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
@ -88,9 +91,50 @@ class UpdateNoteView(UpdateView):
|
||||||
user=self.request.user,
|
user=self.request.user,
|
||||||
institution=self.request.user.institution,
|
institution=self.request.user.institution,
|
||||||
)
|
)
|
||||||
|
messages.success(self.request, "Note has been updated.")
|
||||||
messages.success(self.request, "Note has been updated.")
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def form_invalid(self, form):
|
||||||
|
new_description = form.cleaned_data.get('description', '').strip()
|
||||||
|
if not new_description:
|
||||||
|
messages.error(self.request, _("Note cannot be empty."))
|
||||||
|
super().form_invalid(form)
|
||||||
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return self.request.META.get('HTTP_REFERER', reverse_lazy('device:details'))
|
return self.request.META.get('HTTP_REFERER', reverse_lazy('device:details'))
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteNoteView(View):
|
||||||
|
model = Note
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
self.pk = kwargs['pk']
|
||||||
|
referer = request.META.get('HTTP_REFERER')
|
||||||
|
if not referer:
|
||||||
|
raise Http404("No referer header found")
|
||||||
|
|
||||||
|
self.object = get_object_or_404(
|
||||||
|
self.model,
|
||||||
|
pk=self.pk,
|
||||||
|
institution=self.request.user.institution
|
||||||
|
)
|
||||||
|
description = self.object.description
|
||||||
|
snapshot_uuid= self.object.snapshot_uuid
|
||||||
|
|
||||||
|
if request.user != self.object.user and not request.user.is_admin:
|
||||||
|
messages.error(request, _("You do not have permission to delete this note."))
|
||||||
|
return redirect(referer)
|
||||||
|
|
||||||
|
message = _("<Deleted> Note. Description: '{}'. ").format(description)
|
||||||
|
DeviceLog.objects.create(
|
||||||
|
snapshot_uuid=snapshot_uuid,
|
||||||
|
event=message,
|
||||||
|
user=request.user,
|
||||||
|
institution=request.user.institution,
|
||||||
|
)
|
||||||
|
messages.warning(self.request, _("Note '{}' deleted successfully.").format(description))
|
||||||
|
|
||||||
|
self.object.delete()
|
||||||
|
|
||||||
|
return redirect(referer)
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
</caption>
|
</caption>
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" width="5%" class="text-start">
|
<th scope="col" width="1%" class="text-start">
|
||||||
</th>
|
</th>
|
||||||
|
<th scope="col" width="5%" class="text-center">
|
||||||
|
#</th>
|
||||||
<th scope="col">{% trans "State Definition" %}
|
<th scope="col">{% trans "State Definition" %}
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" width="15%" class="text-center">{% trans "Actions" %}
|
<th scope="col" width="15%" class="text-center">{% trans "Actions" %}
|
||||||
|
@ -37,9 +39,11 @@
|
||||||
class="align-items-center">
|
class="align-items-center">
|
||||||
|
|
||||||
<td class="">
|
<td class="">
|
||||||
<i class="fas fa-duotone fa-solid fa-grip px-1" aria-hidden="true">
|
<i class="bi bi-grip-vertical" aria-hidden="true">
|
||||||
</i>
|
</i>
|
||||||
<strong> {{ state_definition.order }} </strong>
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<strong>{{ state_definition.order }} </strong>
|
||||||
</td>
|
</td>
|
||||||
<td class="font-monospace">
|
<td class="font-monospace">
|
||||||
{{ state_definition.state }}
|
{{ state_definition.state }}
|
||||||
|
@ -48,16 +52,21 @@
|
||||||
<!-- action buttons -->
|
<!-- action buttons -->
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group float-end">
|
<div class="btn-group float-end">
|
||||||
<button type="button" class="btn btn-sm btn-info text-white" data-bs-toggle="modal" data-bs-target="#editStateModal{{ state_definition.id }}">
|
<button
|
||||||
<i class="bi bi-pencil">
|
type="button"
|
||||||
</i> {% trans 'Edit' %}
|
class="btn btn-sm btn-outline-info d-flex align-items-center"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#editStateModal{{ state_definition.id }}">
|
||||||
|
<i class="bi bi-pencil me-1"></i>
|
||||||
|
{% trans 'Edit' %}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-sm btn-danger" data-bs-toggle="modal" data-bs-target="#deleteStateModal{{ state_definition.id }}">
|
<button
|
||||||
<i class="bi bi-trash">
|
type="button" class="btn btn-sm btn-outline-danger d-flex align-items-center"
|
||||||
</i>
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#deleteStateModal{{ state_definition.id }}" >
|
||||||
|
<i class="bi bi-trash me-1"></i>
|
||||||
|
{% trans 'Delete' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="position-fixed" style="bottom: 2rem; right: 2rem; z-index: 9999; display: flex; gap: 0.5rem;">
|
<div class="position-fixed" style="bottom: 2rem; right: 2rem; z-index: 9999; display: flex; gap: 0.5rem;">
|
||||||
<button class="btn btn-outline-warning d-flex align-items-center shadow" type="button"
|
<button class="btn btn-warning d-flex align-items-center shadow" type="button"
|
||||||
data-bs-toggle="offcanvas" data-bs-target="#notesOffcanvas" aria-controls="notesOffcanvas"
|
data-bs-toggle="offcanvas" data-bs-target="#notesOffcanvas" aria-controls="notesOffcanvas"
|
||||||
data-bs-toggle="tooltip" data-bs-placement="left" title="{% trans 'View recent notes' %}">
|
data-bs-toggle="tooltip" data-bs-placement="left" title="{% trans 'View recent notes' %}">
|
||||||
<i class="bi bi-journal-text me-1"></i>
|
<i class="bi bi-journal-text me-1"></i>
|
||||||
|
@ -19,24 +19,28 @@
|
||||||
<h5 id="notesOffcanvasLabel">{% trans "Latest Notes" %}</h5>
|
<h5 id="notesOffcanvasLabel">{% trans "Latest Notes" %}</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="offcanvas-body">
|
<div class="offcanvas-body" style="margin-bottom: 5rem;">
|
||||||
{% for note in device_notes|slice:":4" %}
|
{% for note in device_notes|slice:":4" %}
|
||||||
<div class="card mb-3 shadow-sm">
|
<div class="card mb-3 shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div>
|
<div>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
{{ note.date|timesince }} {% trans "ago" %}
|
{{ note.date|timesince }} {% trans "ago" %}
|
||||||
</small>
|
</small>
|
||||||
</div>
|
|
||||||
{% if user == note.user or user.is_admin %}
|
{% if user == note.user or user.is_admin %}
|
||||||
|
<span class="badge bg-warning text-dark ms-2">{% trans "Editable" %}</span>
|
||||||
|
</div>
|
||||||
<blockquote
|
<blockquote
|
||||||
class="blockquote mt-2 p-2 bg-light fst-italic"
|
class="blockquote mt-2 p-2 bg-light fst-italic"
|
||||||
contenteditable="true"
|
contenteditable="true"
|
||||||
style="font-size: 1em!important"
|
style="font-size: 1.2em!important"
|
||||||
data-note-id="{{ note.id }}"
|
data-note-id="{{ note.id }}"
|
||||||
|
title="{% trans 'Click to edit this note' %}"
|
||||||
oninput="toggleSaveLink(this)">
|
oninput="toggleSaveLink(this)">
|
||||||
{% else %}
|
{% else %}
|
||||||
<blockquote style="font-size: 1em!important" class="blockquote mt-2 p-2 fst-italic">
|
</div>
|
||||||
|
<blockquote style="font-size: 1.2em!important" class="blockquote mt-2 p-2 fst-italic">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p data-note-id="{{ note.id }}">
|
<p data-note-id="{{ note.id }}">
|
||||||
{{ note.description }}
|
{{ note.description }}
|
||||||
|
@ -49,6 +53,7 @@
|
||||||
{% if user == note.user or user.is_admin %}
|
{% if user == note.user or user.is_admin %}
|
||||||
<div class="d-flex justify-content-end align-items-center">
|
<div class="d-flex justify-content-end align-items-center">
|
||||||
|
|
||||||
|
<!-- update note button -->
|
||||||
<form
|
<form
|
||||||
id="updateNoteForm{{ note.id }}"
|
id="updateNoteForm{{ note.id }}"
|
||||||
method="post"
|
method="post"
|
||||||
|
@ -60,22 +65,35 @@
|
||||||
<a
|
<a
|
||||||
type="submit"
|
type="submit"
|
||||||
id="saveLink{{ note.id }}"
|
id="saveLink{{ note.id }}"
|
||||||
class="text-muted disabled me-4"
|
class="text-muted disabled me-4 border border-light rounded"
|
||||||
style="pointer-events: none;"
|
style="pointer-events: none;"
|
||||||
title="{% trans 'Save changes' %}"
|
title="{% trans 'Save changes' %}"
|
||||||
onclick="submitUpdatedNote('{{ note.id }}'); return false;"
|
onclick="submitUpdatedNote('{{ note.id }}'); return false;"
|
||||||
>
|
>
|
||||||
<i class="fas fa-save"></i>
|
<i class="fas fa-save px-1"></i>
|
||||||
</a>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form class="d-inline" method="post" action="">
|
|
||||||
{% csrf_token %}
|
|
||||||
<a type="submit" class="text-danger" onclick="return confirm('{% trans 'Are you sure you want to delete this note?' %}')" title="{% trans 'Delete note' %}">
|
|
||||||
<i class="bi bi-trash"></i>
|
|
||||||
</a>
|
</a>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- delete note button -->
|
||||||
|
<button type="button" class="btn btn-link btn-outline-danger btn-sm text-danger" id="deleteIcon{{ note.id }}" title="{% trans 'Delete note' %}" data-bs-toggle="collapse" data-bs-target="#confirmDelete{{ note.id }}">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<form class="d-inline" method="post" action="{% url 'action:delete_note' note.id %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="collapse mt-2" id="confirmDelete{{ note.id }}">
|
||||||
|
<div class="card card-body border border-danger text-center">
|
||||||
|
<p class="mb-2">{% trans 'Are you sure you want to delete this note?' %}</p>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="btn btn-sm btn-outline-danger"
|
||||||
|
onclick="submitDeleteForm({{ note.id }}); return false;"
|
||||||
|
>
|
||||||
|
{% trans 'Confirm delete' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,7 +119,9 @@
|
||||||
{% trans "Change state" %}
|
{% trans "Change state" %}
|
||||||
{% if device_states %}
|
{% if device_states %}
|
||||||
({{ device_states.0.state }})
|
({{ device_states.0.state }})
|
||||||
{% endif %}
|
{% else %}
|
||||||
|
( {% trans "None" %} )
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu" aria-labelledby="addStateDropdown" style="width: 100%;">
|
<ul class="dropdown-menu" aria-labelledby="addStateDropdown" style="width: 100%;">
|
||||||
{% for state in state_definitions %}
|
{% for state in state_definitions %}
|
||||||
|
@ -188,6 +208,7 @@
|
||||||
|
|
||||||
{% include 'tabs/evidences.html' %}
|
{% include 'tabs/evidences.html' %}
|
||||||
|
|
||||||
|
<!-- Add a note popup -->
|
||||||
<div class="modal fade" id="addNoteModal" tabindex="-1" aria-labelledby="addNoteModalLabel" aria-hidden="true">
|
<div class="modal fade" id="addNoteModal" tabindex="-1" aria-labelledby="addNoteModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
|
@ -238,8 +259,8 @@
|
||||||
function toggleSaveLink(blockquoteElem) {
|
function toggleSaveLink(blockquoteElem) {
|
||||||
const saveLink = document.getElementById("saveLink" + blockquoteElem.dataset.noteId);
|
const saveLink = document.getElementById("saveLink" + blockquoteElem.dataset.noteId);
|
||||||
|
|
||||||
saveLink.classList.remove("disabled", "text-muted");
|
saveLink.classList.remove("disabled", "text-muted", "border-light");
|
||||||
saveLink.classList.add("text-success");
|
saveLink.classList.add("text-success", "border-success");
|
||||||
saveLink.style.pointerEvents = "auto";
|
saveLink.style.pointerEvents = "auto";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -251,5 +272,9 @@
|
||||||
descriptionField.value = newText;
|
descriptionField.value = newText;
|
||||||
document.getElementById('updateNoteForm' + noteId).submit();
|
document.getElementById('updateNoteForm' + noteId).submit();
|
||||||
}
|
}
|
||||||
|
//simpler are u sure? confirmation message
|
||||||
|
function submitDeleteForm(noteId) {
|
||||||
|
document.getElementById('confirmDelete' + noteId).closest('form').submit();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2,30 +2,23 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
<div class="tab-pane fade" id="user_properties">
|
<div class="tab-pane fade" id="user_properties">
|
||||||
<div class="btn-group mt-1 mb-3">
|
<div class="d-flex justify-content-end mt-1 mb-3">
|
||||||
<a href="{% url 'device:add_user_property' object.pk %}" class="btn btn-primary">
|
<a href="{% url 'device:add_user_property' object.pk %}"
|
||||||
<i class="bi bi-plus">
|
class="btn btn-green-admin d-flex align-items-center">
|
||||||
</i>
|
<i class="bi bi-plus me-1"></i>
|
||||||
{% trans 'New user property' %}
|
{% trans 'New user property' %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="card-title">{% trans 'User properties' %}
|
<h5 class="card-title">{% trans 'User properties' %}</h5>
|
||||||
</h5>
|
|
||||||
<table class="table table-striped">
|
<table class="table table-hover table-bordered table-responsive align-middle">
|
||||||
<thead>
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">
|
<th scope="col">{% trans 'Key' %}</th>
|
||||||
{% trans 'Key' %}
|
<th scope="col">{% trans 'Value' %}</th>
|
||||||
</th>
|
<th scope="col" data-type="date" class="text-end" data-format="YYYY-MM-DD HH:mm">{% trans 'Created on' %}</th>
|
||||||
<th scope="col">
|
<th scope="col" width="5%" class="text-end" title="{% trans 'Actions' %}"></th>
|
||||||
{% trans 'Value' %}
|
|
||||||
</th>
|
|
||||||
<th scope="col" data-type="date" data-format="YYYY-MM-DD HH:mm">
|
|
||||||
{% trans 'Created on' %}
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -35,17 +28,23 @@
|
||||||
</td>
|
</td>
|
||||||
<td>{{ a.value }}
|
<td>{{ a.value }}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ a.created }}
|
<td class="text-end">{{ a.created }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="btn-group float-end">
|
<div class="btn-group ">
|
||||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#editModal{{ a.id }}">
|
<button
|
||||||
<i class="bi bi-pencil">
|
type="button"
|
||||||
</i> {% trans 'Edit' %}
|
class="btn btn-sm btn-outline-info d-flex align-items-center" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#editModal{{ a.id }}" >
|
||||||
|
<i class="bi bi-pencil me-1"></i>
|
||||||
|
{% trans 'Edit' %}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-sm btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal{{ a.id }}">
|
<button
|
||||||
<i class="bi bi-trash">
|
type="button"
|
||||||
</i>
|
class="btn btn-sm btn-outline-danger d-flex align-items-center"
|
||||||
|
data-bs-toggle="modal" data-bs-target="#deleteModal{{ a.id }}">
|
||||||
|
<i class="bi bi-trash me-1"></i>
|
||||||
|
{% trans 'Delete' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -190,7 +190,6 @@ class AddUserPropertyView(DashboardView, CreateView):
|
||||||
template_name = "new_user_property.html"
|
template_name = "new_user_property.html"
|
||||||
title = _("New User Property")
|
title = _("New User Property")
|
||||||
breadcrumb = "Device / New Property"
|
breadcrumb = "Device / New Property"
|
||||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
|
||||||
model = UserProperty
|
model = UserProperty
|
||||||
fields = ("key", "value")
|
fields = ("key", "value")
|
||||||
|
|
||||||
|
@ -215,17 +214,13 @@ class AddUserPropertyView(DashboardView, CreateView):
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
institution = self.request.user.institution
|
institution = self.request.user.institution
|
||||||
self.property = SystemProperty.objects.filter(
|
self.property = get_object_or_404(SystemProperty, owner=institution, value=pk)
|
||||||
owner=institution,
|
|
||||||
value=pk,
|
|
||||||
).first()
|
|
||||||
|
|
||||||
if not self.property:
|
return super().get_form_kwargs()
|
||||||
raise Http404
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse_lazy('device:details', args=[self.kwargs.get('pk')])
|
||||||
|
|
||||||
self.success_url = reverse_lazy('device:details', args=[pk])
|
|
||||||
kwargs = super().get_form_kwargs()
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
class UpdateUserPropertyView(DashboardView, UpdateView):
|
class UpdateUserPropertyView(DashboardView, UpdateView):
|
||||||
template_name = "new_user_property.html"
|
template_name = "new_user_property.html"
|
||||||
|
@ -234,37 +229,34 @@ class UpdateUserPropertyView(DashboardView, UpdateView):
|
||||||
model = UserProperty
|
model = UserProperty
|
||||||
fields = ("key", "value")
|
fields = ("key", "value")
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_queryset(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
user_property = get_object_or_404(UserProperty, pk=pk, owner=self.request.user.institution)
|
institution = self.request.user.institution
|
||||||
|
return UserProperty.objects.filter(pk=pk, owner=institution)
|
||||||
if not user_property:
|
|
||||||
raise Http404
|
|
||||||
|
|
||||||
kwargs = super().get_form_kwargs()
|
|
||||||
kwargs['instance'] = user_property
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
old_key= self.object.key
|
|
||||||
old_value = self.object.value
|
old_instance = self.get_object()
|
||||||
new_key = form.cleaned_data['key']
|
old_key = old_instance.key
|
||||||
new_value = form.cleaned_data['value']
|
old_value = old_instance.value
|
||||||
|
|
||||||
form.instance.owner = self.request.user.institution
|
form.instance.owner = self.request.user.institution
|
||||||
form.instance.user = self.request.user
|
form.instance.user = self.request.user
|
||||||
form.instance.type = UserProperty.Type.USER
|
form.instance.type = UserProperty.Type.USER
|
||||||
response = super().form_valid(form)
|
|
||||||
messages.success(self.request, _("User property updated successfully."))
|
|
||||||
|
|
||||||
message = _("<Updated> UserProperty: {}: {} to {}: {}".format(old_key, old_value, new_key, new_value ))
|
new_key = form.cleaned_data['key']
|
||||||
|
new_value = form.cleaned_data['value']
|
||||||
|
|
||||||
|
message = _("<Updated> UserProperty: {}: {} to {}: {}".format(old_key, old_value, new_key, new_value))
|
||||||
DeviceLog.objects.create(
|
DeviceLog.objects.create(
|
||||||
snapshot_uuid=form.instance.uuid,
|
snapshot_uuid=form.instance.uuid,
|
||||||
event=message,
|
event=message,
|
||||||
user=self.request.user,
|
user=self.request.user,
|
||||||
institution=self.request.user.institution
|
institution=self.request.user.institution
|
||||||
)
|
)
|
||||||
return response
|
|
||||||
|
messages.success(self.request, _("User property updated successfully."))
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return self.request.META.get('HTTP_REFERER', reverse_lazy('device:details', args=[self.object.pk]))
|
return self.request.META.get('HTTP_REFERER', reverse_lazy('device:details', args=[self.object.pk]))
|
||||||
|
@ -273,17 +265,14 @@ class UpdateUserPropertyView(DashboardView, UpdateView):
|
||||||
class DeleteUserPropertyView(DashboardView, DeleteView):
|
class DeleteUserPropertyView(DashboardView, DeleteView):
|
||||||
model = UserProperty
|
model = UserProperty
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def get_queryset(self):
|
||||||
self.pk = kwargs['pk']
|
return UserProperty.objects.filter(owner=self.request.user.institution)
|
||||||
referer = request.META.get('HTTP_REFERER')
|
|
||||||
if not referer:
|
#using post() method because delete() method from DeleteView has some issues with messages framework
|
||||||
raise Http404("No referer header found")
|
def post(self, request, *args, **kwargs):
|
||||||
|
self.object = self.get_object()
|
||||||
|
self.object.delete()
|
||||||
|
|
||||||
self.object = get_object_or_404(
|
|
||||||
self.model,
|
|
||||||
pk=self.pk,
|
|
||||||
owner=self.request.user.institution
|
|
||||||
)
|
|
||||||
message = _("<Deleted> User Property: {}:{}".format(self.object.key, self.object.value ))
|
message = _("<Deleted> User Property: {}:{}".format(self.object.key, self.object.value ))
|
||||||
DeviceLog.objects.create(
|
DeviceLog.objects.create(
|
||||||
snapshot_uuid=self.object.uuid,
|
snapshot_uuid=self.object.uuid,
|
||||||
|
@ -292,12 +281,15 @@ class DeleteUserPropertyView(DashboardView, DeleteView):
|
||||||
institution=self.request.user.institution
|
institution=self.request.user.institution
|
||||||
)
|
)
|
||||||
|
|
||||||
self.object.delete()
|
|
||||||
messages.info(self.request, _("User property deleted successfully."))
|
messages.info(self.request, _("User property deleted successfully."))
|
||||||
|
|
||||||
# Redirect back to the original URL
|
return self.handle_success()
|
||||||
return redirect(referer)
|
|
||||||
|
|
||||||
|
def handle_success(self):
|
||||||
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return self.request.META.get('HTTP_REFERER', reverse_lazy('device:details', args=[self.object.pk]))
|
||||||
|
|
||||||
class AddDocumentView(DashboardView, CreateView):
|
class AddDocumentView(DashboardView, CreateView):
|
||||||
template_name = "new_user_property.html"
|
template_name = "new_user_property.html"
|
||||||
|
|
|
@ -10,6 +10,7 @@ from device.models import Device
|
||||||
from evidence.parse import Build
|
from evidence.parse import Build
|
||||||
from evidence.models import SystemProperty, UserProperty
|
from evidence.models import SystemProperty, UserProperty
|
||||||
from utils.save_snapshots import move_json, save_in_disk
|
from utils.save_snapshots import move_json, save_in_disk
|
||||||
|
from action.models import DeviceLog
|
||||||
|
|
||||||
|
|
||||||
class UploadForm(forms.Form):
|
class UploadForm(forms.Form):
|
||||||
|
@ -98,19 +99,31 @@ class UserTagForm(forms.Form):
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.instance:
|
if self.instance:
|
||||||
|
old_value = self.instance.value
|
||||||
if not self.tag:
|
if not self.tag:
|
||||||
|
message =_("<Deleted> Evidence Tag. Old Value: '{}'").format(old_value)
|
||||||
self.instance.delete()
|
self.instance.delete()
|
||||||
self.instance.value = self.tag
|
else:
|
||||||
self.instance.save()
|
self.instance.value = self.tag
|
||||||
return
|
self.instance.save()
|
||||||
|
if old_value != self.tag:
|
||||||
SystemProperty.objects.create(
|
message=_("<Updated> Evidence Tag. Old Value: '{}'. New Value: '{}'").format(old_value, self.tag)
|
||||||
uuid=self.uuid,
|
else:
|
||||||
key='CUSTOM_ID',
|
message =_("<Created> Evidence Tag. Value: '{}'").format(self.tag)
|
||||||
value=self.tag,
|
SystemProperty.objects.create(
|
||||||
owner=self.user.institution,
|
uuid=self.uuid,
|
||||||
user=self.user
|
key='CUSTOM_ID',
|
||||||
)
|
value=self.tag,
|
||||||
|
owner=self.user.institution,
|
||||||
|
user=self.user
|
||||||
|
)
|
||||||
|
|
||||||
|
DeviceLog.objects.create(
|
||||||
|
snapshot_uuid=self.uuid,
|
||||||
|
event= message,
|
||||||
|
user=self.user,
|
||||||
|
institution=self.user.institution
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ImportForm(forms.Form):
|
class ImportForm(forms.Form):
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% if form.tag.value %}
|
{% if form.tag.value %}
|
||||||
<div class="col-1">
|
<div class="col-1">
|
||||||
<a class="btn btn-yellow" href="{% url 'device:delete_user_property' form.pk %}">{% translate "Delete" %}</a>
|
<a class="btn btn-yellow" href="{% url 'evidence:delete_tag' form.pk %}">{% translate "Delete" %}</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,4 +20,5 @@ urlpatterns = [
|
||||||
path("<uuid:pk>", views.EvidenceView.as_view(), name="details"),
|
path("<uuid:pk>", views.EvidenceView.as_view(), name="details"),
|
||||||
path("<uuid:pk>/eraseserver", views.EraseServerView.as_view(), name="erase_server"),
|
path("<uuid:pk>/eraseserver", views.EraseServerView.as_view(), name="erase_server"),
|
||||||
path("<uuid:pk>/download", views.DownloadEvidenceView.as_view(), name="download"),
|
path("<uuid:pk>/download", views.DownloadEvidenceView.as_view(), name="download"),
|
||||||
|
path("tag/<str:pk>/delete", views.DeleteEvidenceTagView.as_view(), name="delete_tag"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,6 +12,7 @@ from django.views.generic.edit import (
|
||||||
FormView,
|
FormView,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from action.models import DeviceLog
|
||||||
from dashboard.mixins import DashboardView, Http403
|
from dashboard.mixins import DashboardView, Http403
|
||||||
from evidence.models import SystemProperty, UserProperty, Evidence
|
from evidence.models import SystemProperty, UserProperty, Evidence
|
||||||
from evidence.forms import (
|
from evidence.forms import (
|
||||||
|
@ -184,3 +185,35 @@ class EraseServerView(DashboardView, FormView):
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
success_url = reverse_lazy('evidence:details', args=[self.pk])
|
success_url = reverse_lazy('evidence:details', args=[self.pk])
|
||||||
return success_url
|
return success_url
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteEvidenceTagView(DashboardView, DeleteView):
|
||||||
|
model = SystemProperty
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
# only those with 'CUSTOM_ID'
|
||||||
|
return SystemProperty.objects.filter(owner=self.request.user.institution, key='CUSTOM_ID')
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
self.object = self.get_object()
|
||||||
|
|
||||||
|
message = _("<Deleted> Evidence Tag: {}").format(self.object.value)
|
||||||
|
DeviceLog.objects.create(
|
||||||
|
snapshot_uuid=self.object.uuid,
|
||||||
|
event=message,
|
||||||
|
user=self.request.user,
|
||||||
|
institution=self.request.user.institution
|
||||||
|
)
|
||||||
|
self.object.delete()
|
||||||
|
|
||||||
|
messages.info(self.request, _("Evicende Tag deleted successfully."))
|
||||||
|
return self.handle_success()
|
||||||
|
|
||||||
|
def handle_success(self):
|
||||||
|
return redirect(self.get_success_url())
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return self.request.META.get(
|
||||||
|
'HTTP_REFERER',
|
||||||
|
reverse_lazy('evidence:details', args=[self.object.uuid])
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue