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.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from device.models import Device
|
from device.models import Device
|
||||||
|
from lot.models import LotTag
|
||||||
|
|
||||||
|
|
||||||
class Http403(PermissionDenied):
|
class Http403(PermissionDenied):
|
||||||
|
@ -37,6 +38,7 @@ class DashboardView(LoginRequiredMixin):
|
||||||
'section': self.section,
|
'section': self.section,
|
||||||
'path': resolve(self.request.path).url_name,
|
'path': resolve(self.request.path).url_name,
|
||||||
'user': self.request.user,
|
'user': self.request.user,
|
||||||
|
'lot_tags': LotTag.objects.filter(owner=self.request.user)
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
|
@ -103,21 +103,13 @@
|
||||||
{% trans 'Lots' %}
|
{% trans 'Lots' %}
|
||||||
</a>
|
</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">
|
<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">
|
<li class="nav-items">
|
||||||
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{% url 'lot:lots_incoming' %}">
|
<a class="nav-link{% if path == 'admin_people_list' %} active2{% endif %}" href="{% url 'lot:tag' tag.id %}">
|
||||||
{% trans 'Incoming ' %}
|
{{ tag.name }}
|
||||||
</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>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
|
|
@ -6,7 +6,7 @@ from dashboard.mixins import InventaryMixin, DetailsMixin
|
||||||
from device.models import Device
|
from device.models import Device
|
||||||
from snapshot.xapian import search
|
from snapshot.xapian import search
|
||||||
from snapshot.models import Annotation
|
from snapshot.models import Annotation
|
||||||
from lot.models import Lot
|
from lot.models import Lot, LotTag
|
||||||
|
|
||||||
|
|
||||||
class UnassignedDevicesView(InventaryMixin):
|
class UnassignedDevicesView(InventaryMixin):
|
||||||
|
@ -17,30 +17,14 @@ class UnassignedDevicesView(InventaryMixin):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
annotations = Annotation.objects.filter(
|
devices = Device.objects.filter(
|
||||||
owner=self.request.user).filter(
|
owner=self.request.user
|
||||||
key="hidalgo1").order_by('created')
|
).annotate(num_lots=Count('lot')).filter(num_lots=0)
|
||||||
# '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)
|
|
||||||
|
|
||||||
context.update({
|
context.update({
|
||||||
'devices': devices
|
'devices': devices,
|
||||||
})
|
})
|
||||||
|
|
||||||
return context
|
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
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -26,31 +26,7 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
verbose_name="ID",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("created", models.DateTimeField(auto_now_add=True)),
|
("type", models.CharField(blank=True, max_length=64, null=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)),
|
|
||||||
(
|
(
|
||||||
"owner",
|
"owner",
|
||||||
models.ForeignKey(
|
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 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 user.models import User
|
||||||
from utils.constants import STR_SM_SIZE, STR_SIZE
|
|
||||||
|
|
||||||
|
|
||||||
class Device(models.Model):
|
class Device(models.Model):
|
||||||
|
@ -20,155 +22,59 @@ class Device(models.Model):
|
||||||
BATTERY = "Battery"
|
BATTERY = "Battery"
|
||||||
CAMERA = "Camera"
|
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)
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
try:
|
self.annotations = []
|
||||||
if self.physicalproperties:
|
self.hids = []
|
||||||
return True
|
self.uuids = []
|
||||||
else:
|
self.snapshots = []
|
||||||
return False
|
super().__init__(*args, **kwargs)
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
def initial(self):
|
||||||
|
self.get_annotations()
|
||||||
|
self.get_uuids()
|
||||||
|
self.get_hids()
|
||||||
|
self.get_snapshots()
|
||||||
|
|
||||||
class PhysicalProperties(models.Model):
|
def get_annotations(self):
|
||||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
self.annotations = Annotation.objects.filter(
|
||||||
weight = models.FloatField(blank=True, null=True)
|
device=self,
|
||||||
width = models.FloatField(blank=True, null=True)
|
owner=self.owner
|
||||||
height = models.FloatField(blank=True, null=True)
|
).order_by("-created")
|
||||||
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_uuids(self):
|
||||||
|
for a in self.annotations:
|
||||||
|
if not a.uuid in self.uuids:
|
||||||
|
self.uuids.append(a.uuid)
|
||||||
|
|
||||||
class Computer(models.Model):
|
def get_hids(self):
|
||||||
class Chassis(models.TextChoices):
|
if not self.annotations:
|
||||||
TOWER = 'Tower'
|
self.get_annotations()
|
||||||
ALLINONE = 'All in one'
|
|
||||||
MICROTOWER = 'Microtower'
|
|
||||||
NETBOOK = 'Netbook'
|
|
||||||
LAPTOP = 'Laptop'
|
|
||||||
TABLER = 'Tablet'
|
|
||||||
SERVER = "Server"
|
|
||||||
VIRTUAL = 'Non-physical device'
|
|
||||||
|
|
||||||
|
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)
|
def get_snapshots(self):
|
||||||
chassis = models.CharField(
|
if not self.uuids:
|
||||||
blank=True,
|
self.get_uuids()
|
||||||
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)
|
|
||||||
|
|
||||||
|
self.snapshots = [Snapshot(u) for u in self.uuids]
|
||||||
|
|
||||||
class Component(models.Model):
|
def get_last_snapshot(self):
|
||||||
device = models.OneToOneField(Device, models.CASCADE, primary_key=True)
|
if not self.snapshots:
|
||||||
computer = models.ForeignKey(Computer, on_delete=models.CASCADE, null=True)
|
self.get_snapshots()
|
||||||
|
|
||||||
|
if self.snapshots:
|
||||||
|
return self.snapshots[0]
|
||||||
|
|
||||||
class GraphicCard(models.Model):
|
@classmethod
|
||||||
component = models.OneToOneField(Component, models.CASCADE)
|
def get_unassigned(cls, user):
|
||||||
memory = models.IntegerField(blank=True, null=True)
|
return cls.objects.filter(
|
||||||
|
owner=user
|
||||||
|
).annotate(num_lots=models.Count('lot')).filter(num_lots=0)
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,18 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h3>{{ object.uuid }}</h3>
|
<h3>{{ object.id }}</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div 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="#details">General details</button>
|
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#details">General details</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-items">
|
<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>
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#documents">Documents</button>
|
||||||
|
@ -23,20 +23,19 @@
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#lots">Lots</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-items">
|
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#status">Status</button>
|
|
||||||
</li>
|
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#components">Components</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceabiliy">Traceability log</button>
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#traceabiliy">Traceability log</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-items">
|
||||||
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#snapshots">Snapshots</button>
|
||||||
|
</li>
|
||||||
<li class="nav-items">
|
<li class="nav-items">
|
||||||
<a class="nav-link" href="">Web</a>
|
<a class="nav-link" href="">Web</a>
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content pt-2">
|
<div class="tab-content pt-2">
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
<h5 class="card-title">Details</h5>
|
<h5 class="card-title">Details</h5>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-lg-3 col-md-4 label ">
|
<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>
|
||||||
<div class="col-lg-9 col-md-8">
|
<div class="col-lg-9 col-md-8">
|
||||||
{% if object.hid %}Snapshot{% else %}Placeholder{% endif %}
|
{% if object.hid %}Snapshot{% else %}Placeholder{% endif %}
|
||||||
|
@ -54,7 +53,7 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label ">Phid</div>
|
<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>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -64,101 +63,85 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label ">Type</div>
|
<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>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Manufacturer</div>
|
<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>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Model</div>
|
<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>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 col-md-4 label">Serial Number</div>
|
<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>
|
|
||||||
|
|
||||||
<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="row">
|
||||||
<div class="col-lg-3 col-md-4 label ">
|
<div class="col-lg-3 col-md-4 label">Identifiers</div>
|
||||||
Weight:
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-9 col-md-8">
|
{% for chid in object.hids %}
|
||||||
{{ object.physicalproperties.weight }}
|
<div class="row">
|
||||||
|
<div class="col">{{ chid |default:"" }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="tab-pane fade profile-overview" id="annotations">
|
||||||
<div class="col-lg-3 col-md-4 label ">width:</div>
|
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||||
<div class="col-lg-9 col-md-8">
|
<a href="{% url 'device:add_annotation' object.pk %}" class="btn btn-primary">
|
||||||
{{ object.physicalproperties.width }}
|
<i class="bi bi-plus"></i>
|
||||||
</div>
|
Add new annotation
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<h5 class="card-title">Annotations</h5>
|
||||||
<div class="col-lg-3 col-md-4 label ">height:</div>
|
<table class="table table-striped">
|
||||||
<div class="col-lg-9 col-md-8">
|
<thead>
|
||||||
{{ object.physicalproperties.height }}
|
<tr>
|
||||||
</div>
|
<th scope="col">Key</th>
|
||||||
</div>
|
<th scope="col">Value</th>
|
||||||
|
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created on</th>
|
||||||
<div class="row">
|
<th></th>
|
||||||
<div class="col-lg-3 col-md-4 label ">depth:</div>
|
<th></th>
|
||||||
<div class="col-lg-9 col-md-8">
|
</tr>
|
||||||
{{ object.physicalproperties.depth }}
|
</thead>
|
||||||
</div>
|
<tbody>
|
||||||
</div>
|
{% for a in object.annotations %}
|
||||||
|
{% if a.is_user_annotation %}
|
||||||
<div class="row">
|
<tr>
|
||||||
<div class="col-lg-3 col-md-4 label ">color:</div>
|
<td>{{ a.key }}</td>
|
||||||
<div class="col-lg-9 col-md-8">
|
<td>{{ a.value }}</td>
|
||||||
{{ object.physicalproperties.color }}
|
<td>{{ a.created }}</td>
|
||||||
</div>
|
<td></td>
|
||||||
</div>
|
<td></td>
|
||||||
|
</tr>
|
||||||
<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>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="lots">
|
<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="row">
|
||||||
|
<div class="col">
|
||||||
|
<a href="{% url 'dashboard:lot' lot.id %}">{{ lot.name }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="card-title">Outgoing Lots</h5>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h5 class="card-title">Temporary Lots</h5>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="documents">
|
<div class="tab-pane fade profile-overview" id="documents">
|
||||||
|
@ -188,28 +171,6 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</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">
|
<div class="tab-pane fade profile-overview" id="traceability">
|
||||||
<h5 class="card-title">Traceability log Details</h5>
|
<h5 class="card-title">Traceability log Details</h5>
|
||||||
<div class="list-group col-6">
|
<div class="list-group col-6">
|
||||||
|
@ -233,35 +194,42 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-pane fade profile-overview" id="components">
|
<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">
|
<div class="list-group col-6">
|
||||||
|
{% for c in snapshot.components %}
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="d-flex w-100 justify-content-between">
|
<div class="d-flex w-100 justify-content-between">
|
||||||
<h5 class="mb-1">Motherboard</h5>
|
<h5 class="mb-1">{{ c.type }}</h5>
|
||||||
<small class="text-muted">14:07 23-06-2024</small>
|
<small class="text-muted">{{ snapshot.created }}</small>
|
||||||
</div>
|
</div>
|
||||||
<p class="mb-1">
|
<p class="mb-1">
|
||||||
hp<br />
|
{{ c.manufacturer }}<br />
|
||||||
890e<br />
|
{{ c.model }}<br />
|
||||||
|
{{ c.serialNumber }}<br />
|
||||||
</p>
|
</p>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</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="list-group-item">
|
||||||
<div class="d-flex w-100 justify-content-between">
|
<div class="d-flex w-100 justify-content-between">
|
||||||
<h5 class="mb-1">NetworkAdapter</h5>
|
<h5 class="mb-1"></h5>
|
||||||
<small class="text-muted">14:07 23-06-2024</small>
|
<small class="text-muted">{{ snap.created }}</small>
|
||||||
</div>
|
</div>
|
||||||
<p class="mb-1">
|
<p class="mb-1">
|
||||||
realtek semiconductor co., ltd.<br />
|
{{ snap.uuid }}<br />
|
||||||
rtl8852ae 802.11ax pcie wireless network adapter<br />
|
|
||||||
</p>
|
</p>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ app_name = 'device'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("add/", views.NewDeviceView.as_view(), name="add"),
|
path("add/", views.NewDeviceView.as_view(), name="add"),
|
||||||
path("edit/<uuid:pk>/", views.EditDeviceView.as_view(), name="edit"),
|
path("edit/<int:pk>/", views.EditDeviceView.as_view(), name="edit"),
|
||||||
path("<uuid:pk>/", views.DetailsView.as_view(), name="details"),
|
path("<int:pk>/", views.DetailsView.as_view(), name="details"),
|
||||||
path("physical/<uuid:pk>/", views.PhysicalView.as_view(), name="physical_edit"),
|
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 dashboard.mixins import DashboardView, DetailsMixin
|
||||||
from snapshot.models import Annotation
|
from snapshot.models import Annotation
|
||||||
from snapshot.xapian import search
|
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):
|
class NewDeviceView(DashboardView, CreateView):
|
||||||
|
@ -20,24 +21,10 @@ class NewDeviceView(DashboardView, CreateView):
|
||||||
breadcrumb = "Device / New Device"
|
breadcrumb = "Device / New Device"
|
||||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||||
model = Device
|
model = Device
|
||||||
fields = (
|
|
||||||
'type',
|
|
||||||
"model",
|
|
||||||
"manufacturer",
|
|
||||||
"serial_number",
|
|
||||||
"part_number",
|
|
||||||
"brand",
|
|
||||||
"generation",
|
|
||||||
"version",
|
|
||||||
"production_date",
|
|
||||||
"variant",
|
|
||||||
"family",
|
|
||||||
)
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
form.instance.owner = self.request.user
|
form.instance.owner = self.request.user
|
||||||
response = super().form_valid(form)
|
response = super().form_valid(form)
|
||||||
PhysicalProperties.objects.create(device=form.instance)
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,19 +34,6 @@ class EditDeviceView(DashboardView, UpdateView):
|
||||||
breadcrumb = "Device / Update Device"
|
breadcrumb = "Device / Update Device"
|
||||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||||
model = Device
|
model = Device
|
||||||
fields = (
|
|
||||||
'type',
|
|
||||||
"model",
|
|
||||||
"manufacturer",
|
|
||||||
"serial_number",
|
|
||||||
"part_number",
|
|
||||||
"brand",
|
|
||||||
"generation",
|
|
||||||
"version",
|
|
||||||
"production_date",
|
|
||||||
"variant",
|
|
||||||
"family",
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
|
@ -69,71 +43,51 @@ class EditDeviceView(DashboardView, UpdateView):
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class DetailsView2(DetailsMixin):
|
class DetailsView(DetailsMixin):
|
||||||
template_name = "details.html"
|
template_name = "details.html"
|
||||||
title = _("Device")
|
title = _("Device")
|
||||||
breadcrumb = "Device / Details"
|
breadcrumb = "Device / Details"
|
||||||
model = Device
|
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):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
self.object.initial()
|
||||||
|
lot_tags = LotTag.objects.filter(owner=self.request.user)
|
||||||
context.update({
|
context.update({
|
||||||
'object': self.object,
|
'snapshot': self.object.get_last_snapshot(),
|
||||||
|
'lot_tags': lot_tags,
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class AddAnnotationView(DashboardView, CreateView):
|
||||||
class PhysicalView(DashboardView, UpdateView):
|
template_name = "new_device.html"
|
||||||
template_name = "physical_properties.html"
|
title = _("New annotation")
|
||||||
title = _("Physical Properties")
|
breadcrumb = "Device / New annotation"
|
||||||
breadcrumb = "Device / Physical properties"
|
|
||||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||||
model = PhysicalProperties
|
model = Annotation
|
||||||
fields = (
|
fields = ("key", "value")
|
||||||
"weight",
|
|
||||||
"width",
|
|
||||||
"height",
|
|
||||||
"depth",
|
|
||||||
"color",
|
|
||||||
"image",
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def form_valid(self, form):
|
||||||
context = super().get_context_data(**kwargs)
|
self.device.get_annotations()
|
||||||
context.update({
|
self.device.get_uuids()
|
||||||
'device': self.device,
|
form.instance.owner = self.request.user
|
||||||
})
|
form.instance.device = self.device
|
||||||
return context
|
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):
|
def get_form_kwargs(self):
|
||||||
pk = self.kwargs.get('pk')
|
pk = self.kwargs.get('pk')
|
||||||
self.device = get_object_or_404(Device, pk=pk)
|
self.device = get_object_or_404(Device, pk=pk)
|
||||||
try:
|
self.success_url = reverse_lazy('device:details', args=[pk])
|
||||||
self.object = self.device.physicalproperties
|
|
||||||
except Exception:
|
|
||||||
self.object = PhysicalProperties.objects.create(device=self.device)
|
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def form_valid(self, form):
|
def get_success_url(self):
|
||||||
self.success_url = reverse_lazy('device:details', args=[self.device.id])
|
url = super().get_success_url()
|
||||||
response = super().form_valid(form)
|
import pdb; pdb.set_trace()
|
||||||
return response
|
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
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -10,11 +10,33 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("device", "0003_remove_component_type_remove_computer_type_and_more"),
|
("device", "0001_initial"),
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
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(
|
migrations.CreateModel(
|
||||||
name="Lot",
|
name="Lot",
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -29,18 +51,6 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
("created", models.DateTimeField(auto_now_add=True)),
|
("created", models.DateTimeField(auto_now_add=True)),
|
||||||
("updated", models.DateTimeField(auto_now=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)),
|
("name", models.CharField(blank=True, max_length=64, null=True)),
|
||||||
("code", 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)),
|
("description", models.CharField(blank=True, max_length=64, null=True)),
|
||||||
|
@ -53,6 +63,12 @@ class Migration(migrations.Migration):
|
||||||
to=settings.AUTH_USER_MODEL,
|
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.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
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 user.models import User
|
||||||
from device.models import Device
|
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 Lot(models.Model):
|
||||||
class Types(models.TextChoices):
|
|
||||||
INCOMING = "Incoming"
|
|
||||||
OUTGOING = "Outgoing"
|
|
||||||
TEMPORAL = "Temporal"
|
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
updated = models.DateTimeField(auto_now=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)
|
name = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
code = 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)
|
description = models.CharField(max_length=STR_SIZE, blank=True, null=True)
|
||||||
closed = models.BooleanField(default=True)
|
closed = models.BooleanField(default=True)
|
||||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
type = models.ForeignKey(LotTag, on_delete=models.CASCADE)
|
||||||
devices = models.ManyToManyField(Device)
|
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">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
{% if incoming %}
|
{% for tag in lot_tags %}
|
||||||
<div class="row">
|
<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>
|
</div>
|
||||||
|
|
||||||
{% for lot in lots %}
|
{% for lot in lots %}
|
||||||
{% if lot.is_incoming %}
|
{% if lot.type == tag %}
|
||||||
<div class="row">
|
<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 "><input type="checkbox" name="lots" value="{{ lot.id }}" /></div>
|
||||||
<div class="col-lg-3 col-md-4 label ">{{ lot.name }}</div>
|
<div class="col-lg-3 col-md-4 label ">{{ lot.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% 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 %}
|
{% 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>
|
<button type="submit">Save</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,5 @@ urlpatterns = [
|
||||||
path("edit/<int:pk>/", views.EditLotView.as_view(), name="edit"),
|
path("edit/<int:pk>/", views.EditLotView.as_view(), name="edit"),
|
||||||
path("add/devices/", views.AddToLotView.as_view(), name="add_devices"),
|
path("add/devices/", views.AddToLotView.as_view(), name="add_devices"),
|
||||||
path("del/devices/", views.DelToLotView.as_view(), name="del_devices"),
|
path("del/devices/", views.DelToLotView.as_view(), name="del_devices"),
|
||||||
path("temporal/", views.LotsTemporalView.as_view(), name="lots_temporal"),
|
path("tag/<int:pk>/", views.LotsTagsView.as_view(), name="tag"),
|
||||||
path("outgoing/", views.LotsOutgoingView.as_view(), name="lots_outgoing"),
|
|
||||||
path("incoming/", views.LotsIncomingView.as_view(), name="lots_incoming"),
|
|
||||||
]
|
]
|
||||||
|
|
38
lot/views.py
38
lot/views.py
|
@ -9,7 +9,7 @@ from django.views.generic.edit import (
|
||||||
FormView
|
FormView
|
||||||
)
|
)
|
||||||
from dashboard.mixins import DashboardView
|
from dashboard.mixins import DashboardView
|
||||||
from lot.models import Lot
|
from lot.models import Lot, LotTag
|
||||||
from lot.forms import LotsForm
|
from lot.forms import LotsForm
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,20 +84,15 @@ class AddToLotView(DashboardView, FormView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
lots = Lot.objects.filter(owner=self.request.user)
|
lots = Lot.objects.filter(owner=self.request.user)
|
||||||
lots_incoming = lots.filter(type=Lot.Types.INCOMING).exists()
|
lot_tags = LotTag.objects.filter(owner=self.request.user)
|
||||||
lots_outgoing = lots.filter(type=Lot.Types.OUTGOING).exists()
|
|
||||||
lots_temporal = lots.filter(type=Lot.Types.TEMPORAL).exists()
|
|
||||||
context.update({
|
context.update({
|
||||||
'lots': lots,
|
'lots': lots,
|
||||||
'incoming': lots_incoming,
|
'lot_tags':lot_tags,
|
||||||
'outgoing': lots_outgoing,
|
|
||||||
'temporal': lots_temporal
|
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_form(self):
|
def get_form(self):
|
||||||
form = super().get_form()
|
form = super().get_form()
|
||||||
# import pdb; pdb.set_trace()
|
|
||||||
form.fields["lots"].queryset = Lot.objects.filter(owner=self.request.user)
|
form.fields["lots"].queryset = Lot.objects.filter(owner=self.request.user)
|
||||||
return form
|
return form
|
||||||
|
|
||||||
|
@ -119,28 +114,23 @@ class DelToLotView(AddToLotView):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class LotsTemporalView(DashboardView, TemplateView):
|
class LotsTagsView(DashboardView, TemplateView):
|
||||||
template_name = "lots.html"
|
template_name = "lots.html"
|
||||||
title = _("Temporal lots")
|
title = _("lots")
|
||||||
breadcrumb = "lot / temporal lots"
|
breadcrumb = _("lots") + " /"
|
||||||
success_url = reverse_lazy('dashboard:unassigned_devices')
|
success_url = reverse_lazy('dashboard:unassigned_devices')
|
||||||
lot_type = Lot.Types.TEMPORAL
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
self.pk = kwargs.get('pk')
|
||||||
context = super().get_context_data(**kwargs)
|
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({
|
context.update({
|
||||||
'lots': lots.filter(type=self.lot_type),
|
'lots': lots,
|
||||||
|
'title': self.title,
|
||||||
|
'breadcrumb': self.breadcrumb
|
||||||
})
|
})
|
||||||
return context
|
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
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Snapshot",
|
name="Annotation",
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
"id",
|
||||||
|
@ -28,39 +28,17 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("created", models.DateTimeField(auto_now_add=True)),
|
("created", models.DateTimeField(auto_now_add=True)),
|
||||||
(
|
|
||||||
"software",
|
|
||||||
models.CharField(
|
|
||||||
choices=[("Workbench", "Workbench")],
|
|
||||||
default="Workbench",
|
|
||||||
max_length=32,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("uuid", models.UUIDField()),
|
("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",
|
"type",
|
||||||
models.SmallIntegerField(
|
models.SmallIntegerField(choices=[(0, "System"), (1, "User")]),
|
||||||
choices=[
|
|
||||||
(0, "Info"),
|
|
||||||
(1, "Notice"),
|
|
||||||
(2, "Warning"),
|
|
||||||
(3, "Error"),
|
|
||||||
],
|
|
||||||
default=0,
|
|
||||||
),
|
),
|
||||||
),
|
("key", models.CharField(max_length=256)),
|
||||||
("start_time", models.DateTimeField()),
|
("value", models.CharField(max_length=256)),
|
||||||
("end_time", models.DateTimeField()),
|
|
||||||
("components", models.ManyToManyField(to="device.component")),
|
|
||||||
(
|
(
|
||||||
"computer",
|
"device",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE, to="device.device"
|
||||||
to="device.computer",
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -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 django.db import models
|
||||||
|
|
||||||
from utils.constants import STR_SM_SIZE, STR_EXTEND_SIZE
|
from utils.constants import STR_SM_SIZE, STR_EXTEND_SIZE
|
||||||
|
from snapshot.xapian import search
|
||||||
from user.models import User
|
from user.models import User
|
||||||
from device.models import Computer, Component
|
|
||||||
|
|
||||||
# Create your models here.
|
|
||||||
|
|
||||||
|
|
||||||
class Snapshot(models.Model):
|
class Snapshot:
|
||||||
class SoftWare(models.TextChoices):
|
def __init__(self, uuid):
|
||||||
WORKBENCH= "Workbench"
|
self.uuid = uuid
|
||||||
|
self.owner = None
|
||||||
|
self.doc = None
|
||||||
|
self.created = None
|
||||||
|
self.annotations = []
|
||||||
|
|
||||||
class Severity(models.IntegerChoices):
|
self.get_owner()
|
||||||
Info = 0, "Info"
|
self.get_time()
|
||||||
Notice = 1, "Notice"
|
|
||||||
Warning = 2, "Warning"
|
|
||||||
Error = 3, "Error"
|
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
def get_annotations(self):
|
||||||
software = models.CharField(max_length=STR_SM_SIZE, choices=SoftWare, default=SoftWare.WORKBENCH)
|
self.annotations = Annotation.objects.filter(
|
||||||
uuid = models.UUIDField(unique=True)
|
uuid=self.uuid
|
||||||
version = models.CharField(max_length=STR_SM_SIZE)
|
).order_by("created")
|
||||||
sid = models.CharField(max_length=STR_SM_SIZE)
|
|
||||||
settings_version = models.CharField(max_length=STR_SM_SIZE)
|
def get_owner(self):
|
||||||
is_server_erase = models.BooleanField(default=False)
|
if not self.annotations:
|
||||||
severity = models.SmallIntegerField(choices=Severity, default=Severity.Info)
|
self.get_annotations()
|
||||||
end_time = models.DateTimeField()
|
a = self.annotations.first()
|
||||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
if a:
|
||||||
computer = models.ForeignKey(Computer, on_delete=models.CASCADE)
|
self.owner = a.owner
|
||||||
components = models.ManyToManyField(Component)
|
|
||||||
|
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 Annotation(models.Model):
|
||||||
|
class Type(models.IntegerChoices):
|
||||||
|
SYSTEM= 0, "System"
|
||||||
|
USER = 1, "User"
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
uuid = models.UUIDField(unique=True)
|
uuid = models.UUIDField()
|
||||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
|
type = models.SmallIntegerField(choices=Type)
|
||||||
key = models.CharField(max_length=STR_EXTEND_SIZE)
|
key = models.CharField(max_length=STR_EXTEND_SIZE)
|
||||||
value = 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
|
import hashlib
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from snapshot.xapian import search, index
|
||||||
from snapshot.models import Snapshot, Annotation
|
from snapshot.models import Snapshot, Annotation
|
||||||
from snapshot.xapian import search, indexer, database
|
from device.models import Device
|
||||||
|
from utils.constants import ALGOS
|
||||||
|
|
||||||
HID_ALGO1 = [
|
|
||||||
"manufacturer",
|
|
||||||
"model",
|
|
||||||
"chassis",
|
|
||||||
"serialNumber",
|
|
||||||
"sku"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Build:
|
class Build:
|
||||||
def __init__(self, snapshot_json, user):
|
def __init__(self, snapshot_json, user):
|
||||||
self.json = snapshot_json
|
self.json = snapshot_json
|
||||||
|
self.uuid = self.json['uuid']
|
||||||
self.user = user
|
self.user = user
|
||||||
self.hid = None
|
self.hid = None
|
||||||
|
|
||||||
self.index()
|
self.index()
|
||||||
self.create_annotation()
|
self.create_annotations()
|
||||||
|
|
||||||
def index(self):
|
def index(self):
|
||||||
matches = search(self.json['uuid'], limit=1)
|
|
||||||
if matches.size() > 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
snap = json.dumps(self.json)
|
snap = json.dumps(self.json)
|
||||||
doc = xapian.Document()
|
index(self.uuid, snap)
|
||||||
doc.set_data(snap)
|
|
||||||
|
|
||||||
indexer.set_document(doc)
|
|
||||||
indexer.index_text(snap)
|
|
||||||
|
|
||||||
# Add the document to the database.
|
|
||||||
database.add_document(doc)
|
|
||||||
|
|
||||||
def get_hid_14(self):
|
def get_hid_14(self):
|
||||||
device = self.json['device']
|
device = self.json['device']
|
||||||
|
@ -52,15 +35,35 @@ class Build:
|
||||||
hid = f"{manufacturer}{model}{chassis}{serial_number}{sku}"
|
hid = f"{manufacturer}{model}{chassis}{serial_number}{sku}"
|
||||||
return hashlib.sha3_256(hid.encode()).hexdigest()
|
return hashlib.sha3_256(hid.encode()).hexdigest()
|
||||||
|
|
||||||
def create_annotation(self):
|
def create_annotations(self):
|
||||||
uuid = self.json['uuid']
|
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
|
owner=self.user
|
||||||
key = 'hidalgo1'
|
)
|
||||||
value = self.get_hid_14()
|
|
||||||
Annotation.objects.create(
|
for k, v in algorithms.items():
|
||||||
uuid=uuid,
|
Annotation.objects.create(
|
||||||
owner=owner,
|
uuid=self.uuid,
|
||||||
key=key,
|
owner=self.user,
|
||||||
value=value
|
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.base import TemplateView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.views.generic.edit import (
|
||||||
|
CreateView,
|
||||||
|
UpdateView,
|
||||||
|
)
|
||||||
|
|
||||||
from dashboard.mixins import DashboardView
|
from dashboard.mixins import DashboardView
|
||||||
from snapshot.models import Snapshot
|
from snapshot.models import Snapshot, Annotation
|
||||||
# from snapshot.forms import UploadForm
|
# from snapshot.forms import UploadForm
|
||||||
# from django.shortcuts import render
|
# from django.shortcuts import render
|
||||||
# from rest_framework import viewsets
|
# from rest_framework import viewsets
|
||||||
|
@ -24,7 +28,8 @@ class ListSnapshotsView(DashboardView, TemplateView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**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({
|
context.update({
|
||||||
'snapshots': snapshots,
|
'snapshots': snapshots,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,22 +1,51 @@
|
||||||
import xapian
|
import xapian
|
||||||
|
|
||||||
database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
|
# database = xapian.WritableDatabase("db", xapian.DB_CREATE_OR_OPEN)
|
||||||
|
|
||||||
indexer = xapian.TermGenerator()
|
# Read Only
|
||||||
stemmer = xapian.Stem("english")
|
# database = xapian.Database("db")
|
||||||
indexer.set_stemmer(stemmer)
|
|
||||||
|
# indexer = xapian.TermGenerator()
|
||||||
|
# stemmer = xapian.Stem("english")
|
||||||
|
# indexer.set_stemmer(stemmer)
|
||||||
|
|
||||||
|
|
||||||
def search(qs, offset=0, limit=10):
|
def search(qs, offset=0, limit=10):
|
||||||
query_string = str.join(' ', qs)
|
database = xapian.Database("db")
|
||||||
|
|
||||||
qp = xapian.QueryParser()
|
qp = xapian.QueryParser()
|
||||||
qp.set_stemmer(stemmer)
|
|
||||||
qp.set_database(database)
|
qp.set_database(database)
|
||||||
|
qp.set_stemmer(xapian.Stem("english"))
|
||||||
qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME)
|
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 = xapian.Enquire(database)
|
||||||
enquire.set_query(query)
|
enquire.set_query(query)
|
||||||
matches = enquire.get_mset(offset, limit)
|
matches = enquire.get_mset(offset, limit)
|
||||||
return matches
|
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.core.management.base import BaseCommand
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from lot.models import LotTag
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
@ -16,8 +17,21 @@ class Command(BaseCommand):
|
||||||
email = kwargs['email']
|
email = kwargs['email']
|
||||||
password = kwargs['password']
|
password = kwargs['password']
|
||||||
self.create_user(email, password)
|
self.create_user(email, password)
|
||||||
|
self.create_lot_tags()
|
||||||
|
|
||||||
def create_user(self, email, password):
|
def create_user(self, email, password):
|
||||||
u = User.objects.create(email=email, password=password)
|
self.u = User.objects.create(email=email, password=password)
|
||||||
u.set_password(password)
|
self.u.set_password(password)
|
||||||
u.save()
|
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
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,17 @@ STR_SM_SIZE = 32
|
||||||
STR_SIZE = 64
|
STR_SIZE = 64
|
||||||
STR_BIG_SIZE = 128
|
STR_BIG_SIZE = 128
|
||||||
STR_EXTEND_SIZE = 256
|
STR_EXTEND_SIZE = 256
|
||||||
|
|
||||||
|
|
||||||
|
# Algorithms for build hids
|
||||||
|
HID_ALGO1 = [
|
||||||
|
"manufacturer",
|
||||||
|
"model",
|
||||||
|
"chassis",
|
||||||
|
"serialNumber",
|
||||||
|
"sku"
|
||||||
|
]
|
||||||
|
|
||||||
|
ALGOS = {
|
||||||
|
"hidalgo1": HID_ALGO1,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue