diff --git a/Lagerregal/settings/template_production.py b/Lagerregal/settings/template_production.py
index e87f331b..c6c8d749 100644
--- a/Lagerregal/settings/template_production.py
+++ b/Lagerregal/settings/template_production.py
@@ -105,7 +105,8 @@
DATA_PROVIDERS = {
'opsi': 'devicedata.providers.opsi.OpsiProvider',
- 'puppet': 'devicedata.providers.puppet.PuppetProvide',
+ 'puppet': 'devicedata.providers.puppet.PuppetProvider',
+ 'baramundi': 'devicedata.providers.baramundi.BaramundiProvider',
}
PUPPETDB_SETTINGS = {
@@ -124,6 +125,13 @@
"port": "4447",
}
+BARAMUNDI_SETTINGS = {
+ "host": "https://baramundi.mpib-berlin.mpg.de",
+ "port": "443",
+ "ignore_ssl": True,
+ "authorization": ""
+}
+
HOST_BASE_DOMAIN = "mpib-berlin.mpg.de"
# sample logger
diff --git a/Lagerregal/urls.py b/Lagerregal/urls.py
index 2db2de73..285de65c 100644
--- a/Lagerregal/urls.py
+++ b/Lagerregal/urls.py
@@ -4,10 +4,13 @@
from django.contrib.auth.decorators import login_required
from django.urls import include
from django.urls import path
+from django.urls import re_path
from django.views.decorators.clickjacking import xframe_options_exempt
+from django.views.generic import RedirectView
from django.views.i18n import JavaScriptCatalog
from django.views.static import serve
+from favicon import conf
from rest_framework.urlpatterns import format_suffix_patterns
from api import views as api_views
@@ -163,7 +166,7 @@
path('oauth2/', include('oauth2_provider.urls', namespace='oauth2_provider')),
- path('', include('favicon.urls')),
+ re_path(r'^favicon\.ico$', RedirectView.as_view(url=conf.FAVICON_PATH, permanent=True), name='favicon'),
path('devices_ajax/add_widget/', login_required(main_ajax.WidgetAdd.as_view()), name="widget_add"),
path('devices_ajax/remove_widget/', login_required(main_ajax.WidgetRemove.as_view()), name="widget_remove"),
diff --git a/README.md b/README.md
index e590e124..cea8f04d 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Features
+ Generates and prints Dymo labels from templates for inventory stickers
+ Manage static IP addresses for legacy network environments
+ Semi-Automatic e-mail delivery (on lending, trashing etc)
-+ Optional query and listing for puppet facts or opsi details of a device
++ Optional query and listing of device data from puppet, opsi or baramundi
+ Permission system for users and public device lists
+ Themable with bootswatch
diff --git a/api/views.py b/api/views.py
index 25d5bb06..08c81040 100644
--- a/api/views.py
+++ b/api/views.py
@@ -5,7 +5,7 @@
from django.contrib.auth.models import Group
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
import rest_framework.reverse
from rest_framework import generics
diff --git a/devicedata/ajax.py b/devicedata/ajax.py
index f04ff59c..def9933a 100644
--- a/devicedata/ajax.py
+++ b/devicedata/ajax.py
@@ -5,7 +5,7 @@
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from django.utils.timesince import timesince
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic.base import View
from devicedata.generic import _get_provider
@@ -45,7 +45,7 @@ def get(request, device):
raw_entries = [{"name": entry.name,
"type": entry.type,
"raw_value": as_nested_list(entry.raw_value)} for entry in device_info.raw_entries]
- new_entries = _update_provided_data(device, device_info)
+ new_entries = _update_provided_data(device, device_info, True)
formatted_entries = [{"name": entry.name,
"value": entry.formatted_value,
"stored_at": timesince(entry.stored_at)} for entry in new_entries]
@@ -58,8 +58,11 @@ class DeviceSoftware(View):
@staticmethod
def get(request, device):
device = get_object_or_404(Device, pk=device)
+ provider = _get_provider(device)
+ if provider is None:
+ return JsonResponse({})
try:
- software_info = _get_provider(device).get_software_info(device)
+ software_info = provider.get_software_info(device)
except Exception as e:
logger.error(e)
return HttpResponse(_("Could not load data."))
diff --git a/devicedata/generic.py b/devicedata/generic.py
index b3bfcf91..2c1a8ed4 100644
--- a/devicedata/generic.py
+++ b/devicedata/generic.py
@@ -17,12 +17,12 @@ def _get_provider(device):
def _update_provided_data(device, data, force=False):
+ old_data = device.provided_data.all()
if not force:
- old_data = device.provided_data.all()
if len(old_data) > 0:
if (timezone.now() - old_data[0].stored_at).days < 7:
return old_data
- device.provided_data.all().delete()
+ old_data.delete()
for entry in data.formatted_entries:
pd = ProvidedData()
pd.device = device
diff --git a/devicedata/providers/baramundi.py b/devicedata/providers/baramundi.py
new file mode 100644
index 00000000..c8eb7a97
--- /dev/null
+++ b/devicedata/providers/baramundi.py
@@ -0,0 +1,132 @@
+import base64
+from unicodedata import name
+
+from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+from django.utils.translation import gettext_lazy as _
+
+import requests
+
+from devicedata.providers.base_provider import BaseDeviceInfo
+from devicedata.providers.base_provider import BaseProvider
+from devicedata.providers.base_provider import DeviceInfoEntry
+from devicedata.providers.base_provider import FormattedDeviceInfoEntry
+from devicedata.providers.helpers import format_bytes
+
+
+class BaramundiDeviceInfo(BaseDeviceInfo):
+ def format_serialnumber(self):
+ self.simple_format('SerialNumber', _('Serial Number'))
+
+ def format_hostname(self):
+ self.simple_format('HostName', _('Hostname'))
+
+ def format_type(self):
+ self.simple_format('ModelName', _('Type'))
+
+ def format_lastseen(self):
+ self.simple_format('LastSeen', _('Last Seen'))
+
+ def format_processor(self):
+ self.simple_format('CPUDescription', _('Processor'))
+
+ def format_memory(self):
+ entries = self.find_entries("TotalMemory")
+ if len(entries) > 0:
+ self.formatted_entries.append(
+ FormattedDeviceInfoEntry(_("Memory"), format_bytes(entries[0].raw_value * 1024 * 1024)))
+
+ def format_storage(self):
+ entries = self.find_entries("StorageMedia")
+ drives = []
+ for entry in entries:
+ for disk in entry.raw_value:
+ if "ByteSize" in disk and disk["ByteSize"] < 1000000000:
+ # Smaller than 10gb. This most likely is not a hard drive.
+ continue
+ drives.append(disk)
+ formatted_capacities = "
".join(
+ ["{0}: {1}".format(drive["Name"], format_bytes(drive["ByteSize"])) for drive in drives])
+ self.formatted_entries.append(FormattedDeviceInfoEntry(_("Storage"), formatted_capacities))
+
+ def format_entries(self):
+ self.format_serialnumber()
+ self.format_hostname()
+ self.format_lastseen()
+ self.format_processor()
+ self.format_memory()
+ self.format_storage()
+
+class BaramundiProvider(BaseProvider):
+ name = "baramundi"
+
+ @staticmethod
+ def __run_query(url):
+ if not hasattr(settings, "BARAMUNDI_SETTINGS"):
+ return
+
+ host = settings.BARAMUNDI_SETTINGS['host'] + ":" + str(settings.BARAMUNDI_SETTINGS['port'])
+ full_url = url %host
+ if 'authorization' in settings.BARAMUNDI_SETTINGS:
+ authorization = settings.BARAMUNDI_SETTINGS['authorization']
+ else:
+ authorization = ('{}:{}'.format(settings.BARAMUNDI_SETTINGS['user_name'], settings.BARAMUNDI_SETTINGS['password'])).encode('ascii')
+ authorization = base64.b64encode(authorization).decode('ascii')
+ session = requests.Session()
+ session.headers.update({'Authorization': 'Basic {}'.format(authorization), 'content-type': "application/json; charset=utf-8"})
+
+ print(full_url, settings.BARAMUNDI_SETTINGS['ignore_ssl'] is not True)
+ result = session.get(full_url, verify=settings.BARAMUNDI_SETTINGS['ignore_ssl'] is not True)
+ body = result.json()
+ if len(body) == 0:
+ raise ObjectDoesNotExist()
+ return body
+
+ def _get_device_id(self, device):
+ if len(device.hostname) > 0:
+ term = device.hostname
+ else:
+ term = '{:06d}'.format(device.id)
+ try:
+ data = self.__run_query('https://%s/bConnect/v1.0/search.json?type=endpoint&term=' + term)
+ print(data)
+ return data[0]['Id']
+ except ObjectDoesNotExist:
+ print("no object")
+ return None
+ except KeyError as e:
+ print(e)
+ return None
+
+ def get_device_info(self, device):
+ if not hasattr(settings, "BARAMUNDI_SETTINGS"):
+ return
+ id = self._get_device_id(device)
+ if id is None:
+ return
+ info = self.__run_query('https://%s/bConnect/v1.0/endpoints.json?id=' + id)
+ device_entries = []
+ for key in info:
+ device_entries.append(DeviceInfoEntry(key, None, info[key]))
+ return BaramundiDeviceInfo(device, device_entries)
+
+ def get_software_info(self, device):
+ return
+ if not hasattr(settings, "BARAMUNDI_SETTINGS"):
+ return
+ id = self._get_device_id(device)
+ if id is None:
+ return
+ info = self.__run_query('https://%s/bConnect/v1.0/softwarescanrules.json?id=' + id)
+ print(info)
+ return super().get_software_info(device)
+
+ def has_device(self, device):
+ if not hasattr(settings, "BARAMUNDI_SETTINGS"):
+ return False
+ try:
+ id = self._get_device_id(device)
+ print(id)
+ return id is not None and len(id) > 0
+ except ObjectDoesNotExist:
+ return False
\ No newline at end of file
diff --git a/devicedata/providers/base_provider.py b/devicedata/providers/base_provider.py
index 1d48a7d9..40371417 100644
--- a/devicedata/providers/base_provider.py
+++ b/devicedata/providers/base_provider.py
@@ -12,6 +12,11 @@ class BaseDeviceInfo(ABC):
def find_entries(self, entry_type):
return [entry for entry in self.raw_entries if entry.type == entry_type]
+ def simple_format(self, entry_type, name):
+ entries = self.find_entries(entry_type)
+ if len(entries) > 0:
+ self.formatted_entries.append((FormattedDeviceInfoEntry(name, entries[0].raw_value)))
+
def __init__(self, device, raw_entries):
self.device = device
self.formatted_entries = []
diff --git a/devicedata/providers/helpers.py b/devicedata/providers/helpers.py
index 8061138d..b659f4b5 100644
--- a/devicedata/providers/helpers.py
+++ b/devicedata/providers/helpers.py
@@ -5,4 +5,4 @@ def format_bytes(size, power=2**10):
while size > power:
size /= power
n += 1
- return "{0:g}{1}".format(size, power_labels[n] + "B")
+ return "{0:.2f}{1}".format(size, power_labels[n] + "B")
diff --git a/devicedata/providers/opsi.py b/devicedata/providers/opsi.py
index 43ee9fb9..1f6b3170 100644
--- a/devicedata/providers/opsi.py
+++ b/devicedata/providers/opsi.py
@@ -1,6 +1,6 @@
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from devicedata.providers.base_provider import BaseDeviceInfo
from devicedata.providers.base_provider import BaseProvider
diff --git a/devicedata/providers/puppet.py b/devicedata/providers/puppet.py
index 36d702f4..9e140057 100644
--- a/devicedata/providers/puppet.py
+++ b/devicedata/providers/puppet.py
@@ -6,7 +6,7 @@
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
import requests
@@ -28,9 +28,7 @@ def format_serialnumber(self):
self.formatted_entries.append(FormattedDeviceInfoEntry(_("Serial Number"), entries[0].raw_value))
def format_type(self):
- entries = self.find_entries("sp_machine_name")
- if len(entries) > 0:
- self.formatted_entries.append(FormattedDeviceInfoEntry(_("Type"), entries[0].raw_value))
+ self.simple_format('sp_machine_name', _('Type'))
def format_hostname(self):
entries = self.find_entries("fqdn")
@@ -43,9 +41,7 @@ def format_hostname(self):
self.formatted_entries.append(FormattedDeviceInfoEntry(_("Hostname"), entries[0].raw_value))
def format_lastseen(self):
- entries = self.find_entries("timestamp")
- if len(entries) > 0:
- self.formatted_entries.append(FormattedDeviceInfoEntry(_("Last Seen"), entries[0].raw_value))
+ self.simple_format('timestamp', _('Last Seen'))
def format_processor(self):
entries = self.find_entries("processors")
diff --git a/devicegroups/models.py b/devicegroups/models.py
index 145507e0..e1b15772 100644
--- a/devicegroups/models.py
+++ b/devicegroups/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from reversion import revisions as reversion
diff --git a/devicegroups/views.py b/devicegroups/views.py
index b63aa0f9..e374906a 100644
--- a/devicegroups/views.py
+++ b/devicegroups/views.py
@@ -2,7 +2,7 @@
from django.db.models import Q
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView
diff --git a/devices/forms.py b/devices/forms.py
index 37d616d3..eaaf700e 100644
--- a/devices/forms.py
+++ b/devices/forms.py
@@ -7,7 +7,7 @@
from django.db.utils import OperationalError
from django.db.utils import ProgrammingError
from django.shortcuts import get_object_or_404
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django_select2.forms import Select2MultipleWidget
from django_select2.forms import Select2Widget
diff --git a/devices/models.py b/devices/models.py
index 0b6f49b0..271ff888 100644
--- a/devices/models.py
+++ b/devices/models.py
@@ -5,7 +5,7 @@
from django.db.models import Q
from django.urls import reverse
from django.utils.timezone import utc
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
import reversion
diff --git a/devices/views.py b/devices/views.py
index a38ecb61..b9e88893 100644
--- a/devices/views.py
+++ b/devices/views.py
@@ -24,7 +24,7 @@
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.timesince import timesince
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView
@@ -725,14 +725,14 @@ def form_valid(self, form):
try:
templates.append(MailTemplate.objects.get(usage="lent"))
except:
- messages.error(self.request, _('MAIL NOT SENT - Template for lent devices does not exist for your main department'))
+ messages.error(self.request, _('MAIL NOT SENT - Template for lent devices does not exist'))
if form.cleaned_data["room"]:
device.room = form.cleaned_data["room"]
try:
templates.append(MailTemplate.objects.get(usage="room"))
except:
- messages.error(self.request, _('MAIL NOT SENT - Template for room change does not exist for your main department'))
+ messages.error(self.request, _('MAIL NOT SENT - Template for room change does not exist'))
if templates:
for template in templates:
template.send(self.request, data={"device": device, "user": self.request.user})
@@ -816,13 +816,13 @@ def form_valid(self, form):
try:
templates.append(MailTemplate.objects.get(usage="returned"))
except:
- messages.error(self.request, _('MAIL NOT SENT - Template for returned device does not exist for your main department'))
+ messages.error(self.request, _('MAIL NOT SENT - Template for returned device does not exist'))
if form.cleaned_data["room"]:
device.room = form.cleaned_data["room"]
try:
templates.append(MailTemplate.objects.get(usage="room"))
except:
- messages.error(self.request, _('MAIL NOT SENT - Template for room change does not exist for your main department'))
+ messages.error(self.request, _('MAIL NOT SENT - Template for room change does not exist'))
if templates:
for template in templates:
template.send(self.request, data={"device": device, "user": self.request.user})
diff --git a/devicetags/models.py b/devicetags/models.py
index 39c5e462..2fb077a8 100644
--- a/devicetags/models.py
+++ b/devicetags/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from devices.models import Device
diff --git a/devicetags/views.py b/devicetags/views.py
index bffad4bd..c6f01281 100644
--- a/devicetags/views.py
+++ b/devicetags/views.py
@@ -3,7 +3,7 @@
from django.shortcuts import render
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import FormView
diff --git a/devicetypes/models.py b/devicetypes/models.py
index 56485154..ca916d9f 100644
--- a/devicetypes/models.py
+++ b/devicetypes/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from reversion import revisions as reversion
diff --git a/devicetypes/views.py b/devicetypes/views.py
index d7ad9d0b..7c517b4d 100644
--- a/devicetypes/views.py
+++ b/devicetypes/views.py
@@ -4,7 +4,7 @@
from django.shortcuts import render
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView
diff --git a/history/views.py b/history/views.py
index 762fc591..2f136609 100644
--- a/history/views.py
+++ b/history/views.py
@@ -5,7 +5,7 @@
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import ListView
from django.views.generic import UpdateView
diff --git a/locations/models.py b/locations/models.py
index 559c5137..8cf303ec 100644
--- a/locations/models.py
+++ b/locations/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
import reversion
diff --git a/locations/views.py b/locations/views.py
index 030ef661..7674a001 100644
--- a/locations/views.py
+++ b/locations/views.py
@@ -5,7 +5,7 @@
from django.shortcuts import render
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView
diff --git a/mail/models.py b/mail/models.py
index f981dfb1..4686da33 100644
--- a/mail/models.py
+++ b/mail/models.py
@@ -5,7 +5,7 @@
from django.db import models
from django.urls import reverse
from django.utils import timezone
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
import pystache
diff --git a/mail/views.py b/mail/views.py
index 83450520..0cb9d3e8 100644
--- a/mail/views.py
+++ b/mail/views.py
@@ -2,7 +2,7 @@
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView
diff --git a/main/models.py b/main/models.py
index aa1d0c0d..097eb9b2 100644
--- a/main/models.py
+++ b/main/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.db.models.signals import post_save
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from users.models import Lageruser
diff --git a/main/views.py b/main/views.py
index 91f3a603..0015afd3 100644
--- a/main/views.py
+++ b/main/views.py
@@ -2,7 +2,7 @@
from django.db.models import Q
from django.shortcuts import redirect
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import TemplateView
from reversion.models import Revision
diff --git a/network/forms.py b/network/forms.py
index 6f7f836b..f4e00926 100644
--- a/network/forms.py
+++ b/network/forms.py
@@ -1,5 +1,5 @@
from django import forms
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django_select2.forms import Select2MultipleWidget
diff --git a/network/models.py b/network/models.py
index 67556efd..06e250f0 100644
--- a/network/models.py
+++ b/network/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from reversion import revisions as reversion
diff --git a/network/views.py b/network/views.py
index 71eb1ade..46b5b60c 100644
--- a/network/views.py
+++ b/network/views.py
@@ -4,7 +4,7 @@
from django.shortcuts import render
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView
diff --git a/package-lock.json b/package-lock.json
index 7ceba260..2e78a201 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,7 +1,106 @@
{
"name": "lagerregal",
+ "lockfileVersion": 2,
"requires": true,
- "lockfileVersion": 1,
+ "packages": {
+ "": {
+ "name": "lagerregal",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "alpinejs": "^2.8.2",
+ "bootstrap": "^4.6.0",
+ "bootswatch": "^4.6.0",
+ "datatables.net": "^1.10.24",
+ "datatables.net-bs4": "^1.10.24",
+ "font-awesome": "^4.7.0",
+ "jquery": "^3.6.0",
+ "jquery-ui-dist": "^1.12.1",
+ "noty": "^2.4.1",
+ "popper.js": "^1.16.1",
+ "print-js": "^1.5.0",
+ "select2": "^4.0.13",
+ "timeago": "^1.6.7"
+ }
+ },
+ "node_modules/alpinejs": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-2.8.2.tgz",
+ "integrity": "sha512-5yOUtckn4CBp0qsHpo2qgjZyZit84uXvHbB7NJ27sn4FA6UlFl2i9PGUAdTXkcbFvvxDJBM+zpOD8RuNYFvQAw=="
+ },
+ "node_modules/bootstrap": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz",
+ "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw=="
+ },
+ "node_modules/bootswatch": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/bootswatch/-/bootswatch-4.6.0.tgz",
+ "integrity": "sha512-Yr6YqFBC8jwTzoJoLViYlvO97IhPWGqZEm+6FXHfD/G6gbUok6sZkdXxdh4Zb6iCGEwr9p7zGCn38yKQD/bh2Q=="
+ },
+ "node_modules/datatables.net": {
+ "version": "1.10.25",
+ "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.25.tgz",
+ "integrity": "sha512-y0+C7all+MC/h1acwnjErhaJPjYGKpWTvbXrfEUbR8+P+nnhgjNn5nL1udgsTwBObMhlj1KITNBRrM/ZLSoj+Q==",
+ "dependencies": {
+ "jquery": ">=1.7"
+ }
+ },
+ "node_modules/datatables.net-bs4": {
+ "version": "1.10.25",
+ "resolved": "https://registry.npmjs.org/datatables.net-bs4/-/datatables.net-bs4-1.10.25.tgz",
+ "integrity": "sha512-leoiWJWxoPKHBNC9dkFRE84PRybQcAI2Aw4UiS5zisROcYRx8YG1uQOTtID4jbqakmbwwXap/c2eH+sdVP5t2w==",
+ "dependencies": {
+ "datatables.net": "1.10.25",
+ "jquery": ">=1.7"
+ }
+ },
+ "node_modules/font-awesome": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+ "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=",
+ "engines": {
+ "node": ">=0.10.3"
+ }
+ },
+ "node_modules/jquery": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
+ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
+ },
+ "node_modules/jquery-ui-dist": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz",
+ "integrity": "sha1-XAgV08xvkP9fqvWyaKbiO0ypBPo="
+ },
+ "node_modules/noty": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/noty/-/noty-2.4.1.tgz",
+ "integrity": "sha1-Qyf7CYX+k/aq25KfpoB/o8zYagc="
+ },
+ "node_modules/popper.js": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+ "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
+ },
+ "node_modules/print-js": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz",
+ "integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg=="
+ },
+ "node_modules/select2": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.13.tgz",
+ "integrity": "sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw=="
+ },
+ "node_modules/timeago": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/timeago/-/timeago-1.6.7.tgz",
+ "integrity": "sha512-FikcjN98+ij0siKH4VO4dZ358PR3oDDq4Vdl1+sN9gWz1/+JXGr3uZbUShYH/hL7bMhcTpPbplJU5Tej4b4jbQ==",
+ "dependencies": {
+ "jquery": ">=1.5.0 <4.0"
+ }
+ }
+ },
"dependencies": {
"alpinejs": {
"version": "2.8.2",
diff --git a/package.json b/package.json
index 2275f521..d3c852f7 100644
--- a/package.json
+++ b/package.json
@@ -11,8 +11,8 @@
"jquery": "^3.6.0",
"jquery-ui-dist": "^1.12.1",
"popper.js": "^1.16.1",
+ "print-js": "^1.5.0",
"select2": "^4.0.13",
- "timeago": "^1.6.7",
- "print-js": "^1.5.0"
+ "timeago": "^1.6.7"
}
}
diff --git a/requirements.txt b/requirements.txt
index 0cad44f3..11af6a90 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
-django ~= 3.2.0
-django-reversion >= 2.0.10
-djangorestframework >= 3.6.4
+django ~= 4.0
+django-reversion >= 4.0.0
+djangorestframework >= 3.13.0
Pillow
django-oauth-toolkit
pytz == 2020.4
@@ -14,4 +14,4 @@ psycopg2-binary
faker~=4.1.1
reportlab
requests
-pdfrw
+pdfrw
\ No newline at end of file
diff --git a/templates/base.html b/templates/base.html
index a9855879..383af9a3 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -4,7 +4,7 @@
{% trans "Loading Device Details..." %}
-
+
| {% trans "Type" %} |
diff --git a/templates/devices/detail/device_detail.html b/templates/devices/detail/device_detail.html
index 5f8a7002..fd36dd99 100644
--- a/templates/devices/detail/device_detail.html
+++ b/templates/devices/detail/device_detail.html
@@ -166,51 +166,13 @@
-
- | {% trans "Lagerregal ID" %} |
- {{ device.pk }} |
-
-
- | {% trans "Inventorynumber" %} |
- {{ device.inventorynumber }} |
-
-
- | {% trans "Serialnumber" %} |
- {{ device.serialnumber }} |
-
-
- | {% trans "Hostname" %} |
- {{ device.hostname }} |
-
-
- | {% trans "Devicetype" %} |
-
- {% if device.devicetype %}
- {{ device.devicetype }}
- {% else %}
- —
- {% endif %}
- |
-
-
- | {% trans "Manufacturer" %} |
-
- {% if device.manufacturer %}
- {{ device.manufacturer }}
- {% else %}
- —
- {% endif %}
- |
-
- | {% trans "Room" %} |
-
- {% if device.room %}
- {{ device.room }}
- {% else %}
- —
- {% endif %}
- |
-
+{% include 'devices/detail/device_detail_table_entry.html' with name='Laggerregal ID' value=device.id %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Inventorynumber' value=device.inventorynumber %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Serialnumber' value=device.serialnumber %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Hostname' value=device.hostname %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Devicetype' value=device.devicetype url='type-detail' url_key=device.devicetype.pk %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Manufacturer' value=device.manufacturer url='manufacturer-detail' url_key=device.manufacturer.pk %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Room' value=device.room url='room-detail' url_key=device.room.pk %}
{% if device.used_in %}
| {% trans "Used in" %} |
@@ -227,26 +189,8 @@
{% endif %}
-
- | {% trans "Devicegroup" %} |
-
- {% if device.group %}
- {{ device.group }}
- {% else %}
- —
- {% endif %}
- |
-
-
- | {% trans "Department" %} |
-
- {% if device.department %}
- {{ device.department }}
- {% else %}
- —
- {% endif %}
- |
-
+{% include 'devices/detail/device_detail_table_entry.html' with name='Devicegroup' value=device.devicegroup url='devicegroup-detail' url_key=device.devicegroup.pk %}
+{% include 'devices/detail/device_detail_table_entry.html' with name='Department' value=device.department %}
| {% trans "Short term device" %} |
@@ -293,10 +237,7 @@
|
{% if device.trashed %}
-
- | {% trans "Trashed on" %} |
- {{ device.trashed }} |
-
+ {% include 'devices/detail/device_detail_table_entry.html' with name='Trashed on' value=device.trashed %}
{% endif %}
{% if device.inventoried %}
@@ -321,7 +262,7 @@
-
+
|
|
diff --git a/templates/devices/detail/device_detail.js b/templates/devices/detail/device_detail.js
index 019877a1..2b6de2de 100644
--- a/templates/devices/detail/device_detail.js
+++ b/templates/devices/detail/device_detail.js
@@ -9,6 +9,7 @@ function loadAdditionalData(adata) {
adata.provided_data = data.formatted_entries;
}
if (data.raw_entries) {
+ console.log(data.raw_entries);
adata.raw_provided_data = data.raw_entries;
}
}).fail(function() {
diff --git a/templates/devices/detail/device_detail_table_entry.html b/templates/devices/detail/device_detail_table_entry.html
new file mode 100644
index 00000000..bcb8117c
--- /dev/null
+++ b/templates/devices/detail/device_detail_table_entry.html
@@ -0,0 +1,13 @@
+{% load i18n %}
+
+ | {% trans name %} |
+
+ {% if url and value %}
+ {{ value }}
+ {% elif value %}
+ {{ value }}
+ {% else %}
+ —
+ {% endif %}
+ |
+
\ No newline at end of file
diff --git a/users/forms.py b/users/forms.py
index 02575854..02bc51f9 100644
--- a/users/forms.py
+++ b/users/forms.py
@@ -1,7 +1,7 @@
from django import forms
from django.conf import settings
-from django.utils.translation import ugettext
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext
+from django.utils.translation import gettext_lazy as _
from users.models import DepartmentUser
from users.models import Lageruser
@@ -20,8 +20,8 @@ class Meta:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.fields["timezone"].choices[0] = ("", ugettext("Default ({0})".format(settings.TIME_ZONE)))
- self.fields["timezone"].widget.choices[0] = ("", ugettext("Default ({0})".format(settings.TIME_ZONE)))
+ self.fields["timezone"].choices[0] = ("", gettext("Default ({0})".format(settings.TIME_ZONE)))
+ self.fields["timezone"].widget.choices[0] = ("", gettext("Default ({0})".format(settings.TIME_ZONE)))
class AvatarForm(forms.ModelForm):
diff --git a/users/models.py b/users/models.py
index 33905845..9c3dd9fd 100644
--- a/users/models.py
+++ b/users/models.py
@@ -8,7 +8,7 @@
from django.db import models
from django.dispatch import receiver
from django.urls import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
import pytz
from django_auth_ldap.backend import populate_user
diff --git a/users/views.py b/users/views.py
index 4dd7d82a..af813a89 100644
--- a/users/views.py
+++ b/users/views.py
@@ -9,7 +9,7 @@
from django.shortcuts import render
from django.urls import reverse
from django.urls import reverse_lazy
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView
from django.views.generic import DeleteView
from django.views.generic import DetailView