add annotations in device and in lots

This commit is contained in:
Cayo Puigdefabregas 2024-07-30 13:37:08 +02:00
parent 91780be94b
commit 0136a98ff5
27 changed files with 502 additions and 208 deletions

View File

@ -7,21 +7,17 @@
<h3>{{ subtitle }}</h3>
</div>
<div class="col text-center">
<a href="{# url 'idhub:admin_people_edit' object.id #}" type="button" class="btn btn-green-admin">
<a href="{% url 'lot:documents' object.id %}" type="button" class="btn btn-green-admin">
<i class="bi bi-folder2"></i>
{% trans 'Lots' %}
</a>
<a href="{# url 'idhub:admin_people_edit' object.id #}" type="button" class="btn btn-green-admin">
<i class="bi bi-plus"></i>
{% trans 'Actions' %}
{% trans 'Documents' %}
</a>
<a href="{# url 'idhub:admin_people_activate' object.id #}" type="button" class="btn btn-green-admin">
<i class="bi bi-reply"></i>
{% trans 'Exports' %}
</a>
<a href="#" type="button" class="btn btn-green-admin">
<a href="{% url 'lot:annotations' object.id %}" type="button" class="btn btn-green-admin">
<i class="bi bi-tag"></i>
{% trans 'Labels' %}
{% trans 'Annotations' %}
</a>
</div>
</div>

View File

@ -1,12 +1,7 @@
import json
from django.utils.translation import gettext_lazy as _
from django.db.models import Count
from dashboard.mixins import InventaryMixin, DetailsMixin
from device.models import Device
from evidence.xapian import search
from evidence.models import Annotation
from lot.models import Lot, LotTag
from lot.models import Lot
class UnassignedDevicesView(InventaryMixin):

View File

@ -4,8 +4,8 @@ import hashlib
import datetime
from django import forms
from snapshot.models import Annotation
from snapshot.xapian import search, index
from evidence.models import Annotation
from evidence.xapian import search, index
DEVICE_TYPES = [
("Desktop", "Desktop"),
@ -27,13 +27,19 @@ DEVICE_TYPES = [
class DeviceForm(forms.Form):
type = forms.ChoiceField(choices = DEVICE_TYPES, required=False)
amount = forms.IntegerField(required=True, initial=1)
amount = forms.IntegerField(required=False, initial=1)
tag = forms.CharField(required=False)
name = forms.CharField(required=False)
value = forms.CharField(required=False)
class BaseDeviceFormSet(forms.BaseFormSet):
def clean(self):
for x in self.cleaned_data:
if x.get("amount"):
return True
return False
def save(self, user, commit=True):
self.user = user
doc = {}

View File

@ -1,18 +0,0 @@
# 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),
),
]

View File

@ -1,18 +0,0 @@
# 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),
),
]

View File

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

View File

@ -56,10 +56,32 @@ class Device:
self.owner = self.annotations[0].owner
return self.annotations
def get_user_annotations(self):
if not self.uuids:
self.get_uuids()
annotations = Annotation.objects.filter(
uuid__in=self.uuids,
owner=self.owner,
type=Annotation.Type.USER
)
return annotations
def get_user_documents(self):
if not self.uuids:
self.get_uuids()
annotations = Annotation.objects.filter(
uuid__in=self.uuids,
owner=self.owner,
type=Annotation.Type.DOCUMENT
)
return annotations
def get_uuids(self):
for a in self.get_annotations():
if not a.uuid in self.uuids:
if a.uuid not in self.uuids:
self.uuids.append(a.uuid)
def get_hids(self):

View File

@ -90,7 +90,7 @@
</a>
</div>
<h5 class="card-title">Annotations</h5>
<h5 class="card-title mt-2">Annotations</h5>
<table class="table table-striped">
<thead>
<tr>
@ -102,8 +102,7 @@
</tr>
</thead>
<tbody>
{% for a in object.annotations %}
{% if a.is_user_annotation %}
{% for a in object.get_user_annotations %}
<tr>
<td>{{ a.key }}</td>
<td>{{ a.value }}</td>
@ -111,7 +110,6 @@
<td></td>
<td></td>
</tr>
{% endif %}
{% endfor %}
</tbody>
@ -137,26 +135,35 @@
<div class="tab-pane fade profile-overview" id="documents">
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
<a href="/inventory/device/4W8D3/document/add/" class="btn btn-primary">
<a href="{% url 'device:add_document' object.pk %}" class="btn btn-primary">
<i class="bi bi-plus"></i>
Add new document
<span class="caret"></span>
</a>
</div>
<h5 class="card-title">Documents</h5>
<table class="table">
<h5 class="card-title mt-2">Documents</h5>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">File</th>
<th scope="col">Type</th>
<th scope="col">Description</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Uploaded on</th>
<th scope="col">Key</th>
<th scope="col">Value</th>
<th scope="col" data-type="date" data-format="YYYY-MM-DD hh:mm">Created on</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for a in object.get_user_documents %}
<tr>
<td>{{ a.key }}</td>
<td>{{ a.value }}</td>
<td>{{ a.created }}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,45 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col">
<h3>{{ subtitle }}</h3>
</div>
</div>
{% load django_bootstrap5 %}
<form role="form" method="post">
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
<div class="message">
{% for field, error in form.errors.items %}
{{ error }}<br />
{% endfor %}
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
</div>
</div>
{% endif %}
{{ form.management_form }}
<div class="container" id="formset-container">
<div class="row mb-2">
<div class="col"></div>
</div>
{% for f in form %}
<div class="row mb-2">
<div class="col">
{% bootstrap_field f %}
</div>
</div>
{% endfor %}
</div>
<div class="container">
<a class="btn btn-grey" href="{% url 'dashboard:unassigned_devices' %}">{% translate "Cancel" %}</a>
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
</div>
</form>
{% endblock %}

View File

@ -8,4 +8,5 @@ urlpatterns = [
path("edit/<str:pk>/", views.EditDeviceView.as_view(), name="edit"),
path("<str:pk>/", views.DetailsView.as_view(), name="details"),
path("<str:pk>/annotation/add", views.AddAnnotationView.as_view(), name="add_annotation"),
path("<str:pk>/document/add", views.AddDocumentView.as_view(), name="add_document"),
]

View File

@ -10,8 +10,8 @@ from django.views.generic.edit import (
)
from django.views.generic.base import TemplateView
from dashboard.mixins import DashboardView
from snapshot.models import Annotation
from snapshot.xapian import search
from evidence.models import Annotation
from evidence.xapian import search
from lot.models import LotTag
from device.models import Device
from device.forms import DeviceFormSet
@ -95,14 +95,14 @@ class DetailsView(DashboardView, TemplateView):
lot_tags = LotTag.objects.filter(owner=self.request.user)
context.update({
'object': self.object,
'snapshot': self.object.get_last_snapshot(),
'snapshot': self.object.get_last_evidence(),
'lot_tags': lot_tags,
})
return context
class AddAnnotationView(DashboardView, CreateView):
template_name = "new_device.html"
template_name = "new_annotation.html"
title = _("New annotation")
breadcrumb = "Device / New annotation"
success_url = reverse_lazy('dashboard:unassigned_devices')
@ -110,25 +110,46 @@ class AddAnnotationView(DashboardView, CreateView):
fields = ("key", "value")
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.uuid = self.annotation.uuid
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)
self.annotation = Annotation.objects.filter(
owner=self.request.user, value=pk, type=Annotation.Type.SYSTEM
).first()
if not self.annotation:
get_object_or_404(Annotation, pk=0, owner=self.request.user)
self.success_url = reverse_lazy('device:details', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs
def get_success_url(self):
url = super().get_success_url()
import pdb; pdb.set_trace()
return url
class AddDocumentView(DashboardView, CreateView):
template_name = "new_annotation.html"
title = _("New Document")
breadcrumb = "Device / New document"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = Annotation
fields = ("key", "value")
def form_valid(self, form):
form.instance.owner = self.request.user
form.instance.uuid = self.annotation.uuid
form.instance.type = Annotation.Type.DOCUMENT
response = super().form_valid(form)
return response
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
self.annotation = Annotation.objects.filter(
owner=self.request.user, value=pk, type=Annotation.Type.SYSTEM
).first()
if not self.annotation:
get_object_or_404(Annotation, pk=0, owner=self.request.user)
self.success_url = reverse_lazy('device:details', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs

View File

@ -21,7 +21,7 @@ urlpatterns = [
# path('api/', include('snapshot.urls')),
path("", include("login.urls")),
path("dashboard/", include("dashboard.urls")),
path("snapshot/", include("snapshot.urls")),
path("evidence/", include("evidence.urls")),
path("device/", include("device.urls")),
path("lot/", include("lot.urls")),
]

View File

@ -4,7 +4,7 @@ import json
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from snapshot.parse import Build
from evidence.parse import Build
User = get_user_model()

View File

@ -1,4 +1,4 @@
# Generated by Django 5.0.6 on 2024-07-17 14:57
# Generated by Django 5.0.6 on 2024-07-27 16:23
import django.db.models.deletion
from django.conf import settings
@ -10,7 +10,6 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("device", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
@ -35,12 +34,6 @@ class Migration(migrations.Migration):
),
("key", models.CharField(max_length=256)),
("value", models.CharField(max_length=256)),
(
"device",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="device.device"
),
),
(
"owner",
models.ForeignKey(

View File

@ -0,0 +1,20 @@
# Generated by Django 5.0.6 on 2024-07-29 14:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("evidence", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="annotation",
name="type",
field=models.SmallIntegerField(
choices=[(0, "System"), (1, "User"), (2, "Document"), (3, "Action")]
),
),
]

View File

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

View File

@ -0,0 +1,20 @@
# Generated by Django 5.0.6 on 2024-07-29 15:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("evidence", "0002_alter_annotation_type"),
]
operations = [
migrations.AlterField(
model_name="annotation",
name="type",
field=models.SmallIntegerField(
choices=[(0, "System"), (1, "User"), (2, "Document")]
),
),
]

View File

@ -56,6 +56,7 @@ class Annotation(models.Model):
class Type(models.IntegerChoices):
SYSTEM= 0, "System"
USER = 1, "User"
DOCUMENT = 2, "Document"
created = models.DateTimeField(auto_now_add=True)
uuid = models.UUIDField()
@ -68,8 +69,3 @@ class Annotation(models.Model):
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

View File

@ -1,4 +1,4 @@
# Generated by Django 5.0.6 on 2024-07-17 14:57
# Generated by Django 5.0.6 on 2024-07-27 16:23
import django.db.models.deletion
from django.conf import settings
@ -10,11 +10,58 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
("device", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Lot",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(auto_now_add=True)),
("updated", models.DateTimeField(auto_now=True)),
("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)),
("closed", models.BooleanField(default=True)),
(
"owner",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
),
migrations.CreateModel(
name="DeviceLot",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("device_id", models.CharField(max_length=256)),
(
"lot",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="lot.lot"
),
),
],
),
migrations.CreateModel(
name="LotTag",
fields=[
@ -37,38 +84,11 @@ class Migration(migrations.Migration):
),
],
),
migrations.CreateModel(
name="Lot",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(auto_now_add=True)),
("updated", models.DateTimeField(auto_now=True)),
("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)),
("closed", models.BooleanField(default=True)),
("devices", models.ManyToManyField(to="device.device")),
(
"owner",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
(
"type",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="lot.lottag"
),
),
],
migrations.AddField(
model_name="lot",
name="type",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="lot.lottag"
),
),
]

View File

@ -1,4 +1,4 @@
# Generated by Django 5.0.6 on 2024-07-17 14:57
# Generated by Django 5.0.6 on 2024-07-29 15:37
import django.db.models.deletion
from django.conf import settings
@ -7,15 +7,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("lot", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Device",
name="LotAnnotation",
fields=[
(
"id",
@ -26,7 +25,21 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("type", models.CharField(blank=True, max_length=64, null=True)),
("created", models.DateTimeField(auto_now_add=True)),
(
"type",
models.SmallIntegerField(
choices=[(0, "System"), (1, "User"), (2, "Document")]
),
),
("key", models.CharField(max_length=256)),
("value", models.CharField(max_length=256)),
(
"lot",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="lot.lot"
),
),
(
"owner",
models.ForeignKey(

View File

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

View File

@ -43,3 +43,16 @@ class Lot(models.Model):
for d in DeviceLot.objects.filter(lot=self, device_id=v):
d.delete()
class LotAnnotation(models.Model):
class Type(models.IntegerChoices):
SYSTEM= 0, "System"
USER = 1, "User"
DOCUMENT = 2, "Document"
created = models.DateTimeField(auto_now_add=True)
lot = models.ForeignKey(Lot, 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)
value = models.CharField(max_length=STR_EXTEND_SIZE)

View File

@ -0,0 +1,48 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col">
<h3>Lot {{ lot.name }}</h3>
</div>
</div>
<div class="row">
<div class="tab-pane fade show active" id="details">
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
<a href="{% url 'lot:add_annotation' lot.pk %}" class="btn btn-primary">
<i class="bi bi-plus"></i>
Add new annotation
<span class="caret"></span>
</a>
</div>
<h5 class="card-title mt-2">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 annotations %}
<tr>
<td>{{ a.key }}</td>
<td>{{ a.value }}</td>
<td>{{ a.created }}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col">
<h3>Lot {{ lot.name }}</h3>
</div>
</div>
<div class="row">
<div class="tab-pane fade show active" id="details">
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
<a href="{% url 'lot:add_document' lot.pk %}" class="btn btn-primary">
<i class="bi bi-plus"></i>
Add new document
<span class="caret"></span>
</a>
</div>
<h5 class="card-title mt-2">Documents</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 documents %}
<tr>
<td>{{ a.key }}</td>
<td>{{ a.value }}</td>
<td>{{ a.created }}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col">
<h3>{{ subtitle }}</h3>
</div>
</div>
{% load django_bootstrap5 %}
<form role="form" method="post">
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
<div class="message">
{% for field, error in form.errors.items %}
{{ error }}<br />
{% endfor %}
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
</div>
</div>
{% endif %}
{{ form.management_form }}
<div class="container" id="formset-container">
<div class="row mb-2">
<div class="col"></div>
</div>
{% for f in form %}
<div class="row mb-2">
<div class="col">
{% bootstrap_field f %}
</div>
</div>
{% endfor %}
</div>
<div class="container">
<a class="btn btn-grey" href="{% url 'dashboard:unassigned_devices' %}">{% translate "Cancel" %}</a>
<input class="btn btn-green-admin" type="submit" name="submit" value="{% translate 'Save' %}" />
</div>
</form>
{% endblock %}

View File

@ -10,4 +10,8 @@ urlpatterns = [
path("add/devices/", views.AddToLotView.as_view(), name="add_devices"),
path("del/devices/", views.DelToLotView.as_view(), name="del_devices"),
path("tag/<int:pk>/", views.LotsTagsView.as_view(), name="tag"),
path("<int:pk>/document/", views.LotDocumentsView.as_view(), name="documents"),
path("<int:pk>/document/add", views.LotAddDocumentView.as_view(), name="add_document"),
path("<int:pk>/annotation", views.LotAnnotationsView.as_view(), name="annotations"),
path("<int:pk>/annotation/add", views.LotAddAnnotationView.as_view(), name="add_annotation"),
]

View File

@ -9,7 +9,7 @@ from django.views.generic.edit import (
FormView,
)
from dashboard.mixins import DashboardView
from lot.models import Lot, LotTag
from lot.models import Lot, LotTag, LotAnnotation
from lot.forms import LotsForm
@ -134,3 +134,94 @@ class LotsTagsView(DashboardView, TemplateView):
})
return context
class LotAddDocumentView(DashboardView, CreateView):
template_name = "new_annotation.html"
title = _("New Document")
breadcrumb = "Device / New document"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = LotAnnotation
fields = ("key", "value")
def form_valid(self, form):
form.instance.owner = self.request.user
form.instance.lot = self.lot
form.instance.type = LotAnnotation.Type.DOCUMENT
response = super().form_valid(form)
return response
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
self.lot = get_object_or_404(Lot, pk=pk, owner=self.request.user)
self.success_url = reverse_lazy('lot:documents', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs
class LotDocumentsView(DashboardView, TemplateView):
template_name = "documents.html"
title = _("New Document")
breadcrumb = "Device / New document"
def get_context_data(self, **kwargs):
self.pk = kwargs.get('pk')
context = super().get_context_data(**kwargs)
lot = get_object_or_404(Lot, owner=self.request.user, id=self.pk)
documents = LotAnnotation.objects.filter(
lot=lot,
owner=self.request.user,
type=LotAnnotation.Type.DOCUMENT,
)
context.update({
'lot': lot,
'documents': documents,
'title': self.title,
'breadcrumb': self.breadcrumb
})
return context
class LotAnnotationsView(DashboardView, TemplateView):
template_name = "annotations.html"
title = _("New Annotation")
breadcrumb = "Device / New annotation"
def get_context_data(self, **kwargs):
self.pk = kwargs.get('pk')
context = super().get_context_data(**kwargs)
lot = get_object_or_404(Lot, owner=self.request.user, id=self.pk)
annotations = LotAnnotation.objects.filter(
lot=lot,
owner=self.request.user,
type=LotAnnotation.Type.USER,
)
context.update({
'lot': lot,
'annotations': annotations,
'title': self.title,
'breadcrumb': self.breadcrumb
})
return context
class LotAddAnnotationView(DashboardView, CreateView):
template_name = "new_annotation.html"
title = _("New Annotation")
breadcrumb = "Device / New annotation"
success_url = reverse_lazy('dashboard:unassigned_devices')
model = LotAnnotation
fields = ("key", "value")
def form_valid(self, form):
form.instance.owner = self.request.user
form.instance.lot = self.lot
form.instance.type = LotAnnotation.Type.USER
response = super().form_valid(form)
return response
def get_form_kwargs(self):
pk = self.kwargs.get('pk')
self.lot = get_object_or_404(Lot, pk=pk, owner=self.request.user)
self.success_url = reverse_lazy('lot:annotations', args=[pk])
kwargs = super().get_form_kwargs()
return kwargs