feature/90-implement-public-website-for-device #17
|
@ -70,10 +70,17 @@ class SearchView(InventaryMixin):
|
||||||
return self.search_hids(query, offset, limit)
|
return self.search_hids(query, offset, limit)
|
||||||
|
|
||||||
devices = []
|
devices = []
|
||||||
|
dev_id = []
|
||||||
|
|
||||||
for x in matches:
|
for x in matches:
|
||||||
devices.append(self.get_annotations(x))
|
# devices.append(self.get_annotations(x))
|
||||||
|
dev = self.get_annotations(x)
|
||||||
|
if dev.id not in dev_id:
|
||||||
|
devices.append(dev)
|
||||||
|
dev_id.append(dev.id)
|
||||||
|
|
||||||
count = matches.size()
|
count = matches.size()
|
||||||
|
# TODO fix of pagination, the count is not correct
|
||||||
return devices, count
|
return devices, count
|
||||||
|
|
||||||
def get_annotations(self, xp):
|
def get_annotations(self, xp):
|
||||||
|
|
|
@ -108,6 +108,22 @@ class Device:
|
||||||
return
|
return
|
||||||
annotation = annotations.first()
|
annotation = annotations.first()
|
||||||
self.last_evidence = Evidence(annotation.uuid)
|
self.last_evidence = Evidence(annotation.uuid)
|
||||||
|
|
||||||
|
def is_eraseserver(self):
|
||||||
|
if not self.uuids:
|
||||||
|
self.get_uuids()
|
||||||
|
if not self.uuids:
|
||||||
|
return False
|
||||||
|
|
||||||
|
annotation = Annotation.objects.filter(
|
||||||
|
uuid__in=self.uuids,
|
||||||
|
owner=self.owner,
|
||||||
|
type=Annotation.Type.ERASE_SERVER
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if annotation:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def last_uuid(self):
|
def last_uuid(self):
|
||||||
return self.uuids[0]
|
return self.uuids[0]
|
||||||
|
|
|
@ -2,38 +2,126 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3>{{ object.shortid }}</h3>
|
<h3>{{ object.shortid }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#details" class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">{% trans "General details" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#annotations" class="nav-link" data-bs-toggle="tab" data-bs-target="#annotations">{% trans "User annotations" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#documents" class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">{% trans "Documents" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#lots" class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">{% trans "Lots" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#components" class="nav-link" data-bs-toggle="tab" data-bs-target="#components">{% trans "Components" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">{% trans "Evidences" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="#web" class="nav-link" href="">Web</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-content pt-2">
|
||||||
|
|
||||||
|
<div class="tab-pane fade show active" id="details">
|
||||||
|
<h5 class="card-title">{% trans "Details" %}</h5>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ object.id }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% if object.is_eraseserver %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-lg-3 col-md-4 label">{% trans "Is a erase server" %}</div>
|
||||||
|
<div class="col-lg-9 col-md-8"></div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label ">{% trans "Type" %}</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ object.type }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if object.is_websnapshot %}
|
||||||
|
{% for k, v in object.last_user_evidence %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">{{ k }}</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ v|default:"" }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ object.manufacturer|default:"" }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Model</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ object.model|default:"" }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
||||||
|
<div class="col-lg-9 col-md-8">{{ object.last_evidence.doc.device.serialNumber|default:"" }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 label">Identifiers</div>
|
||||||
|
</div>
|
||||||
|
{% for chid in object.hids %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">{{ chid |default:"" }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="tab-pane fade profile-overview" id="annotations">
|
||||||
<div class="col">
|
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
<a href="{% url 'device:add_annotation' object.pk %}" class="btn btn-primary">
|
||||||
<li class="nav-items">
|
<i class="bi bi-plus"></i>
|
||||||
<a href="#details" class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">General details</a>
|
{% trans "Add new annotation" %}
|
||||||
</li>
|
<span class="caret"></span>
|
||||||
<li class="nav-items">
|
</a>
|
||||||
<a href="#annotations" class="nav-link" data-bs-toggle="tab" data-bs-target="#annotations">User annotations</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-items">
|
|
||||||
<a href="#documents" class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-items">
|
|
||||||
<a href="#lots" class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-items">
|
|
||||||
<a href="#components" class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-items">
|
|
||||||
<a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">Evidences</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-items">
|
|
||||||
<a class="nav-link" href="{% url 'device:device_web' object.id %}">Web</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h5 class="card-title mt-2">{% trans "Annotations" %}</h5>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Key</th>
|
||||||
|
<th scope="col">Value</th>
|
||||||
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created on</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for a in object.get_user_annotations %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ a.key }}</td>
|
||||||
|
<td>{{ a.value }}</td>
|
||||||
|
<td>{{ a.created }}</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content pt-2">
|
<div class="tab-content pt-2">
|
||||||
<div class="tab-pane fade show active" id="details">
|
<div class="tab-pane fade show active" id="details">
|
||||||
|
|
|
@ -162,3 +162,56 @@ class ImportForm(forms.Form):
|
||||||
return table
|
return table
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class EraseServerForm(forms.Form):
|
||||||
|
erase_server = forms.BooleanField(label=_("Is a Erase Server"), required=False)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.pk = None
|
||||||
|
self.uuid = kwargs.pop('uuid', None)
|
||||||
|
self.user = kwargs.pop('user')
|
||||||
|
instance = Annotation.objects.filter(
|
||||||
|
uuid=self.uuid,
|
||||||
|
type=Annotation.Type.ERASE_SERVER,
|
||||||
|
key='ERASE_SERVER',
|
||||||
|
owner=self.user.institution
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if instance:
|
||||||
|
kwargs["initial"]["erase_server"] = instance.value
|
||||||
|
self.pk = instance.pk
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
self.erase_server = self.cleaned_data.get('erase_server', False)
|
||||||
|
self.instance = Annotation.objects.filter(
|
||||||
|
uuid=self.uuid,
|
||||||
|
type=Annotation.Type.ERASE_SERVER,
|
||||||
|
key='ERASE_SERVER',
|
||||||
|
owner=self.user.institution
|
||||||
|
).first()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def save(self, user, commit=True):
|
||||||
|
if not commit:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.erase_server:
|
||||||
|
if self.instance:
|
||||||
|
self.instance.delete()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.instance:
|
||||||
|
return
|
||||||
|
|
||||||
|
Annotation.objects.create(
|
||||||
|
uuid=self.uuid,
|
||||||
|
type=Annotation.Type.ERASE_SERVER,
|
||||||
|
key='ERASE_SERVER',
|
||||||
|
value=self.erase_server,
|
||||||
|
owner=self.user.institution,
|
||||||
|
user=self.user
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-10-28 12:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("evidence", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="annotation",
|
||||||
|
name="type",
|
||||||
|
field=models.SmallIntegerField(
|
||||||
|
choices=[
|
||||||
|
(0, "System"),
|
||||||
|
(1, "User"),
|
||||||
|
(2, "Document"),
|
||||||
|
(3, "EraseServer"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -14,6 +14,7 @@ class Annotation(models.Model):
|
||||||
SYSTEM= 0, "System"
|
SYSTEM= 0, "System"
|
||||||
USER = 1, "User"
|
USER = 1, "User"
|
||||||
DOCUMENT = 2, "Document"
|
DOCUMENT = 2, "Document"
|
||||||
|
ERASE_SERVER = 3, "EraseServer"
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
uuid = models.UUIDField()
|
uuid = models.UUIDField()
|
||||||
|
|
|
@ -12,13 +12,16 @@
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#device">Devices</button>
|
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#device">{% trans "Devices" %}</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tag">Tag</button>
|
<a href="#tag" class="nav-link" data-bs-toggle="tab" data-bs-target="#tag">{% trans "Tag" %}</a>
|
||||||
<li class="nav-items">
|
|
||||||
<a href="{% url 'evidence:download' object.uuid %}" class="nav-link">Download File</a>
|
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="{% url 'evidence:erase_server' object.uuid %}" class="nav-link">{% trans "Erase Server" %}</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<a href="{% url 'evidence:download' object.uuid %}" class="nav-link">{% trans "Download File" %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -83,3 +86,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extrascript %}
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
// Obtener el hash de la URL (ejemplo: #components)
|
||||||
|
const hash = window.location.hash;
|
||||||
|
|
||||||
|
// Verificar si hay un hash en la URL
|
||||||
|
if (hash) {
|
||||||
|
// Buscar el botón o enlace que corresponde al hash y activarlo
|
||||||
|
const tabTrigger = document.querySelector(`[data-bs-target="${hash}"]`);
|
||||||
|
|
||||||
|
if (tabTrigger) {
|
||||||
|
// Crear una instancia de tab de Bootstrap para activar el tab
|
||||||
|
const tab = new bootstrap.Tab(tabTrigger);
|
||||||
|
tab.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -18,6 +18,7 @@ urlpatterns = [
|
||||||
path("upload", views.UploadView.as_view(), name="upload"),
|
path("upload", views.UploadView.as_view(), name="upload"),
|
||||||
path("import", views.ImportView.as_view(), name="import"),
|
path("import", views.ImportView.as_view(), name="import"),
|
||||||
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>/download", views.DownloadEvidenceView.as_view(), name="download"),
|
path("<uuid:pk>/download", views.DownloadEvidenceView.as_view(), name="download"),
|
||||||
path('annotation/<int:pk>/del', views.AnnotationDeleteView.as_view(), name='delete_annotation'),
|
path('annotation/<int:pk>/del', views.AnnotationDeleteView.as_view(), name='delete_annotation'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,18 +11,14 @@ from django.views.generic.edit import (
|
||||||
FormView,
|
FormView,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
from dashboard.mixins import DashboardView, Http403
|
from dashboard.mixins import DashboardView, Http403
|
||||||
from evidence.models import Evidence, Annotation
|
from evidence.models import Evidence, Annotation
|
||||||
from evidence.forms import UploadForm, UserTagForm, ImportForm
|
from evidence.forms import (
|
||||||
# from django.shortcuts import render
|
UploadForm,
|
||||||
# from rest_framework import viewsets
|
UserTagForm,
|
||||||
# from snapshot.serializers import SnapshotSerializer
|
ImportForm,
|
||||||
|
EraseServerForm
|
||||||
|
)
|
||||||
# class SnapshotViewSet(viewsets.ModelViewSet):
|
|
||||||
# queryset = Snapshot.objects.all()
|
|
||||||
# serializer_class = SnapshotSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class ListEvidencesView(DashboardView, TemplateView):
|
class ListEvidencesView(DashboardView, TemplateView):
|
||||||
|
@ -167,3 +163,48 @@ class AnnotationDeleteView(DashboardView, DeleteView):
|
||||||
|
|
||||||
|
|
||||||
return redirect(url_name, **kwargs_view)
|
return redirect(url_name, **kwargs_view)
|
||||||
|
|
||||||
|
|
||||||
|
class EraseServerView(DashboardView, FormView):
|
||||||
|
template_name = "ev_eraseserver.html"
|
||||||
|
section = "evidences"
|
||||||
|
title = _("Evidences")
|
||||||
|
breadcrumb = "Evidences / Details"
|
||||||
|
success_url = reverse_lazy('evidence:list')
|
||||||
|
form_class = EraseServerForm
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
self.pk = kwargs['pk']
|
||||||
|
self.object = Evidence(self.pk)
|
||||||
|
if self.object.owner != self.request.user.institution:
|
||||||
|
raise Http403
|
||||||
|
|
||||||
|
self.object.get_annotations()
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context.update({
|
||||||
|
'object': self.object,
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_form_kwargs(self):
|
||||||
|
self.pk = self.kwargs.get('pk')
|
||||||
|
kwargs = super().get_form_kwargs()
|
||||||
|
kwargs['uuid'] = self.pk
|
||||||
|
kwargs['user'] = self.request.user
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
form.save(self.request.user)
|
||||||
|
response = super().form_valid(form)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def form_invalid(self, form):
|
||||||
|
response = super().form_invalid(form)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
success_url = reverse_lazy('evidence:details', args=[self.pk])
|
||||||
|
return success_url
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-10-28 12:56
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("lot", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="lot",
|
||||||
|
name="closed",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
Loading…
Reference in New Issue