new structure
This commit is contained in:
parent
e135fd9d28
commit
b1440fddfa
|
@ -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 lot.models import LotTag
|
||||
|
||||
|
||||
class Http403(PermissionDenied):
|
||||
|
@ -37,6 +38,7 @@ class DashboardView(LoginRequiredMixin):
|
|||
'section': self.section,
|
||||
'path': resolve(self.request.path).url_name,
|
||||
'user': self.request.user,
|
||||
'lot_tags': LotTag.objects.filter(owner=self.request.user)
|
||||
})
|
||||
return context
|
||||
|
||||
|
|
|
@ -103,21 +103,13 @@
|
|||
{% trans 'Lots' %}
|
||||
</a>
|
||||
<ul class="flex-column mb-2 ul_sidebar accordion-collapse {% if section == 'People' %}expanded{% else %}collapse{% endif %}" id="ul_lots" data-bs-parent="#sidebarMenu">
|
||||
{% for tag in lot_tags %}
|
||||
<li class="nav-items">
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{% url 'lot:lots_incoming' %}">
|
||||
{% trans 'Incoming ' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{% url 'lot:lots_outgoing' %}">
|
||||
{% trans 'Outgoing ' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if path == 'admin_people_new' %} active2{% endif %}" href="{% url 'lot:lots_temporal' %}">
|
||||
{% trans 'Temporal ' %}
|
||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{% url 'lot:tag' tag.id %}">
|
||||
{{ tag.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
|
|
|
@ -6,7 +6,7 @@ from dashboard.mixins import InventaryMixin, DetailsMixin
|
|||
from device.models import Device
|
||||
from snapshot.xapian import search
|
||||
from snapshot.models import Annotation
|
||||
from lot.models import Lot
|
||||
from lot.models import Lot, LotTag
|
||||
|
||||
|
||||
class UnassignedDevicesView(InventaryMixin):
|
||||
|
@ -17,30 +17,14 @@ class UnassignedDevicesView(InventaryMixin):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
annotations = Annotation.objects.filter(
|
||||
owner=self.request.user).filter(
|
||||
key="hidalgo1").order_by('created')
|
||||
# 'created').distinct('value')
|
||||
# ).annotate(num_lots=Count('lot')).filter(num_lots=0)
|
||||
|
||||
hids = {}
|
||||
ids = []
|
||||
for x in annotations:
|
||||
if not hids.get(x.key):
|
||||
hids[x.key] = x.uuid
|
||||
ids.append(str(x.uuid))
|
||||
|
||||
devices = []
|
||||
for xa in search(ids):
|
||||
# import pdb; pdb.set_trace()
|
||||
snap = json.loads(xa.document.get_data())
|
||||
dev = snap.get("device", {})
|
||||
dev["id"] = snap["uuid"]
|
||||
devices.append(dev)
|
||||
devices = Device.objects.filter(
|
||||
owner=self.request.user
|
||||
).annotate(num_lots=Count('lot')).filter(num_lots=0)
|
||||
|
||||
context.update({
|
||||
'devices': devices
|
||||
'devices': devices,
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 5.0.6 on 2024-06-11 09:20
|
||||
# Generated by Django 5.0.6 on 2024-07-17 14:57
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
@ -26,31 +26,7 @@ class Migration(migrations.Migration):
|
|||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("updated", models.DateTimeField(auto_now=True)),
|
||||
("type", models.CharField(max_length=32)),
|
||||
("model", models.CharField(blank=True, max_length=64, null=True)),
|
||||
(
|
||||
"manufacturer",
|
||||
models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
(
|
||||
"serial_number",
|
||||
models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
("part_number", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("brand", models.TextField(blank=True, null=True)),
|
||||
("generation", models.SmallIntegerField(blank=True, null=True)),
|
||||
("version", models.TextField(blank=True, null=True)),
|
||||
("production_date", models.DateTimeField(blank=True, null=True)),
|
||||
("variant", models.TextField(blank=True, null=True)),
|
||||
("devicehub_id", models.TextField(blank=True, null=True, unique=True)),
|
||||
("dhid_bk", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("phid_bk", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("family", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("hid", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("chid", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("active", models.BooleanField(default=True)),
|
||||
("type", models.CharField(blank=True, max_length=64, null=True)),
|
||||
(
|
||||
"owner",
|
||||
models.ForeignKey(
|
||||
|
@ -60,345 +36,4 @@ class Migration(migrations.Migration):
|
|||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Component",
|
||||
fields=[
|
||||
(
|
||||
"device",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="device.device",
|
||||
),
|
||||
),
|
||||
(
|
||||
"type",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("GraphicCard", "Graphiccard"),
|
||||
("DataStorage", "Datastorage"),
|
||||
("Motherboard", "Motherboard"),
|
||||
("NetworkAdapter", "Networkadapter"),
|
||||
("Processor", "Processor"),
|
||||
("RamModule", "Rammodule"),
|
||||
("SoundCard", "Soundcard"),
|
||||
("Display", "Display"),
|
||||
("Battery", "Battery"),
|
||||
("Camera", "Camera"),
|
||||
],
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Computer",
|
||||
fields=[
|
||||
(
|
||||
"device",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="device.device",
|
||||
),
|
||||
),
|
||||
("chassis", models.TextField(blank=True, null=True)),
|
||||
("system_uuid", models.UUIDField()),
|
||||
("sku", models.TextField(blank=True, null=True)),
|
||||
(
|
||||
"type",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("Desktop", "Desktop"),
|
||||
("Laptop", "Laptop"),
|
||||
("Server", "Server"),
|
||||
],
|
||||
default="Laptop",
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="PhysicalProperties",
|
||||
fields=[
|
||||
(
|
||||
"device",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="device.device",
|
||||
),
|
||||
),
|
||||
("weight", models.FloatField(blank=True, null=True)),
|
||||
("width", models.FloatField(blank=True, null=True)),
|
||||
("height", models.FloatField(blank=True, null=True)),
|
||||
("depth", models.FloatField(blank=True, null=True)),
|
||||
("color", models.CharField(blank=True, max_length=20, null=True)),
|
||||
("image", models.CharField(blank=True, max_length=64, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SoundCard",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="RamModule",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("size", models.IntegerField(blank=True, null=True)),
|
||||
("speed", models.SmallIntegerField(blank=True, null=True)),
|
||||
(
|
||||
"interface",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("SDRAM", "Sdram"),
|
||||
("DDR SDRAM", "Ddr"),
|
||||
("DDR2 SDRAM", "Ddr2"),
|
||||
("DDR3 SDRAM", "Ddr3"),
|
||||
("DDR4 SDRAM", "Ddr4"),
|
||||
("DDR5 SDRAM", "Ddr5"),
|
||||
("DDR6 SDRAM", "Ddr6"),
|
||||
("LPDDR3", "Lpddr3"),
|
||||
],
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
(
|
||||
"format",
|
||||
models.CharField(
|
||||
choices=[("DIMM", "Dimm"), ("SODIMM", "Sodimm")], max_length=32
|
||||
),
|
||||
),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Processor",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("speed", models.FloatField(blank=True, null=True)),
|
||||
("cores", models.SmallIntegerField(blank=True, null=True)),
|
||||
("threads", models.SmallIntegerField(blank=True, null=True)),
|
||||
("address", models.SmallIntegerField(blank=True, null=True)),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="NetworkAdapter",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("speed", models.IntegerField(blank=True, null=True)),
|
||||
("wireless", models.BooleanField(default=False)),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Motherboard",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("slots", models.SmallIntegerField(blank=True, null=True)),
|
||||
("usb", models.SmallIntegerField(blank=True, null=True)),
|
||||
("firewire", models.SmallIntegerField(blank=True, null=True)),
|
||||
("serial", models.SmallIntegerField(blank=True, null=True)),
|
||||
("pcmcia", models.SmallIntegerField(blank=True, null=True)),
|
||||
("bios_date", models.DateTimeField()),
|
||||
("ram_slots", models.SmallIntegerField(blank=True, null=True)),
|
||||
("ram_max_size", models.IntegerField(blank=True, null=True)),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="GraphicCard",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("memory", models.IntegerField(blank=True, null=True)),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Display",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="DataStorage",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("size", models.IntegerField(blank=True, null=True)),
|
||||
(
|
||||
"interface",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("ATA", "Ata"),
|
||||
("USB", "Usb"),
|
||||
("PCI", "Pci"),
|
||||
("NVME", "Nvme"),
|
||||
],
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
(
|
||||
"type",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("HardDrive", "Harddrive"),
|
||||
("SolidStateDrive", "Solidstatedrive"),
|
||||
],
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Battery",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"component",
|
||||
models.OneToOneField(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.component",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="component",
|
||||
name="computer",
|
||||
field=models.OneToOneField(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.computer",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-03 11:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="brand",
|
||||
field=models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="devicehub_id",
|
||||
field=models.CharField(blank=True, max_length=64, null=True, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="variant",
|
||||
field=models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="version",
|
||||
field=models.CharField(blank=True, max_length=64, null=True),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-18 09:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="device",
|
||||
name="model",
|
||||
field=models.CharField(blank=True, max_length=256, null=True),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-18 09:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0002_device_model"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="device",
|
||||
name="manufacturer",
|
||||
field=models.CharField(blank=True, max_length=256, null=True),
|
||||
),
|
||||
]
|
|
@ -1,73 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-03 12:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0002_alter_device_brand_alter_device_devicehub_id_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="component",
|
||||
name="type",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="computer",
|
||||
name="type",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="datastorage",
|
||||
name="type",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="computer",
|
||||
name="chassis",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("Tower", "Tower"),
|
||||
("All in one", "Allinone"),
|
||||
("Microtower", "Microtower"),
|
||||
("Netbook", "Netbook"),
|
||||
("Laptop", "Laptop"),
|
||||
("Tablet", "Tabler"),
|
||||
("Server", "Server"),
|
||||
("Non-physical device", "Virtual"),
|
||||
],
|
||||
max_length=32,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="computer",
|
||||
name="sku",
|
||||
field=models.CharField(blank=True, max_length=32, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="device",
|
||||
name="type",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("Desktop", "Desktop"),
|
||||
("Laptop", "Laptop"),
|
||||
("Server", "Server"),
|
||||
("GraphicCard", "Graphiccard"),
|
||||
("HardDrive", "Harddrive"),
|
||||
("SolidStateDrive", "Solidstatedrive"),
|
||||
("Motherboard", "Motherboard"),
|
||||
("NetworkAdapter", "Networkadapter"),
|
||||
("Processor", "Processor"),
|
||||
("RamModule", "Rammodule"),
|
||||
("SoundCard", "Soundcard"),
|
||||
("Display", "Display"),
|
||||
("Battery", "Battery"),
|
||||
("Camera", "Camera"),
|
||||
],
|
||||
default="Laptop",
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,46 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-11 13:58
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("device", "0003_remove_component_type_remove_computer_type_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="device",
|
||||
name="dhid_bk",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="device",
|
||||
name="phid_bk",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="computer",
|
||||
name="erasure_server",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="device",
|
||||
name="reliable",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="component",
|
||||
name="computer",
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.computer",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="computer",
|
||||
name="system_uuid",
|
||||
field=models.UUIDField(blank=True, null=True),
|
||||
),
|
||||
]
|
188
device/models.py
188
device/models.py
|
@ -1,6 +1,8 @@
|
|||
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 utils.constants import STR_SM_SIZE, STR_SIZE
|
||||
|
||||
|
||||
class Device(models.Model):
|
||||
|
@ -20,155 +22,59 @@ class Device(models.Model):
|
|||
BATTERY = "Battery"
|
||||
CAMERA = "Camera"
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Types, default=Types.LAPTOP)
|
||||
model = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
manufacturer = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
serial_number = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
part_number = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
brand = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
generation = models.SmallIntegerField(blank=True, null=True)
|
||||
version = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
production_date = models.DateTimeField(blank=True, null=True)
|
||||
variant = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
devicehub_id = models.CharField(max_length=STR_SIZE, unique=True, blank=True, null=True)
|
||||
family = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
hid = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
chid = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
active = models.BooleanField(default=True)
|
||||
reliable = models.BooleanField(default=True)
|
||||
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 has_physical_properties(self):
|
||||
try:
|
||||
if self.physicalproperties:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.annotations = []
|
||||
self.hids = []
|
||||
self.uuids = []
|
||||
self.snapshots = []
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def initial(self):
|
||||
self.get_annotations()
|
||||
self.get_uuids()
|
||||
self.get_hids()
|
||||
self.get_snapshots()
|
||||
|
||||
class PhysicalProperties(models.Model):
|
||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
||||
weight = models.FloatField(blank=True, null=True)
|
||||
width = models.FloatField(blank=True, null=True)
|
||||
height = models.FloatField(blank=True, null=True)
|
||||
depth = models.FloatField(blank=True, null=True)
|
||||
color = models.CharField(max_length=20, blank=True, null=True)
|
||||
image = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
def get_annotations(self):
|
||||
self.annotations = Annotation.objects.filter(
|
||||
device=self,
|
||||
owner=self.owner
|
||||
).order_by("-created")
|
||||
|
||||
def get_uuids(self):
|
||||
for a in self.annotations:
|
||||
if not a.uuid in self.uuids:
|
||||
self.uuids.append(a.uuid)
|
||||
|
||||
class Computer(models.Model):
|
||||
class Chassis(models.TextChoices):
|
||||
TOWER = 'Tower'
|
||||
ALLINONE = 'All in one'
|
||||
MICROTOWER = 'Microtower'
|
||||
NETBOOK = 'Netbook'
|
||||
LAPTOP = 'Laptop'
|
||||
TABLER = 'Tablet'
|
||||
SERVER = "Server"
|
||||
VIRTUAL = 'Non-physical device'
|
||||
def get_hids(self):
|
||||
if not self.annotations:
|
||||
self.get_annotations()
|
||||
|
||||
self.hids = self.annotations.filter(
|
||||
type=Annotation.Type.SYSTEM,
|
||||
key__in=ALGOS.keys(),
|
||||
).values_list("value", flat=True)
|
||||
|
||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
||||
chassis = models.CharField(
|
||||
blank=True,
|
||||
null=True,
|
||||
max_length=STR_SM_SIZE,
|
||||
choices=Chassis
|
||||
)
|
||||
system_uuid = models.UUIDField(blank=True, null=True)
|
||||
sku = models.CharField(max_length=STR_SM_SIZE, blank=True, null=True)
|
||||
erasure_server = models.BooleanField(default=False)
|
||||
def get_snapshots(self):
|
||||
if not self.uuids:
|
||||
self.get_uuids()
|
||||
|
||||
self.snapshots = [Snapshot(u) for u in self.uuids]
|
||||
|
||||
class Component(models.Model):
|
||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
||||
computer = models.ForeignKey(Computer, on_delete=models.CASCADE, null=True)
|
||||
def get_last_snapshot(self):
|
||||
if not self.snapshots:
|
||||
self.get_snapshots()
|
||||
|
||||
if self.snapshots:
|
||||
return self.snapshots[0]
|
||||
|
||||
class GraphicCard(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
memory = models.IntegerField(blank=True, null=True)
|
||||
|
||||
|
||||
class DataStorage(models.Model):
|
||||
class Interface(models.TextChoices):
|
||||
ATA = 'ATA'
|
||||
USB = 'USB'
|
||||
PCI = 'PCI'
|
||||
NVME = 'NVME'
|
||||
|
||||
size = models.IntegerField(blank=True, null=True)
|
||||
interface = models.CharField(max_length=STR_SM_SIZE, choices=Interface)
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
|
||||
|
||||
class Motherboard(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
slots = models.SmallIntegerField(blank=True, null=True)
|
||||
usb = models.SmallIntegerField(blank=True, null=True)
|
||||
firewire = models.SmallIntegerField(blank=True, null=True)
|
||||
serial = models.SmallIntegerField(blank=True, null=True)
|
||||
pcmcia = models.SmallIntegerField(blank=True, null=True)
|
||||
bios_date = models.DateTimeField()
|
||||
ram_slots = models.SmallIntegerField(blank=True, null=True)
|
||||
ram_max_size = models.IntegerField(blank=True, null=True)
|
||||
|
||||
|
||||
class NetworkAdapter(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
speed = models.IntegerField(blank=True, null=True)
|
||||
wireless = models.BooleanField(default=False)
|
||||
|
||||
def __format__(self, format_spec):
|
||||
v = super().__format__(format_spec)
|
||||
if 's' in format_spec:
|
||||
v += ' – {} Mbps'.format(self.speed)
|
||||
return v
|
||||
|
||||
|
||||
class Processor(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
speed = models.FloatField(blank=True, null=True)
|
||||
cores = models.SmallIntegerField(blank=True, null=True)
|
||||
threads = models.SmallIntegerField(blank=True, null=True)
|
||||
address = models.SmallIntegerField(blank=True, null=True)
|
||||
|
||||
|
||||
class RamModule(models.Model):
|
||||
class Interface(models.TextChoices):
|
||||
SDRAM = 'SDRAM'
|
||||
DDR = 'DDR SDRAM'
|
||||
DDR2 = 'DDR2 SDRAM'
|
||||
DDR3 = 'DDR3 SDRAM'
|
||||
DDR4 = 'DDR4 SDRAM'
|
||||
DDR5 = 'DDR5 SDRAM'
|
||||
DDR6 = 'DDR6 SDRAM'
|
||||
LPDDR3 = 'LPDDR3'
|
||||
|
||||
class Format(models.TextChoices):
|
||||
DIMM = 'DIMM'
|
||||
SODIMM = 'SODIMM'
|
||||
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
size = models.IntegerField(blank=True, null=True)
|
||||
interface = models.CharField(max_length=STR_SM_SIZE, choices=Interface)
|
||||
speed = models.SmallIntegerField(blank=True, null=True)
|
||||
interface = models.CharField(max_length=STR_SM_SIZE, choices=Interface)
|
||||
format = models.CharField(max_length=STR_SM_SIZE, choices=Format)
|
||||
|
||||
|
||||
class SoundCard(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
|
||||
|
||||
class Display(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
|
||||
|
||||
class Battery(models.Model):
|
||||
component = models.OneToOneField(Component, models.CASCADE)
|
||||
|
||||
@classmethod
|
||||
def get_unassigned(cls, user):
|
||||
return cls.objects.filter(
|
||||
owner=user
|
||||
).annotate(num_lots=models.Count('lot')).filter(num_lots=0)
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ object.uuid }}</h3>
|
||||
<h3>{{ object.id }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="nav nav-tabs nav-tabs-bordered">
|
||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||
<li class="nav-items">
|
||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">General details</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#physicalproperties">Physical properties</button>
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#annotations">User annotations</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</button>
|
||||
|
@ -23,20 +23,19 @@
|
|||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</button>
|
||||
</li>
|
||||
<li class="nav-items">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#status">Status</button>
|
||||
</li>
|
||||
<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>
|
||||
<li class="nav-items">
|
||||
<a class="nav-link" href="">Web</a>
|
||||
</li>
|
||||
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content pt-2">
|
||||
|
@ -45,7 +44,7 @@
|
|||
<h5 class="card-title">Details</h5>
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
(<a href="{% url 'device:edit' object.uuid %}">Edit Device</a>)
|
||||
(<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 %}
|
||||
|
@ -54,7 +53,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.uuid }}</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.id }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
@ -64,101 +63,85 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Type</div>
|
||||
<div class="col-lg-9 col-md-8">{{ object.type }}</div>
|
||||
<div class="col-lg-9 col-md-8">{{ snapshot.doc.device.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">{{ object.device.manufacturer|default:"" }}</div>
|
||||
<div class="col-lg-9 col-md-8">{{ snapshot.doc.device.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.device.model|default:"" }}</div>
|
||||
<div class="col-lg-9 col-md-8">{{ snapshot.doc.device.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.device.serialNumber|default:"" }}</div>
|
||||
<div class="col-lg-9 col-md-8">{{ snapshot.doc.device.serialNumber|default:"" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="physicalproperties">
|
||||
<h5 class="card-title">Physical Properties</h5>
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
(<a href="{% url 'device:physical_edit' object.uuid %}">Edit Physical Properties</a>)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if object.has_physical_properties %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">
|
||||
Weight:
|
||||
<div class="col-lg-3 col-md-4 label">Identifiers</div>
|
||||
</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{{ object.physicalproperties.weight }}
|
||||
{% for chid in object.hids %}
|
||||
<div class="row">
|
||||
<div class="col">{{ chid |default:"" }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">width:</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{{ object.physicalproperties.width }}
|
||||
</div>
|
||||
<div class="tab-pane fade profile-overview" id="annotations">
|
||||
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||
<a href="{% url 'device:add_annotation' object.pk %}" class="btn btn-primary">
|
||||
<i class="bi bi-plus"></i>
|
||||
Add new annotation
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">height:</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{{ object.physicalproperties.height }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">depth:</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{{ object.physicalproperties.depth }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">color:</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{{ object.physicalproperties.color }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">image:</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
{% if object.physicalproperties.image %}
|
||||
<img width="200px" src="{{ object.physicalproperties.image }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="card-title">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.annotations %}
|
||||
{% if a.is_user_annotation %}
|
||||
<tr>
|
||||
<td>{{ a.key }}</td>
|
||||
<td>{{ a.value }}</td>
|
||||
<td>{{ a.created }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="lots">
|
||||
<h5 class="card-title">Incoming Lots</h5>
|
||||
{% for tag in lot_tags %}
|
||||
<h5 class="card-title">{{ tag }}</h5>
|
||||
|
||||
{% for lot in object.lot_set.filter %}
|
||||
{% if lot.type == tag %}
|
||||
<div class="row">
|
||||
|
||||
<div class="col">
|
||||
<a href="{% url 'dashboard:lot' lot.id %}">{{ lot.name }}</a>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Outgoing Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Temporary Lots</h5>
|
||||
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="documents">
|
||||
|
@ -188,28 +171,6 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="status">
|
||||
<h5 class="card-title">Status Details</h5>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Physical State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Lifecycle State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label">Allocated State</div>
|
||||
<div class="col-lg-9 col-md-8">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="traceability">
|
||||
<h5 class="card-title">Traceability log Details</h5>
|
||||
<div class="list-group col-6">
|
||||
|
@ -233,35 +194,42 @@
|
|||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="components">
|
||||
<h5 class="card-title">Components Snapshot</h5>
|
||||
<h5 class="card-title">Components last snapshot</h5>
|
||||
<div class="list-group col-6">
|
||||
|
||||
{% for c in snapshot.components %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">Motherboard</h5>
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
<h5 class="mb-1">{{ c.type }}</h5>
|
||||
<small class="text-muted">{{ snapshot.created }}</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
hp<br />
|
||||
890e<br />
|
||||
{{ c.manufacturer }}<br />
|
||||
{{ c.model }}<br />
|
||||
{{ c.serialNumber }}<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
</small>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade profile-overview" id="snapshots">
|
||||
<h5 class="card-title">List of snapshots</h5>
|
||||
<div class="list-group col-6">
|
||||
{% for snap in object.snapshots %}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">NetworkAdapter</h5>
|
||||
<small class="text-muted">14:07 23-06-2024</small>
|
||||
<h5 class="mb-1"></h5>
|
||||
<small class="text-muted">{{ snap.created }}</small>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
realtek semiconductor co., ltd.<br />
|
||||
rtl8852ae 802.11ax pcie wireless network adapter<br />
|
||||
{{ snap.uuid }}<br />
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
</small>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ app_name = 'device'
|
|||
|
||||
urlpatterns = [
|
||||
path("add/", views.NewDeviceView.as_view(), name="add"),
|
||||
path("edit/<uuid:pk>/", views.EditDeviceView.as_view(), name="edit"),
|
||||
path("<uuid:pk>/", views.DetailsView.as_view(), name="details"),
|
||||
path("physical/<uuid:pk>/", views.PhysicalView.as_view(), name="physical_edit"),
|
||||
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"),
|
||||
]
|
||||
|
|
100
device/views.py
100
device/views.py
|
@ -11,7 +11,8 @@ from django.views.generic.base import TemplateView
|
|||
from dashboard.mixins import DashboardView, DetailsMixin
|
||||
from snapshot.models import Annotation
|
||||
from snapshot.xapian import search
|
||||
from device.models import Device, PhysicalProperties
|
||||
from lot.models import LotTag
|
||||
from device.models import Device
|
||||
|
||||
|
||||
class NewDeviceView(DashboardView, CreateView):
|
||||
|
@ -20,24 +21,10 @@ class NewDeviceView(DashboardView, CreateView):
|
|||
breadcrumb = "Device / New Device"
|
||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||
model = Device
|
||||
fields = (
|
||||
'type',
|
||||
"model",
|
||||
"manufacturer",
|
||||
"serial_number",
|
||||
"part_number",
|
||||
"brand",
|
||||
"generation",
|
||||
"version",
|
||||
"production_date",
|
||||
"variant",
|
||||
"family",
|
||||
)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.owner = self.request.user
|
||||
response = super().form_valid(form)
|
||||
PhysicalProperties.objects.create(device=form.instance)
|
||||
return response
|
||||
|
||||
|
||||
|
@ -47,19 +34,6 @@ class EditDeviceView(DashboardView, UpdateView):
|
|||
breadcrumb = "Device / Update Device"
|
||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||
model = Device
|
||||
fields = (
|
||||
'type',
|
||||
"model",
|
||||
"manufacturer",
|
||||
"serial_number",
|
||||
"part_number",
|
||||
"brand",
|
||||
"generation",
|
||||
"version",
|
||||
"production_date",
|
||||
"variant",
|
||||
"family",
|
||||
)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
|
@ -69,71 +43,51 @@ class EditDeviceView(DashboardView, UpdateView):
|
|||
return kwargs
|
||||
|
||||
|
||||
class DetailsView2(DetailsMixin):
|
||||
class DetailsView(DetailsMixin):
|
||||
template_name = "details.html"
|
||||
title = _("Device")
|
||||
breadcrumb = "Device / Details"
|
||||
model = Device
|
||||
|
||||
class DetailsView(DashboardView, TemplateView):
|
||||
template_name = "details.html"
|
||||
title = _("Device")
|
||||
breadcrumb = "Device / Details"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
# import pdb; pdb.set_trace()
|
||||
self.pk = kwargs['pk']
|
||||
annotation = get_object_or_404(Annotation, owner=self.request.user, uuid=self.pk)
|
||||
for xa in search([str(self.pk)]):
|
||||
self.object = json.loads(xa.document.get_data())
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
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,
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class PhysicalView(DashboardView, UpdateView):
|
||||
template_name = "physical_properties.html"
|
||||
title = _("Physical Properties")
|
||||
breadcrumb = "Device / Physical properties"
|
||||
class AddAnnotationView(DashboardView, CreateView):
|
||||
template_name = "new_device.html"
|
||||
title = _("New annotation")
|
||||
breadcrumb = "Device / New annotation"
|
||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||
model = PhysicalProperties
|
||||
fields = (
|
||||
"weight",
|
||||
"width",
|
||||
"height",
|
||||
"depth",
|
||||
"color",
|
||||
"image",
|
||||
)
|
||||
model = Annotation
|
||||
fields = ("key", "value")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'device': self.device,
|
||||
})
|
||||
return context
|
||||
def form_valid(self, form):
|
||||
self.device.get_annotations()
|
||||
self.device.get_uuids()
|
||||
form.instance.owner = self.request.user
|
||||
form.instance.device = self.device
|
||||
form.instance.uuid = self.device.uuids[0]
|
||||
form.instance.type = Annotation.Type.USER
|
||||
response = super().form_valid(form)
|
||||
return response
|
||||
|
||||
def get_form_kwargs(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
self.device = get_object_or_404(Device, pk=pk)
|
||||
try:
|
||||
self.object = self.device.physicalproperties
|
||||
except Exception:
|
||||
self.object = PhysicalProperties.objects.create(device=self.device)
|
||||
self.success_url = reverse_lazy('device:details', args=[pk])
|
||||
kwargs = super().get_form_kwargs()
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
self.success_url = reverse_lazy('device:details', args=[self.device.id])
|
||||
response = super().form_valid(form)
|
||||
return response
|
||||
def get_success_url(self):
|
||||
url = super().get_success_url()
|
||||
import pdb; pdb.set_trace()
|
||||
return url
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"type": "Snapshot", "components": [{"type": "SoundCard", "model": "Xeon E3-1200 V3/4th Gen Core Processor Hd Audio Controller", "manufacturer": "Intel Corporation"}, {"type": "SoundCard", "model": "Hp Hd Webcam", "manufacturer": "Chicony Electronics Co.,ltd.", "serialNumber": "200901010001"}, {"type": "SoundCard", "model": "8 Series/c220 Series Chipset High Definition Audio Controller", "manufacturer": "Intel Corporation"}, {"type": "RamModule", "model": "M471b5273ch0-Yk0", "manufacturer": "Samsung", "serialNumber": "96C0FA89", "size": 4096, "speed": 1600, "interface": "DDR3", "format": "SODIMM"}, {"type": "Processor", "actions": [{"type": "BenchmarkProcessor", "elapsed": 0, "rate": 19951.48}, {"type": "BenchmarkProcessorSysbench", "elapsed": 15, "rate": 14.6652}], "model": "Intel Core I5-4200m Cpu @ 2.50ghz", "manufacturer": "Intel Corp.", "brand": "Core i5", "generation": 4, "speed": 2.524414, "cores": 2, "threads": 4, "address": 64}, {"type": "NetworkAdapter", "model": "Ethernet Connection I217-V", "manufacturer": "Intel Corporation", "serialNumber": "FC:15:B4:E7:5D:D7", "variant": "04", "speed": 1000, "wireless": false}, {"type": "NetworkAdapter", "model": "Bcm43228 802.11a/b/g/n", "manufacturer": "Broadcom Inc. and Subsidiaries", "variant": "00", "wireless": false}, {"type": "SolidStateDrive", "actions": [{"type": "BenchmarkDataStorage", "elapsed": 2, "readSpeed": 487, "writeSpeed": 179}], "model": "Emtec X150 120gb", "serialNumber": "LDS645R002202", "variant": "5.0", "size": 120034.123776, "interface": "ATA"}, {"type": "Display", "model": "Lcd Monitor", "manufacturer": "Auo", "productionDate": "2012-01-01T00:00:00", "size": 15.529237982414482, "technology": "LCD", "resolutionWidth": 1366, "resolutionHeight": 768, "refreshRate": 60}, {"type": "GraphicCard", "model": "4th Gen Core Processor Integrated Graphics Controller", "manufacturer": "Intel Corporation"}, {"type": "Motherboard", "model": "1993", "manufacturer": "Hewlett-Packard", "serialNumber": "PEBJK001X5ZI3Z", "version": "L77 Ver. 01.05", "slots": 2, "usb": 3, "firewire": 0, "serial": 1, "pcmcia": 0, "biosDate": "2014-04-28T22:00:00.000Z", "ramSlots": 2, "ramMaxSize": 16}], "device": {"type": "Laptop", "actions": [{"type": "BenchmarkRamSysbench", "elapsed": 1, "rate": 0.731}], "model": "Hp Probook 650 G1", "manufacturer": "Hewlett-Packard", "serialNumber": "CNU406CLGR", "version": "A3009DD10303", "sku": "H5G75EA#ABE", "chassis": "Netbook"}, "closed": true, "endTime": "2022-06-09T12:10:50.809Z", "uuid": "7928afeb-e6a4-464a-a842-0c3de0d01677", "software": "Workbench", "version": "12.0b0", "elapsed": 34}
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-08 13:55
|
||||
# Generated by Django 5.0.6 on 2024-07-17 14:57
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
@ -10,11 +10,33 @@ class Migration(migrations.Migration):
|
|||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("device", "0003_remove_component_type_remove_computer_type_and_more"),
|
||||
("device", "0001_initial"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="LotTag",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=64)),
|
||||
(
|
||||
"owner",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Lot",
|
||||
fields=[
|
||||
|
@ -29,18 +51,6 @@ class Migration(migrations.Migration):
|
|||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("updated", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"type",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("Incoming", "Incoming"),
|
||||
("Outgoing", "Outgoing"),
|
||||
("Temporal", "Temporal"),
|
||||
],
|
||||
default="Temporal",
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
("name", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("code", models.CharField(blank=True, max_length=64, null=True)),
|
||||
("description", models.CharField(blank=True, max_length=64, null=True)),
|
||||
|
@ -53,6 +63,12 @@ class Migration(migrations.Migration):
|
|||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="lot.lottag"
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,41 +1,31 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from utils.constants import STR_SM_SIZE, STR_SIZE
|
||||
from utils.constants import (
|
||||
STR_SM_SIZE,
|
||||
STR_SIZE,
|
||||
STR_EXTEND_SIZE,
|
||||
)
|
||||
|
||||
from user.models import User
|
||||
from device.models import Device
|
||||
from snapshot.models import Annotation
|
||||
|
||||
|
||||
class LotTag(models.Model):
|
||||
name = models.CharField(max_length=STR_SIZE, blank=False, null=False)
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Lot(models.Model):
|
||||
class Types(models.TextChoices):
|
||||
INCOMING = "Incoming"
|
||||
OUTGOING = "Outgoing"
|
||||
TEMPORAL = "Temporal"
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
type = models.CharField(max_length=STR_SM_SIZE, choices=Types, default=Types.TEMPORAL)
|
||||
name = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
code = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
description = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||
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)
|
||||
|
||||
@property
|
||||
def is_incoming(self):
|
||||
if self.type == self.Types.INCOMING:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_outgoing(self):
|
||||
if self.type == self.Types.OUTGOING:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_temporal(self):
|
||||
if self.type == self.Types.TEMPORAL:
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -11,50 +11,21 @@
|
|||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if incoming %}
|
||||
{% for tag in lot_tags %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Incoming Lots</div>
|
||||
<div class="col-lg-3 col-md-4 label ">{{ tag }}</div>
|
||||
</div>
|
||||
|
||||
{% for lot in lots %}
|
||||
{% if lot.is_incoming %}
|
||||
{% if lot.type == tag %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label "><input type="checkbox" name="lots" value="{{ lot.id }}" /></div>
|
||||
<div class="col-lg-3 col-md-4 label ">{{ lot.name }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if outgoing %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Outgoing Lots</div>
|
||||
</div>
|
||||
|
||||
{% for lot in lots %}
|
||||
{% if lot.is_outgoing %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label "><input type="checkbox" name="lots" value="{{ lot.id }}" /></div>
|
||||
<div class="col-lg-3 col-md-4 label ">{{ lot.name }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% if temporal %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label ">Temporary Lots</div>
|
||||
</div>
|
||||
|
||||
{% for lot in lots %}
|
||||
{% if lot.is_temporal %}
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-md-4 label "><input type="checkbox" name="lots" value="{{ lot.id }}" /></div>
|
||||
<div class="col-lg-3 col-md-4 label ">{{ lot.name }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<button type="submit">Save</button>
|
||||
</form>
|
||||
|
||||
|
|
|
@ -9,7 +9,5 @@ urlpatterns = [
|
|||
path("edit/<int:pk>/", views.EditLotView.as_view(), name="edit"),
|
||||
path("add/devices/", views.AddToLotView.as_view(), name="add_devices"),
|
||||
path("del/devices/", views.DelToLotView.as_view(), name="del_devices"),
|
||||
path("temporal/", views.LotsTemporalView.as_view(), name="lots_temporal"),
|
||||
path("outgoing/", views.LotsOutgoingView.as_view(), name="lots_outgoing"),
|
||||
path("incoming/", views.LotsIncomingView.as_view(), name="lots_incoming"),
|
||||
path("tag/<int:pk>/", views.LotsTagsView.as_view(), name="tag"),
|
||||
]
|
||||
|
|
38
lot/views.py
38
lot/views.py
|
@ -9,7 +9,7 @@ from django.views.generic.edit import (
|
|||
FormView
|
||||
)
|
||||
from dashboard.mixins import DashboardView
|
||||
from lot.models import Lot
|
||||
from lot.models import Lot, LotTag
|
||||
from lot.forms import LotsForm
|
||||
|
||||
|
||||
|
@ -84,20 +84,15 @@ class AddToLotView(DashboardView, FormView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
lots = Lot.objects.filter(owner=self.request.user)
|
||||
lots_incoming = lots.filter(type=Lot.Types.INCOMING).exists()
|
||||
lots_outgoing = lots.filter(type=Lot.Types.OUTGOING).exists()
|
||||
lots_temporal = lots.filter(type=Lot.Types.TEMPORAL).exists()
|
||||
lot_tags = LotTag.objects.filter(owner=self.request.user)
|
||||
context.update({
|
||||
'lots': lots,
|
||||
'incoming': lots_incoming,
|
||||
'outgoing': lots_outgoing,
|
||||
'temporal': lots_temporal
|
||||
'lot_tags':lot_tags,
|
||||
})
|
||||
return context
|
||||
|
||||
def get_form(self):
|
||||
form = super().get_form()
|
||||
# import pdb; pdb.set_trace()
|
||||
form.fields["lots"].queryset = Lot.objects.filter(owner=self.request.user)
|
||||
return form
|
||||
|
||||
|
@ -119,28 +114,23 @@ class DelToLotView(AddToLotView):
|
|||
return response
|
||||
|
||||
|
||||
class LotsTemporalView(DashboardView, TemplateView):
|
||||
class LotsTagsView(DashboardView, TemplateView):
|
||||
template_name = "lots.html"
|
||||
title = _("Temporal lots")
|
||||
breadcrumb = "lot / temporal lots"
|
||||
title = _("lots")
|
||||
breadcrumb = _("lots") + " /"
|
||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||
lot_type = Lot.Types.TEMPORAL
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
self.pk = kwargs.get('pk')
|
||||
context = super().get_context_data(**kwargs)
|
||||
lots = Lot.objects.filter(owner=self.request.user)
|
||||
tag = get_object_or_404(LotTag, owner=self.request.user, id=self.pk)
|
||||
self.title += " {}".format(tag.name)
|
||||
self.breadcrumb += " {}".format(tag.name)
|
||||
lots = Lot.objects.filter(owner=self.request.user).filter(type=tag)
|
||||
context.update({
|
||||
'lots': lots.filter(type=self.lot_type),
|
||||
'lots': lots,
|
||||
'title': self.title,
|
||||
'breadcrumb': self.breadcrumb
|
||||
})
|
||||
return context
|
||||
|
||||
class LotsOutgoingView(LotsTemporalView):
|
||||
title = _("Outgoing lots")
|
||||
breadcrumb = "lot / outging lots"
|
||||
lot_type = Lot.Types.OUTGOING
|
||||
|
||||
|
||||
class LotsIncomingView(LotsTemporalView):
|
||||
title = _("Incoming lots")
|
||||
breadcrumb = "lot / Incoming lots"
|
||||
lot_type = Lot.Types.INCOMING
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
rm db/*
|
||||
./manage.py migrate
|
||||
./manage.py add_user user@example.org 1234
|
||||
./manage.py up_snapshots example/ user@example.org
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 5.0.6 on 2024-06-11 09:20
|
||||
# Generated by Django 5.0.6 on 2024-07-17 14:57
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
|||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Snapshot",
|
||||
name="Annotation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
|
@ -28,39 +28,17 @@ class Migration(migrations.Migration):
|
|||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
(
|
||||
"software",
|
||||
models.CharField(
|
||||
choices=[("Workbench", "Workbench")],
|
||||
default="Workbench",
|
||||
max_length=32,
|
||||
),
|
||||
),
|
||||
("uuid", models.UUIDField()),
|
||||
("version", models.CharField(max_length=32)),
|
||||
("sid", models.CharField(max_length=32)),
|
||||
("settings_version", models.CharField(max_length=32)),
|
||||
("is_server_erase", models.BooleanField(default=False)),
|
||||
(
|
||||
"severity",
|
||||
models.SmallIntegerField(
|
||||
choices=[
|
||||
(0, "Info"),
|
||||
(1, "Notice"),
|
||||
(2, "Warning"),
|
||||
(3, "Error"),
|
||||
],
|
||||
default=0,
|
||||
"type",
|
||||
models.SmallIntegerField(choices=[(0, "System"), (1, "User")]),
|
||||
),
|
||||
),
|
||||
("start_time", models.DateTimeField()),
|
||||
("end_time", models.DateTimeField()),
|
||||
("components", models.ManyToManyField(to="device.component")),
|
||||
("key", models.CharField(max_length=256)),
|
||||
("value", models.CharField(max_length=256)),
|
||||
(
|
||||
"computer",
|
||||
"device",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="device.computer",
|
||||
on_delete=django.db.models.deletion.CASCADE, to="device.device"
|
||||
),
|
||||
),
|
||||
(
|
||||
|
@ -72,4 +50,10 @@ class Migration(migrations.Migration):
|
|||
),
|
||||
],
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="annotation",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("type", "key", "uuid"), name="unique_type_key_uuid"
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-11 14:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("snapshot", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="snapshot",
|
||||
name="uuid",
|
||||
field=models.UUIDField(unique=True),
|
||||
),
|
||||
]
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-11 14:18
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("snapshot", "0002_alter_snapshot_uuid"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="snapshot",
|
||||
name="start_time",
|
||||
),
|
||||
]
|
|
@ -1,41 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-15 09:20
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("snapshot", "0003_remove_snapshot_start_time"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="anotation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("uuid", models.UUIDField(unique=True)),
|
||||
("key", models.CharField(max_length=256)),
|
||||
("value", models.CharField(max_length=256)),
|
||||
(
|
||||
"owner",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -1,44 +0,0 @@
|
|||
# Generated by Django 5.0.6 on 2024-07-15 09:21
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("snapshot", "0004_anotation"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Annotation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("uuid", models.UUIDField(unique=True)),
|
||||
("key", models.CharField(max_length=256)),
|
||||
("value", models.CharField(max_length=256)),
|
||||
(
|
||||
"owner",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name="anotation",
|
||||
),
|
||||
]
|
|
@ -1,39 +1,76 @@
|
|||
import json
|
||||
|
||||
from django.db import models
|
||||
|
||||
from utils.constants import STR_SM_SIZE, STR_EXTEND_SIZE
|
||||
from snapshot.xapian import search
|
||||
from user.models import User
|
||||
from device.models import Computer, Component
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Snapshot(models.Model):
|
||||
class SoftWare(models.TextChoices):
|
||||
WORKBENCH= "Workbench"
|
||||
class Snapshot:
|
||||
def __init__(self, uuid):
|
||||
self.uuid = uuid
|
||||
self.owner = None
|
||||
self.doc = None
|
||||
self.created = None
|
||||
self.annotations = []
|
||||
|
||||
class Severity(models.IntegerChoices):
|
||||
Info = 0, "Info"
|
||||
Notice = 1, "Notice"
|
||||
Warning = 2, "Warning"
|
||||
Error = 3, "Error"
|
||||
self.get_owner()
|
||||
self.get_time()
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
software = models.CharField(max_length=STR_SM_SIZE, choices=SoftWare, default=SoftWare.WORKBENCH)
|
||||
uuid = models.UUIDField(unique=True)
|
||||
version = models.CharField(max_length=STR_SM_SIZE)
|
||||
sid = models.CharField(max_length=STR_SM_SIZE)
|
||||
settings_version = models.CharField(max_length=STR_SM_SIZE)
|
||||
is_server_erase = models.BooleanField(default=False)
|
||||
severity = models.SmallIntegerField(choices=Severity, default=Severity.Info)
|
||||
end_time = models.DateTimeField()
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
computer = models.ForeignKey(Computer, on_delete=models.CASCADE)
|
||||
components = models.ManyToManyField(Component)
|
||||
def get_annotations(self):
|
||||
self.annotations = Annotation.objects.filter(
|
||||
uuid=self.uuid
|
||||
).order_by("created")
|
||||
|
||||
def get_owner(self):
|
||||
if not self.annotations:
|
||||
self.get_annotations()
|
||||
a = self.annotations.first()
|
||||
if a:
|
||||
self.owner = a.owner
|
||||
|
||||
def get_doc(self):
|
||||
self.doc = {}
|
||||
qry = 'uuid:"{}"'.format(self.uuid)
|
||||
matches = search(qry, limit=1)
|
||||
if matches.size() < 0:
|
||||
return
|
||||
|
||||
for xa in matches:
|
||||
self.doc = json.loads(xa.document.get_data())
|
||||
|
||||
def get_time(self):
|
||||
if not self.doc:
|
||||
self.get_doc()
|
||||
self.created = self.doc.get("endTime")
|
||||
|
||||
if not self.created:
|
||||
self.created = self.annotations.last().created
|
||||
|
||||
def components(self):
|
||||
return self.doc.get('components', [])
|
||||
|
||||
|
||||
class Annotation(models.Model):
|
||||
class Type(models.IntegerChoices):
|
||||
SYSTEM= 0, "System"
|
||||
USER = 1, "User"
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
uuid = models.UUIDField(unique=True)
|
||||
uuid = models.UUIDField()
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
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 = [
|
||||
models.UniqueConstraint(fields=["type", "key", "uuid"], name="unique_type_key_uuid")
|
||||
]
|
||||
|
||||
def is_user_annotation(self):
|
||||
if self.type == self.Type.USER:
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -5,42 +5,25 @@ import xapian
|
|||
import hashlib
|
||||
|
||||
from datetime import datetime
|
||||
from snapshot.xapian import search, index
|
||||
from snapshot.models import Snapshot, Annotation
|
||||
from snapshot.xapian import search, indexer, database
|
||||
|
||||
|
||||
HID_ALGO1 = [
|
||||
"manufacturer",
|
||||
"model",
|
||||
"chassis",
|
||||
"serialNumber",
|
||||
"sku"
|
||||
]
|
||||
from device.models import Device
|
||||
from utils.constants import ALGOS
|
||||
|
||||
|
||||
class Build:
|
||||
def __init__(self, snapshot_json, user):
|
||||
self.json = snapshot_json
|
||||
self.uuid = self.json['uuid']
|
||||
self.user = user
|
||||
self.hid = None
|
||||
|
||||
self.index()
|
||||
self.create_annotation()
|
||||
self.create_annotations()
|
||||
|
||||
def index(self):
|
||||
matches = search(self.json['uuid'], limit=1)
|
||||
if matches.size() > 0:
|
||||
return
|
||||
|
||||
snap = json.dumps(self.json)
|
||||
doc = xapian.Document()
|
||||
doc.set_data(snap)
|
||||
|
||||
indexer.set_document(doc)
|
||||
indexer.index_text(snap)
|
||||
|
||||
# Add the document to the database.
|
||||
database.add_document(doc)
|
||||
index(self.uuid, snap)
|
||||
|
||||
def get_hid_14(self):
|
||||
device = self.json['device']
|
||||
|
@ -52,15 +35,35 @@ class Build:
|
|||
hid = f"{manufacturer}{model}{chassis}{serial_number}{sku}"
|
||||
return hashlib.sha3_256(hid.encode()).hexdigest()
|
||||
|
||||
def create_annotation(self):
|
||||
uuid = self.json['uuid']
|
||||
def create_annotations(self):
|
||||
algorithms = {
|
||||
'hidalgo1': self.get_hid_14(),
|
||||
}
|
||||
|
||||
annotation = Annotation.objects.filter(
|
||||
owner=self.user,
|
||||
type=Annotation.Type.SYSTEM,
|
||||
key='hidalgo1',
|
||||
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
|
||||
key = 'hidalgo1'
|
||||
value = self.get_hid_14()
|
||||
Annotation.objects.create(
|
||||
uuid=uuid,
|
||||
owner=owner,
|
||||
key=key,
|
||||
value=value
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
|
|
|
@ -2,9 +2,13 @@ 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,
|
||||
)
|
||||
|
||||
from dashboard.mixins import DashboardView
|
||||
from snapshot.models import Snapshot
|
||||
from snapshot.models import Snapshot, Annotation
|
||||
# from snapshot.forms import UploadForm
|
||||
# from django.shortcuts import render
|
||||
# from rest_framework import viewsets
|
||||
|
@ -24,7 +28,8 @@ class ListSnapshotsView(DashboardView, TemplateView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
snapshots = Snapshot.objects.filter(owner=self.request.user)
|
||||
# snapshots = Snapshot.objects.filter(owner=self.request.user)
|
||||
snapshots = []
|
||||
context.update({
|
||||
'snapshots': snapshots,
|
||||
})
|
||||
|
|
|
@ -1,22 +1,51 @@
|
|||
import xapian
|
||||
|
||||
database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
|
||||
# database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
|
||||
|
||||
indexer = xapian.TermGenerator()
|
||||
stemmer = xapian.Stem("english")
|
||||
indexer.set_stemmer(stemmer)
|
||||
# Read Only
|
||||
# database = xapian.Database("db")
|
||||
|
||||
# indexer = xapian.TermGenerator()
|
||||
# stemmer = xapian.Stem("english")
|
||||
# indexer.set_stemmer(stemmer)
|
||||
|
||||
|
||||
def search(qs, offset=0, limit=10):
|
||||
query_string = str.join(' ', qs)
|
||||
database = xapian.Database("db")
|
||||
|
||||
qp = xapian.QueryParser()
|
||||
qp.set_stemmer(stemmer)
|
||||
qp.set_database(database)
|
||||
qp.set_stemmer(xapian.Stem("english"))
|
||||
qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME)
|
||||
query = qp.parse_query(query_string)
|
||||
qp.add_prefix("uuid", "uuid")
|
||||
# qp.add_prefix("snapshot", "snapshot")
|
||||
query = qp.parse_query(qs)
|
||||
enquire = xapian.Enquire(database)
|
||||
enquire.set_query(query)
|
||||
matches = enquire.get_mset(offset, limit)
|
||||
return matches
|
||||
|
||||
|
||||
def index(uuid, snap):
|
||||
uuid = 'uuid:"{}"'.format(uuid)
|
||||
try:
|
||||
matches = search(uuid, limit=1)
|
||||
if matches.size() > 0:
|
||||
return
|
||||
except xapian.DatabaseNotFoundError:
|
||||
pass
|
||||
|
||||
database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
|
||||
indexer = xapian.TermGenerator()
|
||||
stemmer = xapian.Stem("english")
|
||||
indexer.set_stemmer(stemmer)
|
||||
|
||||
doc = xapian.Document()
|
||||
doc.set_data(snap)
|
||||
|
||||
indexer.set_document(doc)
|
||||
indexer.index_text(snap)
|
||||
indexer.index_text(uuid, 10, "uuid")
|
||||
# indexer.index_text(snap, 1, "snapshot")
|
||||
|
||||
database.add_document(doc)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from django.contrib.auth import get_user_model
|
||||
from lot.models import LotTag
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
@ -16,8 +17,21 @@ class Command(BaseCommand):
|
|||
email = kwargs['email']
|
||||
password = kwargs['password']
|
||||
self.create_user(email, password)
|
||||
self.create_lot_tags()
|
||||
|
||||
def create_user(self, email, password):
|
||||
u = User.objects.create(email=email, password=password)
|
||||
u.set_password(password)
|
||||
u.save()
|
||||
self.u = User.objects.create(email=email, password=password)
|
||||
self.u.set_password(password)
|
||||
self.u.save()
|
||||
|
||||
def create_lot_tags(self):
|
||||
tags = [
|
||||
"Entrada",
|
||||
"Salida",
|
||||
"Temporal"
|
||||
]
|
||||
for tag in tags:
|
||||
LotTag.objects.create(
|
||||
name=tag,
|
||||
owner=self.u
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 5.0.6 on 2024-06-11 09:19
|
||||
# Generated by Django 5.0.6 on 2024-07-17 14:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
|
|
@ -6,3 +6,17 @@ STR_SM_SIZE = 32
|
|||
STR_SIZE = 64
|
||||
STR_BIG_SIZE = 128
|
||||
STR_EXTEND_SIZE = 256
|
||||
|
||||
|
||||
# Algorithms for build hids
|
||||
HID_ALGO1 = [
|
||||
"manufacturer",
|
||||
"model",
|
||||
"chassis",
|
||||
"serialNumber",
|
||||
"sku"
|
||||
]
|
||||
|
||||
ALGOS = {
|
||||
"hidalgo1": HID_ALGO1,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue