new structure

This commit is contained in:
Cayo Puigdefabregas 2024-07-19 17:40:01 +02:00
parent b1440fddfa
commit 0cffa5a951
19 changed files with 262 additions and 115 deletions

View file

@ -5,6 +5,7 @@ from django.core.exceptions import PermissionDenied
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.base import TemplateView
from device.models import Device
from snapshot.models import Annotation
from lot.models import LotTag
@ -45,7 +46,10 @@ class DashboardView(LoginRequiredMixin):
def get_session_devices(self):
# import pdb; pdb.set_trace()
dev_ids = self.request.session.pop("devices", [])
self._devices = Device.objects.filter(id__in=dev_ids).filter(owner=self.request.user)
self._devices = []
for x in Annotation.objects.filter(value__in=dev_ids).filter(owner=self.request.user).distinct():
self._devices.append(Device(id=x.value))
return self._devices
@ -53,7 +57,7 @@ class DetailsMixin(DashboardView, TemplateView):
def get(self, request, *args, **kwargs):
self.pk = kwargs['pk']
self.object = get_object_or_404(self.model, pk=self.pk)
self.object = get_object_or_404(self.model, pk=self.pk, owner=self.request.user)
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):

View file

@ -90,11 +90,6 @@
{% trans 'Unassigned devices' %}
</a>
</li>
<li class="nav-item">
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{% url 'dashboard:all_devices' %}">
{% trans 'All devices' %}
</a>
</li>
</ul>
</li>
<li class="nav-item">

View file

@ -5,6 +5,5 @@ app_name = 'dashboard'
urlpatterns = [
path("", views.UnassignedDevicesView.as_view(), name="unassigned_devices"),
path("all/", views.AllDevicesView.as_view(), name="all_devices"),
path("<int:pk>/", views.LotDashboardView.as_view(), name="lot"),
]

View file

@ -17,9 +17,7 @@ class UnassignedDevicesView(InventaryMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
devices = Device.objects.filter(
owner=self.request.user
).annotate(num_lots=Count('lot')).filter(num_lots=0)
devices = Device.get_unassigned(self.request.user)
context.update({
'devices': devices,
@ -28,32 +26,21 @@ class UnassignedDevicesView(InventaryMixin):
return context
class AllDevicesView(InventaryMixin):
template_name = "unassigned_devices.html"
section = "All"
title = _("All Devices")
breadcrumb = "Devices / All Devices"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
devices = Device.objects.filter(owner=self.request.user)
context.update({
'devices': devices,
})
return context
class LotDashboardView(InventaryMixin, DetailsMixin):
template_name = "unassigned_devices.html"
section = "Unassigned"
section = "dashboard_lot"
title = _("Lot Devices")
breadcrumb = "Devices / Lot Devices"
breadcrumb = "Lot / Devices"
model = Lot
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
devices = self.object.devices.filter(owner=self.request.user)
devices = self.get_devices()
context.update({
'devices': devices,
})
return context
def get_devices(self):
chids = self.object.devicelot_set.all().values_list("device_id", flat=True).distinct()
return [Device(id=x) for x in chids]

View file

@ -1,3 +1,17 @@
from django import forms
from snapshot.models import Annotation
class DeviceForm2(forms.ModelForm):
class Meta:
model = Annotation
fields = ['key', 'value']
class DeviceForm(forms.Form):
name = forms.CharField()
value = forms.CharField()
DeviceFormSet = forms.formset_factory(form=DeviceForm, extra=1)

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2024-07-18 17:30
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("device", "0003_device_manufacturer"),
("lot", "0002_remove_lot_devices_devicelot"),
("snapshot", "0002_remove_annotation_device"),
]
operations = [
migrations.DeleteModel(
name="Device",
),
]

View file

@ -3,9 +3,10 @@ from django.db import models
from utils.constants import STR_SM_SIZE, STR_SIZE, STR_EXTEND_SIZE, ALGOS
from snapshot.models import Annotation, Snapshot
from user.models import User
from lot.models import DeviceLot
class Device(models.Model):
class Device:
class Types(models.TextChoices):
DESKTOP = "Desktop"
LAPTOP = "Laptop"
@ -22,17 +23,18 @@ class Device(models.Model):
BATTERY = "Battery"
CAMERA = "Camera"
owner = models.ForeignKey(User, on_delete=models.CASCADE)
type = models.CharField(max_length=STR_SIZE, blank=True, null=True)
manufacturer = models.CharField(max_length=STR_EXTEND_SIZE, blank=True, null=True)
model = models.CharField(max_length=STR_EXTEND_SIZE, blank=True, null=True)
def __init__(self, *args, **kwargs):
# the id is the chid of the device
self.id = kwargs["id"]
self.pk = self.id
self.algorithm = None
self.owner = None
self.annotations = []
self.hids = []
self.uuids = []
self.snapshots = []
super().__init__(*args, **kwargs)
self.last_snapshot = None
self.get_last_snapshot()
def initial(self):
self.get_annotations()
@ -41,21 +43,29 @@ class Device(models.Model):
self.get_snapshots()
def get_annotations(self):
if self.annotations:
return self.annotations
self.annotations = Annotation.objects.filter(
device=self,
owner=self.owner
type=Annotation.Type.SYSTEM,
value=self.id
).order_by("-created")
if self.annotations.count():
self.algorithm = self.annotations[0].key
self.owner = self.annotations[0].owner
return self.annotations
def get_uuids(self):
for a in self.annotations:
for a in self.get_annotations():
if not a.uuid in self.uuids:
self.uuids.append(a.uuid)
def get_hids(self):
if not self.annotations:
self.get_annotations()
annotations = self.get_annotations()
self.hids = self.annotations.filter(
self.hids = annotations.filter(
type=Annotation.Type.SYSTEM,
key__in=ALGOS.keys(),
).values_list("value", flat=True)
@ -67,14 +77,47 @@ class Device(models.Model):
self.snapshots = [Snapshot(u) for u in self.uuids]
def get_last_snapshot(self):
if not self.snapshots:
self.get_snapshots()
annotations = self.get_annotations()
if annotations:
annotation = annotations.first()
self.last_snapshot = Snapshot(annotation.uuid)
if self.snapshots:
return self.snapshots[0]
def last_uuid(self):
return self.uuids[0]
@classmethod
def get_unassigned(cls, user):
return cls.objects.filter(
owner=user
).annotate(num_lots=models.Count('lot')).filter(num_lots=0)
chids = DeviceLot.objects.filter(lot__owner=user).values_list("device_id", flat=True).distinct()
annotations = Annotation.objects.filter(
owner=user,
type=Annotation.Type.SYSTEM,
).exclude(value__in=chids).values_list("value", flat=True).distinct()
return [cls(id=x) for x in annotations]
# return cls.objects.filter(
# owner=user
# ).annotate(num_lots=models.Count('lot')).filter(num_lots=0)
@property
def manufacturer(self):
if not self.last_snapshot:
self.get_last_snapshot()
return self.last_snapshot.doc['device']['manufacturer']
@property
def type(self):
if not self.last_snapshot:
self.get_last_snapshot()
return self.last_snapshot.doc['device']['type']
@property
def model(self):
if not self.last_snapshot:
self.get_last_snapshot()
return self.last_snapshot.doc['device']['model']
@property
def type(self):
if not self.last_snapshot:
self.get_last_snapshot()
return self.last_snapshot.doc['device']['type']

View file

@ -26,9 +26,6 @@
<li class="nav-items">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
</li>
<li class="nav-items">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceabiliy">Traceability log</button>
</li>
<li class="nav-items">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#snapshots">Snapshots</button>
</li>
@ -47,7 +44,6 @@
(<a href="{% url 'device:edit' object.id %}">Edit Device</a>)
</div>
<div class="col-lg-9 col-md-8">
{% if object.hid %}Snapshot{% else %}Placeholder{% endif %}
</div>
</div>
@ -56,29 +52,24 @@
<div class="col-lg-9 col-md-8">{{ object.id }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label ">Id device internal</div>
<div class="col-lg-9 col-md-8"></div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label ">Type</div>
<div class="col-lg-9 col-md-8">{{ snapshot.doc.device.type }}</div>
<div class="col-lg-9 col-md-8">{{ object.type }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
<div class="col-lg-9 col-md-8">{{ snapshot.doc.device.manufacturer|default:"" }}</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">{{ snapshot.doc.device.model|default:"" }}</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">{{ snapshot.doc.device.serialNumber|default:"" }}</div>
<div class="col-lg-9 col-md-8">{{ object.last_snapshot.doc.device.serialNumber|default:"" }}</div>
</div>
<div class="row">
<div class="col-lg-3 col-md-4 label">Identifiers</div>
@ -132,7 +123,7 @@
{% for tag in lot_tags %}
<h5 class="card-title">{{ tag }}</h5>
{% for lot in object.lot_set.filter %}
{% for lot in tag.lot_set.filter %}
{% if lot.type == tag %}
<div class="row">
<div class="col">
@ -171,32 +162,10 @@
</table>
</div>
<div class="tab-pane fade profile-overview" id="traceability">
<h5 class="card-title">Traceability log Details</h5>
<div class="list-group col-6">
<div class="list-group-item d-flex justify-content-between align-items-center">
Snapshot ✓
<small class="text-muted">14:07 23-06-2024</small>
</div>
<div class="list-group-item d-flex justify-content-between align-items-center">
EraseCrypto ✓
<small class="text-muted">14:07 23-06-2024</small>
</div>
<div class="list-group-item d-flex justify-content-between align-items-center">
EraseCrypto ✓
<small class="text-muted">14:07 23-06-2024</small>
</div>
</div>
</div>
<div class="tab-pane fade profile-overview" id="components">
<h5 class="card-title">Components last snapshot</h5>
<div class="list-group col-6">
{% for c in snapshot.components %}
{% for c in object.last_snapshot.doc.components %}
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ c.type }}</h5>

View file

@ -22,11 +22,34 @@
</div>
</div>
{% endif %}
{% bootstrap_form form %}
{# bootstrap_form form #}
<div class="form-actions-no-box">
<a class="btn btn-grey" href="{% url 'dashboard:unassigned_devices' %}">{% translate "Cancel" %}</a>
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
</div>
</form>
<script>
function addForm(button) {
var formCount = parseInt(document.getElementById('id_form-TOTAL_FORMS').value);
var formCopy = document.querySelector('.dynamic-form').cloneNode(true);
formCopy.style.display = 'block';
formCopy.innerHTML = formCopy.innerHTML.replace(/__prefix__/g, formCount);
document.getElementById('formset-container').appendChild(formCopy);
document.getElementById('id_form-TOTAL_FORMS').value = formCount + 1;
}
</script>
<form method="post">
{% csrf_token %}
<div id="formset-container">
{% for f in form %}
<div class="dynamic-form" style="display: {% if forloop.first %}block{% else %}none{% endif %};">
{{ f.as_p }}
</div>
{% endfor %}
</div>
<button type="button" onclick="addForm(this);">Add</button>
<button type="submit">Submit</button>
</form>
{% endblock %}

View file

@ -5,7 +5,7 @@ app_name = 'device'
urlpatterns = [
path("add/", views.NewDeviceView.as_view(), name="add"),
path("edit/<int:pk>/", views.EditDeviceView.as_view(), name="edit"),
path("<int:pk>/", views.DetailsView.as_view(), name="details"),
path("<int:pk>/annotation/add", views.AddAnnotationView.as_view(), name="add_annotation"),
path("edit/<str:pk>/", views.EditDeviceView.as_view(), name="edit"),
path("<str:pk>/", views.DetailsView.as_view(), name="details"),
path("<str:pk>/annotation/add", views.AddAnnotationView.as_view(), name="add_annotation"),
]

View file

@ -6,21 +6,23 @@ from django.utils.translation import gettext_lazy as _
from django.views.generic.edit import (
CreateView,
UpdateView,
FormView,
)
from django.views.generic.base import TemplateView
from dashboard.mixins import DashboardView, DetailsMixin
from dashboard.mixins import DashboardView
from snapshot.models import Annotation
from snapshot.xapian import search
from lot.models import LotTag
from device.models import Device
from device.forms import DeviceFormSet
class NewDeviceView(DashboardView, CreateView):
class NewDeviceView(DashboardView, FormView):
template_name = "new_device.html"
title = _("New Device")
breadcrumb = "Device / New Device"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = Device
form_class = DeviceFormSet
def form_valid(self, form):
form.instance.owner = self.request.user
@ -28,12 +30,41 @@ class NewDeviceView(DashboardView, CreateView):
return response
# class AddToLotView(DashboardView, FormView):
# template_name = "list_lots.html"
# title = _("Add to lots")
# breadcrumb = "lot / add to lots"
# success_url = reverse_lazy('dashboard:unassigned_devices')
# form_class = LotsForm
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# lots = Lot.objects.filter(owner=self.request.user)
# lot_tags = LotTag.objects.filter(owner=self.request.user)
# context.update({
# 'lots': lots,
# 'lot_tags':lot_tags,
# })
# return context
# def get_form(self):
# form = super().get_form()
# form.fields["lots"].queryset = Lot.objects.filter(owner=self.request.user)
# return form
# def form_valid(self, form):
# form.devices = self.get_session_devices()
# form.save()
# response = super().form_valid(form)
# return response
class EditDeviceView(DashboardView, UpdateView):
template_name = "new_device.html"
title = _("Update Device")
breadcrumb = "Device / Update Device"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = Device
model = Annotation
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
@ -43,17 +74,23 @@ class EditDeviceView(DashboardView, UpdateView):
return kwargs
class DetailsView(DetailsMixin):
class DetailsView(DashboardView, TemplateView):
template_name = "details.html"
title = _("Device")
breadcrumb = "Device / Details"
model = Device
model = Annotation
def get(self, request, *args, **kwargs):
self.pk = kwargs['pk']
self.object = Device(id=self.pk)
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
self.object.initial()
lot_tags = LotTag.objects.filter(owner=self.request.user)
context.update({
'object': self.object,
'snapshot': self.object.get_last_snapshot(),
'lot_tags': lot_tags,
})

View file

@ -15,13 +15,14 @@ class LotsForm(forms.Form):
def save(self, commit=True):
if not commit:
return
for dev in self.devices:
for lot in self._lots:
lot.devices.add(dev.id)
lot.add(dev.id)
return
def remove(self):
for dev in self.devices:
for lot in self._lots:
lot.devices.remove(dev.id)
lot.remove(dev.id)
return

View file

@ -0,0 +1,39 @@
# Generated by Django 5.0.6 on 2024-07-18 17:30
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("lot", "0001_initial"),
]
operations = [
migrations.RemoveField(
model_name="lot",
name="devices",
),
migrations.CreateModel(
name="DeviceLot",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("device_id", models.CharField(max_length=256)),
(
"lot",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="lot.lot"
),
),
],
),
]

View file

@ -7,7 +7,7 @@ from utils.constants import (
)
from user.models import User
from device.models import Device
# from device.models import Device
from snapshot.models import Annotation
@ -19,6 +19,11 @@ class LotTag(models.Model):
return self.name
class DeviceLot(models.Model):
lot = models.ForeignKey("Lot", on_delete=models.CASCADE)
device_id = models.CharField(max_length=STR_EXTEND_SIZE, blank=False, null=False)
class Lot(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
@ -28,4 +33,13 @@ class Lot(models.Model):
closed = models.BooleanField(default=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
type = models.ForeignKey(LotTag, on_delete=models.CASCADE)
devices = models.ManyToManyField(Device)
def add(self, v):
if DeviceLot.objects.filter(lot=self, device_id=v).exists():
return
DeviceLot.objects.create(lot=self, device_id=v)
def remove(self, v):
for d in DeviceLot.objects.filter(lot=self, device_id=v):
d.delete()

View file

@ -6,7 +6,7 @@ from django.views.generic.edit import (
CreateView,
DeleteView,
UpdateView,
FormView
FormView,
)
from dashboard.mixins import DashboardView
from lot.models import Lot, LotTag

View file

@ -0,0 +1,17 @@
# Generated by Django 5.0.6 on 2024-07-18 17:30
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("snapshot", "0001_initial"),
]
operations = [
migrations.RemoveField(
model_name="annotation",
name="device",
),
]

View file

@ -63,7 +63,6 @@ class Annotation(models.Model):
type = models.SmallIntegerField(choices=Type)
key = models.CharField(max_length=STR_EXTEND_SIZE)
value = models.CharField(max_length=STR_EXTEND_SIZE)
device = models.ForeignKey('device.Device', on_delete=models.CASCADE)
class Meta:
constraints = [

View file

@ -7,7 +7,6 @@ import hashlib
from datetime import datetime
from snapshot.xapian import search, index
from snapshot.models import Snapshot, Annotation
from device.models import Device
from utils.constants import ALGOS
@ -47,21 +46,10 @@ class Build:
value = algorithms['hidalgo1']
).first()
if annotation:
device = annotation.device
else:
device = Device.objects.create(
type=self.json["device"]["type"],
manufacturer=self.json["device"]["manufacturer"],
model=self.json["device"]["model"],
owner=self.user
)
for k, v in algorithms.items():
Annotation.objects.create(
uuid=self.uuid,
owner=self.user,
device=device,
type=Annotation.Type.SYSTEM,
key=k,
value=v

View file

@ -1,10 +1,10 @@
from django.utils.translation import gettext_lazy as _
from django.views.generic.base import TemplateView
from django.views.generic.edit import FormView
from django.urls import reverse_lazy
from django.views.generic.edit import (
CreateView,
UpdateView,
FormView,
)
from dashboard.mixins import DashboardView