From c263dc0ae0c763241e7adbc4b2512e57e4c793c3 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Fri, 18 Nov 2022 10:18:54 +0100
Subject: [PATCH 01/49] changelog
---
CHANGELOG.md | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d69d4a2..044b40bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,24 @@ ml).
## testing
+## [2.4.3] - 2022-11-18
+- [added] #386 add registration module.
+- [added] #387 add template settings for Secure Erasure.
+- [added] #397 add obada standard export.
+- [added] #402 add reset password module.
+- [changed] #391 add dhid in table and export of Erasure section.
+- [changed] #395 change response for the new api to workbench.
+- [changed] #396 modularize commands.
+- [fixed] #388 lock update different motherboard with the same id.
+- [fixed] #389 some datastorage without placeholder.
+- [fixed] #390 fix image in form edit device.
+- [fixed] #398 placeholder in new components.
+- [fixed] #399 add api_host in config.
+- [fixed] #401 db_host need to be api address.
+- [fixed] #403 change delimiter in obada export.
+- [fixed] #404 javascript select all devices.
+- [fixed] #405 update pillow.
+
## [2.4.2] - 2022-10-18
- [added] #373 Enhancement - UX Lots.
- [added] #377 add prefix in lots in device list.
From d1eed13b0a236a18004b49272e1044a5948e3a87 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Fri, 18 Nov 2022 18:46:10 +0100
Subject: [PATCH 02/49] tabs
---
.../templates/inventory/erasure_list.html | 29 ++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index e33bed45..29a53d8b 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -18,7 +18,34 @@
-
+
+
+ -
+
+
+
+ -
+ Web
+
+
+ -
+
+
+
+ -
+
+
+
+ -
+
+
+
+ -
+
+
+
+
+
From a09e087b0e13e464aa3455c5f4bae474595f9511 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 13:24:56 +0100
Subject: [PATCH 03/49] add tab for Hard drives without device
---
ereuse_devicehub/inventory/views.py | 14 +++-
ereuse_devicehub/resources/device/models.py | 13 ++++
.../templates/inventory/erasure_list.html | 75 ++++++++++++++-----
3 files changed, 81 insertions(+), 21 deletions(-)
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 93740af5..1d34a7b3 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -115,15 +115,19 @@ class DeviceListMixin(GenericMixin):
class ErasureListView(DeviceListMixin):
template_name = 'inventory/erasure_list.html'
- def dispatch_request(self):
+ def dispatch_request(self, orphans=0):
self.get_context()
- self.get_devices()
+ self.get_devices(orphans)
+ if orphans:
+ self.context['orphans'] = True
return flask.render_template(self.template_name, **self.context)
- def get_devices(self):
+ def get_devices(self, orphans):
erasure = EraseBasic.query.filter_by(author=g.user).order_by(
EraseBasic.created.desc()
)
+ if orphans:
+ erasure = [e for e in erasure if e.device.orphan]
self.context['erasure'] = erasure
@@ -1452,3 +1456,7 @@ devices.add_url_rule(
devices.add_url_rule(
'/device/erasure/', view_func=ErasureListView.as_view('device_erasure_list')
)
+devices.add_url_rule(
+ '/device/erasure//',
+ view_func=ErasureListView.as_view('device_erasure_list_orphans'),
+)
diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py
index 86d8c834..0f398737 100644
--- a/ereuse_devicehub/resources/device/models.py
+++ b/ereuse_devicehub/resources/device/models.py
@@ -1326,6 +1326,19 @@ class DataStorage(JoinedComponentTableMixin, Component):
except LookupError:
return None
+ @property
+ def orphan(self):
+ if not self.parent:
+ return True
+
+ if self.parent.placeholder and self.parent.placeholder.kangaroo:
+ return True
+
+ if self.parent.binding and self.parent.binding.kangaroo:
+ return True
+
+ return False
+
class HardDrive(DataStorage):
pass
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index 29a53d8b..1b55ba97 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -21,33 +21,51 @@
+ {% if orphans %}
+
+
+
+
+
+
+ {% endif %}
+ {% if orphans %}
+
+
+
+
+ {% endif %}
From 35dd08c9c8de0c33a172a89ea0fe7ae163c2baa6 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 15:13:36 +0100
Subject: [PATCH 04/49] fixing add hdd to lot
---
ereuse_devicehub/resources/lot/views.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ereuse_devicehub/resources/lot/views.py b/ereuse_devicehub/resources/lot/views.py
index c3416db2..80922e47 100644
--- a/ereuse_devicehub/resources/lot/views.py
+++ b/ereuse_devicehub/resources/lot/views.py
@@ -306,7 +306,7 @@ class LotDeviceView(LotBaseChildrenView):
dev_qry = Device.query.filter(Device.id.in_(ids)).filter(Device.owner == g.user)
for dev in dev_qry:
- if isinstance(dev, DataStorage) and dev.parent:
+ if isinstance(dev, DataStorage) and not dev.orphan:
continue
devices.add(dev)
From fb430f21383cf272f89d12c36913f64f4fe9cf89 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 15:14:02 +0100
Subject: [PATCH 05/49] add lot to list erasure
---
.../templates/inventory/erasure_list.html | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index 1b55ba97..adaec94f 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -140,11 +140,24 @@
{% if ac.device.phid() %}
+ {% if ac.device.get_type_logo() %}
+
+ {% endif %}
{{ ac.device.serial_number.upper() }}
{% else %}
+ {% if ac.device.get_type_logo() %}
+
+ {% endif %}
{{ ac.device.serial_number.upper() }}
{% endif %}
+ {% if ac.device.lots | length > 0 %}
+
+ {% for lot in ac.device.get_lots_for_template() %}
+ {{ lot }}
+ {% endfor %}
+
+ {% endif %}
|
{% if ac.device.phid() %}
From 6fd87ac8e83520002b38d5d5671e5c0297aafe94 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 15:34:00 +0100
Subject: [PATCH 06/49] fix label dhid
---
ereuse_devicehub/templates/labels/print_labels.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ereuse_devicehub/templates/labels/print_labels.html b/ereuse_devicehub/templates/labels/print_labels.html
index 0e36d68d..e8db7d0c 100644
--- a/ereuse_devicehub/templates/labels/print_labels.html
+++ b/ereuse_devicehub/templates/labels/print_labels.html
@@ -32,7 +32,7 @@
@@ -41,7 +41,7 @@
data-model="{{ dev.model or '' }}"
data-tags="{{ dev.list_tags() }}"
data-phid="{{ dev.phid() }}"
- data-sid="{{ dev.sid or '' }}">{{ dev.devicehub_id }}
+ data-sid="{{ dev.sid or '' }}">{{ dev.dhid }}
@@ -192,7 +192,7 @@
{% endblock main %}
From 0e85b81857b83f9423b745ee9b59e7d5004647bd Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 15:35:37 +0100
Subject: [PATCH 07/49] fix test
---
tests/test_basic.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/test_basic.py b/tests/test_basic.py
index 3d7a0ad8..68c7d696 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -56,6 +56,7 @@ def test_api_docs(client: Client):
'/inventory/device/{id}/',
'/inventory/device/{dhid}/binding/',
'/inventory/device/erasure/',
+ '/inventory/device/erasure/{orphans}/',
'/inventory/all/device/',
'/inventory/export/{export_id}/',
'/inventory/lot/add/',
From 15d9c86104af901959ef9c62fe05157fb887b131 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 17:34:19 +0100
Subject: [PATCH 08/49] add test orphans disks
---
tests/test_render_2_0.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tests/test_render_2_0.py b/tests/test_render_2_0.py
index f9f82928..0a95eee1 100644
--- a/tests/test_render_2_0.py
+++ b/tests/test_render_2_0.py
@@ -2393,6 +2393,19 @@ def test_list_erasures(user3: UserClientFlask):
assert status == '200 OK'
assert txt in body
+ uri = '/inventory/device/erasure/1/'
+ body, status = user3.get(uri)
+ assert status == '200 OK'
+ assert txt not in body
+
+ dev = Device.query.first()
+ dev.binding.kangaroo = True
+ db.session.commit()
+
+ body, status = user3.get(uri)
+ assert status == '200 OK'
+ assert txt in body
+
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
From 2d67c9afd2c679568fec85dc6fae25987544a067 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 21 Nov 2022 17:37:51 +0100
Subject: [PATCH 09/49] version
---
CHANGELOG.md | 1 +
ereuse_devicehub/__init__.py | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 044b40bd..3d6b36a2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ ml).
- [added] #387 add template settings for Secure Erasure.
- [added] #397 add obada standard export.
- [added] #402 add reset password module.
+- [added] #406 add orphans disks page.
- [changed] #391 add dhid in table and export of Erasure section.
- [changed] #395 change response for the new api to workbench.
- [changed] #396 modularize commands.
diff --git a/ereuse_devicehub/__init__.py b/ereuse_devicehub/__init__.py
index 60be088d..5a8e0983 100644
--- a/ereuse_devicehub/__init__.py
+++ b/ereuse_devicehub/__init__.py
@@ -1 +1 @@
-__version__ = "2.4.2"
+__version__ = "2.4.3"
From 67cf797c6ce81d30668b7bea07e05aac516c6fc4 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Tue, 22 Nov 2022 11:58:56 +0100
Subject: [PATCH 10/49] fixing name hardDrive in filter
---
ereuse_devicehub/inventory/forms.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py
index 41505a8a..b86dca83 100644
--- a/ereuse_devicehub/inventory/forms.py
+++ b/ereuse_devicehub/inventory/forms.py
@@ -88,7 +88,7 @@ DEVICES = {
],
"Drives & Storage": [
"All DataStorage",
- "HardDrives",
+ "HardDrive",
"SolidStageDrive",
],
}
From 7bf879bbcf608889095560df7f9eb462ac1f849f Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Tue, 22 Nov 2022 11:59:31 +0100
Subject: [PATCH 11/49] add my_partner for get the partner of one device
---
ereuse_devicehub/resources/device/models.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py
index 0f398737..35e4d559 100644
--- a/ereuse_devicehub/resources/device/models.py
+++ b/ereuse_devicehub/resources/device/models.py
@@ -632,6 +632,14 @@ class Device(Thing):
return self.binding.device.devicehub_id
return self.devicehub_id
+ @property
+ def my_partner(self):
+ if self.placeholder and self.placeholder.binding:
+ return self.placeholder.binding
+ if self.binding:
+ return self.binding.device
+ return self
+
@property
def get_updated(self):
if self.placeholder and self.placeholder.binding:
From 796f49f6cf17282ed71a93fa94ef61a8ec986509 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Tue, 22 Nov 2022 12:00:17 +0100
Subject: [PATCH 12/49] show correctly the ids in the templates
---
ereuse_devicehub/templates/inventory/erasure_list.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index adaec94f..7573bb4b 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -128,7 +128,7 @@
{% for ac in erasure %}
- 0 %}
+ {% if ac.device.my_partner.lots | length > 0 %}
- {% for lot in ac.device.get_lots_for_template() %}
+ {% for lot in ac.device.my_partner.get_lots_for_template() %}
{{ lot }}
{% endfor %}
From ac535cc9b5dedbf5dd301916ece94a5e5e92bb38 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Tue, 22 Nov 2022 15:44:44 +0100
Subject: [PATCH 13/49] add new fields in the filters
---
ereuse_devicehub/inventory/forms.py | 17 +
.../resources/device/definitions.py | 476 ++++++++++++++----
ereuse_devicehub/resources/device/schemas.py | 4 +
.../templates/inventory/device_create.html | 8 +-
4 files changed, 419 insertions(+), 86 deletions(-)
diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py
index 41505a8a..a46c4dd5 100644
--- a/ereuse_devicehub/inventory/forms.py
+++ b/ereuse_devicehub/inventory/forms.py
@@ -50,11 +50,14 @@ from ereuse_devicehub.resources.device.models import (
Keyboard,
Laptop,
MemoryCardReader,
+ Monitor,
Mouse,
Placeholder,
+ Projector,
Server,
Smartphone,
Tablet,
+ TelevisionSet,
)
from ereuse_devicehub.resources.documents.models import DataWipeDocument
from ereuse_devicehub.resources.enums import Severity
@@ -91,6 +94,13 @@ DEVICES = {
"HardDrives",
"SolidStageDrive",
],
+ "Accessories": [
+ "All Accessories",
+ "Mouse",
+ "MemoryCardReader",
+ "SAI",
+ "Keyboard",
+ ],
}
COMPUTERS = ['Desktop', 'Laptop', 'Server', 'Computer']
@@ -98,6 +108,7 @@ COMPUTERS = ['Desktop', 'Laptop', 'Server', 'Computer']
MONITORS = ["ComputerMonitor", "Monitor", "TelevisionSet", "Projector"]
MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"]
STORAGE = ["HardDrive", "SolidStateDrive"]
+ACCESSORIES = ["Mouse", "MemoryCardReader", "SAI", "Keyboard"]
class AdvancedSearchForm(FlaskForm):
@@ -184,6 +195,9 @@ class FilterForm(FlaskForm):
elif "All DataStorage" == self.device_type:
filter_type = STORAGE
+ elif "All Accessories" == self.device_type:
+ filter_type = ACCESSORIES
+
if filter_type:
self.devices = self.devices.filter(Device.type.in_(filter_type))
@@ -371,6 +385,9 @@ class NewDeviceForm(FlaskForm):
"Tablet": Tablet,
"Cellphone": Cellphone,
"ComputerMonitor": ComputerMonitor,
+ "Monitor": Monitor,
+ "TelevisionSet": TelevisionSet,
+ "Projector": Projector,
"Mouse": Mouse,
"Keyboard": Keyboard,
"SAI": SAI,
diff --git a/ereuse_devicehub/resources/device/definitions.py b/ereuse_devicehub/resources/device/definitions.py
index cdc99c05..015d5040 100644
--- a/ereuse_devicehub/resources/device/definitions.py
+++ b/ereuse_devicehub/resources/device/definitions.py
@@ -4,7 +4,11 @@ from teal.resource import Converters, Resource
from ereuse_devicehub.resources.device import schemas
from ereuse_devicehub.resources.device.models import Manufacturer
-from ereuse_devicehub.resources.device.views import DeviceView, DeviceMergeView, ManufacturerView
+from ereuse_devicehub.resources.device.views import (
+ DeviceMergeView,
+ DeviceView,
+ ManufacturerView,
+)
class DeviceDef(Resource):
@@ -13,25 +17,42 @@ class DeviceDef(Resource):
ID_CONVERTER = Converters.string
AUTH = False # We manage this at each view
- def __init__(self, app,
- import_name=__name__,
- static_folder='static',
- static_url_path=None,
- template_folder='templates',
- url_prefix=None,
- subdomain=None,
- url_defaults=None,
- root_path=None,
- cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder='static',
+ static_url_path=None,
+ template_folder='templates',
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
- device_merge = DeviceMergeView.as_view('merge-devices', definition=self, auth=app.auth)
+ device_merge = DeviceMergeView.as_view(
+ 'merge-devices', definition=self, auth=app.auth
+ )
if self.AUTH:
device_merge = app.auth.requires_auth(device_merge)
- path = '/<{value}:dev1_id>/merge/<{value}:dev2_id>'.format(value=self.ID_CONVERTER.value)
+ path = '/<{value}:dev1_id>/merge/<{value}:dev2_id>'.format(
+ value=self.ID_CONVERTER.value
+ )
# self.add_url_rule(path, view_func=device_merge, methods={'POST'})
@@ -40,11 +61,31 @@ class ComputerDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Computer
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class DesktopDef(ComputerDef):
@@ -66,11 +107,31 @@ class MonitorDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Monitor
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class ComputerMonitorDef(MonitorDef):
@@ -83,15 +144,40 @@ class TelevisionSetDef(MonitorDef):
SCHEMA = schemas.TelevisionSet
+class ProjectorDef(MonitorDef):
+ VIEW = None
+ SCHEMA = schemas.Projector
+
+
class MobileDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Mobile
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class SmartphoneDef(MobileDef):
@@ -113,11 +199,31 @@ class ComponentDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Component
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class GraphicCardDef(ComponentDef):
@@ -184,11 +290,31 @@ class ComputerAccessoryDef(DeviceDef):
VIEW = None
SCHEMA = schemas.ComputerAccessory
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class MouseDef(ComputerAccessoryDef):
@@ -215,11 +341,31 @@ class NetworkingDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Networking
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class RouterDef(NetworkingDef):
@@ -246,11 +392,31 @@ class PrinterDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Printer
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class LabelPrinterDef(PrinterDef):
@@ -262,11 +428,31 @@ class SoundDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Sound
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class MicrophoneDef(SoundDef):
@@ -278,11 +464,31 @@ class VideoDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Video
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class VideoScalerDef(VideoDef):
@@ -299,11 +505,31 @@ class CookingDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Cooking
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class Mixer(CookingDef):
@@ -315,11 +541,31 @@ class DIYAndGardeningDef(DeviceDef):
VIEW = None
SCHEMA = schemas.DIYAndGardening
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class DrillDef(DIYAndGardeningDef):
@@ -331,22 +577,62 @@ class PackOfScrewdriversDef(DIYAndGardeningDef):
VIEW = None
SCHEMA = schemas.PackOfScrewdrivers
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class HomeDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Home
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class DehumidifierDef(HomeDef):
@@ -363,11 +649,31 @@ class RecreationDef(DeviceDef):
VIEW = None
SCHEMA = schemas.Recreation
- def __init__(self, app, import_name=__name__, static_folder=None, static_url_path=None,
- template_folder=None, url_prefix=None, subdomain=None, url_defaults=None,
- root_path=None, cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
- super().__init__(app, import_name, static_folder, static_url_path, template_folder,
- url_prefix, subdomain, url_defaults, root_path, cli_commands)
+ def __init__(
+ self,
+ app,
+ import_name=__name__,
+ static_folder=None,
+ static_url_path=None,
+ template_folder=None,
+ url_prefix=None,
+ subdomain=None,
+ url_defaults=None,
+ root_path=None,
+ cli_commands: Iterable[Tuple[Callable, str or None]] = tuple(),
+ ):
+ super().__init__(
+ app,
+ import_name,
+ static_folder,
+ static_url_path,
+ template_folder,
+ url_prefix,
+ subdomain,
+ url_defaults,
+ root_path,
+ cli_commands,
+ )
class BikeDef(RecreationDef):
diff --git a/ereuse_devicehub/resources/device/schemas.py b/ereuse_devicehub/resources/device/schemas.py
index 890dd287..b689a968 100644
--- a/ereuse_devicehub/resources/device/schemas.py
+++ b/ereuse_devicehub/resources/device/schemas.py
@@ -269,6 +269,10 @@ class TelevisionSet(Monitor):
__doc__ = m.TelevisionSet.__doc__
+class Projector(Monitor):
+ __doc__ = m.Projector.__doc__
+
+
class Mobile(Device):
__doc__ = m.Mobile.__doc__
diff --git a/ereuse_devicehub/templates/inventory/device_create.html b/ereuse_devicehub/templates/inventory/device_create.html
index 6acf564f..603aee38 100644
--- a/ereuse_devicehub/templates/inventory/device_create.html
+++ b/ereuse_devicehub/templates/inventory/device_create.html
@@ -46,7 +46,13 @@
| |
-
-
-
{% endif %}
@@ -344,11 +310,14 @@
+
{% if config['DEBUG'] %}
{% else %}
From 1efc650beaf12ab1b3dbcaa823d9a6fa29176fbe Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Wed, 23 Nov 2022 16:13:30 +0100
Subject: [PATCH 15/49] add simpledatatables
---
ereuse_devicehub/templates/inventory/erasure_list.html | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index 57f660b8..be57db76 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -141,6 +141,7 @@
+
@@ -225,6 +226,7 @@
{% endfor %}
+
@@ -317,6 +319,12 @@
});
});
+
{% if config['DEBUG'] %}
From ade9fbd018760b554ee3e807c3dc5db7d31bde5a Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Wed, 23 Nov 2022 19:22:26 +0100
Subject: [PATCH 16/49] add raw query
---
ereuse_devicehub/inventory/views.py | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 56eaab1d..20b0663b 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -118,19 +118,33 @@ class ErasureListView(DeviceListMixin):
def dispatch_request(self, orphans=0):
self.get_context()
self.get_devices(orphans)
- if orphans:
- self.context['orphans'] = True
return flask.render_template(self.template_name, **self.context)
def get_devices(self, orphans):
+ page = int(request.args.get('page', 1))
+ per_page = int(request.args.get('per_page', 5))
+
erasure = EraseBasic.query.filter_by(author=g.user).order_by(
EraseBasic.created.desc()
)
if orphans:
- erasure = [e for e in erasure if e.device.orphan]
-
- page = int(request.args.get('page', 1))
- per_page = int(request.args.get('per_page', 5))
+ schema = app.config.get('SCHEMA')
+ sql = f"""
+ select action.id from {schema}.action as action
+ inner join {schema}.erase_basic as erase
+ on action.id=erase.id
+ inner join {schema}.device as device
+ on device.id=action.parent_id
+ inner join {schema}.placeholder as placeholder
+ on placeholder.binding_id=device.id
+ where action.parent_id is null or placeholder.kangaroo=true
+ """
+ ids = (e[0] for e in db.session.execute(sql))
+ erasure = EraseBasic.query.filter(EraseBasic.id.in_(ids)).order_by(
+ EraseBasic.created.desc()
+ )
+ self.context['orphans'] = True
+ # import pdb; pdb.set_trace()
erasure = erasure.paginate(page=page, per_page=per_page)
erasure.first = per_page * erasure.page - per_page + 1
From 925ce473e6b25f8125a9fea2e55e21e3f57d6443 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Wed, 23 Nov 2022 19:22:49 +0100
Subject: [PATCH 17/49] put the correct links
---
.../templates/inventory/erasure_list.html | 67 ++++++++-----------
1 file changed, 28 insertions(+), 39 deletions(-)
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index be57db76..b7af4b97 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -109,8 +109,12 @@
{% endif %}
+
+ If this text is showing is because there are an error
+
+
-
+
-
- {% if lot and not lot.is_temporary %}
-
-
Documents
-
-
-
- File |
- Uploaded on |
-
-
-
- {% for doc in lot.trade.documents %}
-
-
- {% if doc.url %}
- {{ doc.file_name}}
- {% else %}
- {{ doc.file_name}}
- {% endif %}
- |
-
- {{ doc.created.strftime('%H:%M %d-%m-%Y')}}
- |
-
- {% endfor %}
-
-
-
- {% endif %}
@@ -302,11 +289,6 @@
-{% include "inventory/lot_delete_modal.html" %}
-{% include "inventory/actions.html" %}
-{% include "inventory/allocate.html" %}
-{% include "inventory/data_wipe.html" %}
-{% include "inventory/trade.html" %}
{% include "inventory/alert_export_error.html" %}
{% include "inventory/alert_lots_changes.html" %}
@@ -315,14 +297,21 @@
$(document).ready(() => {
$(".dataTable-selector").on("change", function() {
const per_page = $('.dataTable-selector').val();
+ {% if orphans %}
+ window.location.href = "{{ url_for('inventory.device_erasure_list_orphans', orphans=1, page=1) }}&per_page="+per_page;
+ {% else %}
window.location.href = "{{ url_for('inventory.device_erasure_list', page=1) }}&per_page="+per_page;
+ {% endif %}
});
});
From d7500a2596e8742bd5a0582e5496d7ada88b114c Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Thu, 24 Nov 2022 11:50:56 +0100
Subject: [PATCH 18/49] add pagination to all devices view
---
ereuse_devicehub/inventory/views.py | 10 +-
.../templates/inventory/all_device_list.html | 671 ++++++++++++++++++
.../templates/inventory/device_list.html | 13 +-
3 files changed, 681 insertions(+), 13 deletions(-)
create mode 100644 ereuse_devicehub/templates/inventory/all_device_list.html
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 20b0663b..147ba4d5 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -144,7 +144,6 @@ class ErasureListView(DeviceListMixin):
EraseBasic.created.desc()
)
self.context['orphans'] = True
- # import pdb; pdb.set_trace()
erasure = erasure.paginate(page=page, per_page=per_page)
erasure.first = per_page * erasure.page - per_page + 1
@@ -159,8 +158,17 @@ class DeviceListView(DeviceListMixin):
class AllDeviceListView(DeviceListMixin):
+ template_name = 'inventory/all_device_list.html'
+
def dispatch_request(self):
self.get_context(all_devices=True)
+ # import pdb; pdb.set_trace()
+ page = int(request.args.get('page', 1))
+ per_page = int(request.args.get('per_page', 5))
+ devices = self.context['devices'].paginate(page=page, per_page=per_page)
+ devices.first = per_page * devices.page - per_page + 1
+ devices.last = len(devices.items) + devices.first - 1
+ self.context['devices'] = devices
return flask.render_template(self.template_name, **self.context)
diff --git a/ereuse_devicehub/templates/inventory/all_device_list.html b/ereuse_devicehub/templates/inventory/all_device_list.html
new file mode 100644
index 00000000..79ff81cd
--- /dev/null
+++ b/ereuse_devicehub/templates/inventory/all_device_list.html
@@ -0,0 +1,671 @@
+{% extends "ereuse_devicehub/base_site.html" %}
+{% block main %}
+
+
+
Inventory
+
+
+
+
+
+
+
+
+
+ {% if lot %}
+
+
+
+
+
+
+
+ {% if lot.is_temporary or not lot.transfer.closed %}
+
+ {% if lot and lot.is_temporary %}
+
+ Create Outgoing Lot
+
+
+ Create Incoming Lot
+
+ {% endif %}
+
+ Delete Lot
+
+
+ {% endif %}
+
+
+
+ {% endif %}
+
+
+ {% if lot %}
+
+
+ -
+
+
+
+ {% if lot and not lot.is_temporary %}
+ -
+
+
+
+ {% if lot.transfer %}
+ -
+
+
+ -
+
+
+ -
+
+
+ {% endif %}
+ {% endif %}
+
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ If this text is showing is because there are an error
+
+
+
+
+
+
+ Displaying devices of type
+ {{ form_filter.filter.data or "Computer" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Showing {{ devices.first }} to {{ devices.last }} of {{ devices.total }} entries
+
+
+
+
+
+
+
+ {% if lot and not lot.is_temporary %}
+
+
+
+
Documents
+
+
+
+ File |
+ Uploaded on |
+
+
+
+ {% for doc in lot.documents %}
+
+
+ {% if doc.get_url() %}
+ {{ doc.file_name}}
+ {% else %}
+ {{ doc.file_name}}
+ {% endif %}
+ |
+
+ {{ doc.created.strftime('%Y-%m-%d %H:%M')}}
+ |
+
+ {% endfor %}
+ {% for doc in lot.trade.documents %}
+
+
+ {% if doc.get_url() %}
+ {{ doc.file_name}}
+ {% else %}
+ {{ doc.file_name}}
+ {% endif %}
+ |
+
+ {{ doc.created.strftime('%Y-%m-%d %H:%M')}}
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+{% include "inventory/lot_delete_modal.html" %}
+{% include "inventory/actions.html" %}
+{% include "inventory/allocate.html" %}
+{% include "inventory/data_wipe.html" %}
+{% include "inventory/trade.html" %}
+{% include "inventory/alert_export_error.html" %}
+{% include "inventory/alert_lots_changes.html" %}
+
+
+
+
+{% if config['DEBUG'] %}
+
+{% else %}
+
+{% endif %}
+
+
+{% endblock main %}
diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html
index 8f14446a..98894fe5 100644
--- a/ereuse_devicehub/templates/inventory/device_list.html
+++ b/ereuse_devicehub/templates/inventory/device_list.html
@@ -7,11 +7,7 @@
- Inventory
{% if not lot %}
- {% if all_devices %}
- - All devices
- {% else %}
- - Unassigned
- {% endif %}
+ - Unassigned
{% elif lot.is_temporary %}
- Temporary Lot
- {{ lot.name }}
@@ -230,17 +226,10 @@
-
- {% if not all_devices %}
Devices Lots Spreadsheet
- {% else %}
-
-
- Devices Lots Spreadsheet
-
- {% endif %}
-
From 0f033c8d83eb8dfc1959b27956c78f2e68f1c65f Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Thu, 24 Nov 2022 11:59:18 +0100
Subject: [PATCH 19/49] clean
---
ereuse_devicehub/parser/snapshot.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ereuse_devicehub/parser/snapshot.py b/ereuse_devicehub/parser/snapshot.py
index 559a7f48..490797af 100644
--- a/ereuse_devicehub/parser/snapshot.py
+++ b/ereuse_devicehub/parser/snapshot.py
@@ -1,7 +1,6 @@
from datetime import datetime, timezone
-from typing import List
-from ereuse_workbench.computer import Component, Computer, DataStorage
+from ereuse_workbench.computer import Computer, DataStorage
from ereuse_workbench.utils import Dumpeable
@@ -24,8 +23,8 @@ class Snapshot(Dumpeable):
self.endTime = datetime.now(timezone.utc)
self.closed = False
self.elapsed = None
- self.device = None # type: Computer
- self.components = None # type: List[Component]
+ self.device = None
+ self.components = None
self._storages = None
def computer(self):
From a544549a812fe610bfd0b2877752a15bd427963e Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Thu, 24 Nov 2022 12:21:42 +0100
Subject: [PATCH 20/49] clean
---
docs/conf.py | 42 +++++++++++++++++------------
ereuse_devicehub/config.py | 3 +--
ereuse_devicehub/dummy/dummy.py | 3 +--
ereuse_devicehub/parser/computer.py | 4 +--
4 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/docs/conf.py b/docs/conf.py
index a1b4e42e..73d3ccc9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -30,7 +30,6 @@ from teal.enums import Country, Currency, Layouts, Subdivision
from teal.marshmallow import EnumField
from ereuse_devicehub.marshmallow import NestedOn
-from ereuse_devicehub.resources.schemas import Thing
project = 'Devicehub'
copyright = '2020, eReuse.org team'
@@ -56,7 +55,7 @@ extensions = [
'sphinx.ext.viewcode',
'sphinxcontrib.plantuml',
'sphinx.ext.autosectionlabel',
- 'sphinx.ext.autodoc'
+ 'sphinx.ext.autodoc',
]
# Add any paths that contain templates here, relative to this directory.
@@ -126,15 +125,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
-
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@@ -144,18 +140,20 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'Devicehub.tex', 'Devicehub Documentation',
- 'eReuse.org team', 'manual'),
+ (
+ master_doc,
+ 'Devicehub.tex',
+ 'Devicehub Documentation',
+ 'eReuse.org team',
+ 'manual',
+ ),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'devicehub', 'Devicehub Documentation',
- [author], 1)
-]
+man_pages = [(master_doc, 'devicehub', 'Devicehub Documentation', [author], 1)]
# -- Options for Texinfo output ----------------------------------------------
@@ -163,9 +161,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'Devicehub', 'Devicehub Documentation',
- author, 'Devicehub', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ 'Devicehub',
+ 'Devicehub Documentation',
+ author,
+ 'Devicehub',
+ 'One line description of project.',
+ 'Miscellaneous',
+ ),
]
# -- Extension configuration -------------------------------------------------
@@ -199,6 +203,7 @@ class DhlistDirective(Directive):
This requires :py:class:`ereuse_devicehub.resources.schemas.SchemaMeta`.
You will find in that module more information.
"""
+
has_content = False
# Definition of passed-in options
@@ -216,7 +221,7 @@ class DhlistDirective(Directive):
sections = []
sections.append(self.links(things)) # Make index
- for thng in things: # type: Thing
+ for thng in things:
# Generate a section for each class, with a title,
# fields description and a paragraph
section = n.section(ids=[self._id(thng)])
@@ -228,7 +233,9 @@ class DhlistDirective(Directive):
for key, f in thng._own:
name = n.field_name(text=f.data_key or key)
body = [
- self.parse('{} {}'.format(self.type(f), f.metadata.get('description', '')))
+ self.parse(
+ '{} {}'.format(self.type(f), f.metadata.get('description', ''))
+ )
]
if isinstance(f, EnumField):
body.append(self._parse_enum_field(f))
@@ -244,6 +251,7 @@ class DhlistDirective(Directive):
def _parse_enum_field(self, f):
from ereuse_devicehub.resources.device import states
+
if issubclass(f.enum, (Subdivision, Currency, Country, Layouts, states.State)):
return self.parse(f.enum.__doc__)
else:
@@ -298,7 +306,7 @@ class DhlistDirective(Directive):
def parse(self, text) -> n.container:
"""Parses text possibly containing ReST stuff and adds it in
- a node."""
+ a node."""
p = n.container('')
self.state.nested_parse(StringList(string2lines(inspect.cleandoc(text))), 0, p)
return p
diff --git a/ereuse_devicehub/config.py b/ereuse_devicehub/config.py
index 79a9b75b..a41c9640 100644
--- a/ereuse_devicehub/config.py
+++ b/ereuse_devicehub/config.py
@@ -1,6 +1,5 @@
from distutils.version import StrictVersion
from itertools import chain
-from typing import Set
from decouple import config
from teal.auth import TokenAuth
@@ -44,7 +43,7 @@ class DevicehubConfig(Config):
import_resource(metric_def),
),
)
- PASSWORD_SCHEMES = {'pbkdf2_sha256'} # type: Set[str]
+ PASSWORD_SCHEMES = {'pbkdf2_sha256'}
SECRET_KEY = config('SECRET_KEY')
DB_USER = config('DB_USER', 'dhub')
DB_PASSWORD = config('DB_PASSWORD', 'ereuse')
diff --git a/ereuse_devicehub/dummy/dummy.py b/ereuse_devicehub/dummy/dummy.py
index 7947a85b..ee7f7c15 100644
--- a/ereuse_devicehub/dummy/dummy.py
+++ b/ereuse_devicehub/dummy/dummy.py
@@ -1,7 +1,6 @@
import itertools
import json
from pathlib import Path
-from typing import Set
import click
import click_spinner
@@ -109,7 +108,7 @@ class Dummy:
files = tuple(Path(__file__).parent.joinpath('files').iterdir())
print('done.')
sample_pc = None # We treat this one as a special sample for demonstrations
- pcs = set() # type: Set[int]
+ pcs = set()
with click.progressbar(files, label='Creating devices...'.ljust(28)) as bar:
for path in bar:
with path.open() as f:
diff --git a/ereuse_devicehub/parser/computer.py b/ereuse_devicehub/parser/computer.py
index afd2e17d..b41ce833 100644
--- a/ereuse_devicehub/parser/computer.py
+++ b/ereuse_devicehub/parser/computer.py
@@ -4,7 +4,7 @@ from contextlib import suppress
from datetime import datetime
from fractions import Fraction
from math import hypot
-from typing import Iterator, List, Optional, Type, TypeVar
+from typing import Iterator, List, Optional, TypeVar
import dateutil.parser
from ereuse_utils import getter, text
@@ -404,7 +404,7 @@ class Computer(Device):
chassis value.
"""
- COMPONENTS = list(Component.__subclasses__()) # type: List[Type[Component]]
+ COMPONENTS = list(Component.__subclasses__())
COMPONENTS.remove(Motherboard)
def __init__(self, node: dict) -> None:
From eee61dca8eed54b073f05975219bcafad829537e Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Thu, 24 Nov 2022 13:19:11 +0100
Subject: [PATCH 21/49] fix test
---
tests/test_render_2_0.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/test_render_2_0.py b/tests/test_render_2_0.py
index 0a95eee1..fbd437d9 100644
--- a/tests/test_render_2_0.py
+++ b/tests/test_render_2_0.py
@@ -2368,6 +2368,9 @@ def test_upload_snapshot_smartphone(user3: UserClientFlask):
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_list_erasures(user3: UserClientFlask):
+ from flask import current_app as app
+
+ app.config['SCHEMA'] = 'test'
uri = '/inventory/upload-snapshot/'
file_name = 'erase-sectors-2-hdd.snapshot.yaml'
body, status = user3.get(uri)
From 3a952324c20eec8adc393dc25eaf732fefbd5708 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Thu, 24 Nov 2022 14:02:56 +0100
Subject: [PATCH 22/49] change value per_page
---
ereuse_devicehub/inventory/views.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 147ba4d5..7e4d8ef8 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -55,6 +55,9 @@ devices = Blueprint('inventory', __name__, url_prefix='/inventory')
logger = logging.getLogger(__name__)
+PER_PAGE = 20
+
+
class DeviceListMixin(GenericMixin):
template_name = 'inventory/device_list.html'
@@ -122,7 +125,7 @@ class ErasureListView(DeviceListMixin):
def get_devices(self, orphans):
page = int(request.args.get('page', 1))
- per_page = int(request.args.get('per_page', 5))
+ per_page = int(request.args.get('per_page', PER_PAGE))
erasure = EraseBasic.query.filter_by(author=g.user).order_by(
EraseBasic.created.desc()
@@ -164,7 +167,7 @@ class AllDeviceListView(DeviceListMixin):
self.get_context(all_devices=True)
# import pdb; pdb.set_trace()
page = int(request.args.get('page', 1))
- per_page = int(request.args.get('per_page', 5))
+ per_page = int(request.args.get('per_page', PER_PAGE))
devices = self.context['devices'].paginate(page=page, per_page=per_page)
devices.first = per_page * devices.page - per_page + 1
devices.last = len(devices.items) + devices.first - 1
From abc773fe6e9e16fa14749403ee77f65370791333 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Fri, 25 Nov 2022 18:56:56 +0100
Subject: [PATCH 23/49] add pagination in all list of devices
---
ereuse_devicehub/inventory/views.py | 20 +-
.../templates/inventory/all_device_list.html | 671 ------------------
.../templates/inventory/device_list.html | 119 +++-
3 files changed, 125 insertions(+), 685 deletions(-)
delete mode 100644 ereuse_devicehub/templates/inventory/all_device_list.html
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 7e4d8ef8..59e66e07 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -64,9 +64,17 @@ class DeviceListMixin(GenericMixin):
def get_context(self, lot_id=None, all_devices=False):
super().get_context()
+ page = int(request.args.get('page', 1))
+ per_page = int(request.args.get('per_page', PER_PAGE))
+ filter = request.args.get('filter', "All+Computers")
+ # import pdb; pdb.set_trace()
+
lots = self.context['lots']
form_filter = FilterForm(lots, lot_id, all_devices=all_devices)
- devices = form_filter.search()
+ devices = form_filter.search().paginate(page=page, per_page=per_page)
+ devices.first = per_page * devices.page - per_page + 1
+ devices.last = len(devices.items) + devices.first - 1
+
lot = None
form_transfer = ''
form_delivery = ''
@@ -95,6 +103,7 @@ class DeviceListMixin(GenericMixin):
'tags': self.get_user_tags(),
'list_devices': self.get_selected_devices(form_new_action),
'all_devices': all_devices,
+ 'filter': filter,
}
)
@@ -161,17 +170,8 @@ class DeviceListView(DeviceListMixin):
class AllDeviceListView(DeviceListMixin):
- template_name = 'inventory/all_device_list.html'
-
def dispatch_request(self):
self.get_context(all_devices=True)
- # import pdb; pdb.set_trace()
- page = int(request.args.get('page', 1))
- per_page = int(request.args.get('per_page', PER_PAGE))
- devices = self.context['devices'].paginate(page=page, per_page=per_page)
- devices.first = per_page * devices.page - per_page + 1
- devices.last = len(devices.items) + devices.first - 1
- self.context['devices'] = devices
return flask.render_template(self.template_name, **self.context)
diff --git a/ereuse_devicehub/templates/inventory/all_device_list.html b/ereuse_devicehub/templates/inventory/all_device_list.html
deleted file mode 100644
index 79ff81cd..00000000
--- a/ereuse_devicehub/templates/inventory/all_device_list.html
+++ /dev/null
@@ -1,671 +0,0 @@
-{% extends "ereuse_devicehub/base_site.html" %}
-{% block main %}
-
-
-
Inventory
-
-
-
-
-
-
-
-
-
- {% if lot %}
-
-
-
-
-
-
-
- {% if lot.is_temporary or not lot.transfer.closed %}
-
- {% if lot and lot.is_temporary %}
-
- Create Outgoing Lot
-
-
- Create Incoming Lot
-
- {% endif %}
-
- Delete Lot
-
-
- {% endif %}
-
-
-
- {% endif %}
-
-
- {% if lot %}
-
-
- -
-
-
-
- {% if lot and not lot.is_temporary %}
- -
-
-
-
- {% if lot.transfer %}
- -
-
-
- -
-
-
- -
-
-
- {% endif %}
- {% endif %}
-
-
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- If this text is showing is because there are an error
-
-
-
-
-
-
- Displaying devices of type
- {{ form_filter.filter.data or "Computer" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- Showing {{ devices.first }} to {{ devices.last }} of {{ devices.total }} entries
-
-
-
-
-
-
-
- {% if lot and not lot.is_temporary %}
-
-
-
-
Documents
-
-
-
- File |
- Uploaded on |
-
-
-
- {% for doc in lot.documents %}
-
-
- {% if doc.get_url() %}
- {{ doc.file_name}}
- {% else %}
- {{ doc.file_name}}
- {% endif %}
- |
-
- {{ doc.created.strftime('%Y-%m-%d %H:%M')}}
- |
-
- {% endfor %}
- {% for doc in lot.trade.documents %}
-
-
- {% if doc.get_url() %}
- {{ doc.file_name}}
- {% else %}
- {{ doc.file_name}}
- {% endif %}
- |
-
- {{ doc.created.strftime('%Y-%m-%d %H:%M')}}
- |
-
- {% endfor %}
-
-
-
-
-
-
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
-{% include "inventory/lot_delete_modal.html" %}
-{% include "inventory/actions.html" %}
-{% include "inventory/allocate.html" %}
-{% include "inventory/data_wipe.html" %}
-{% include "inventory/trade.html" %}
-{% include "inventory/alert_export_error.html" %}
-{% include "inventory/alert_lots_changes.html" %}
-
-
-
-
-{% if config['DEBUG'] %}
-
-{% else %}
-
-{% endif %}
-
-
-{% endblock main %}
diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html
index 98894fe5..78c3e39d 100644
--- a/ereuse_devicehub/templates/inventory/device_list.html
+++ b/ereuse_devicehub/templates/inventory/device_list.html
@@ -7,7 +7,11 @@
- Inventory
{% if not lot %}
- - Unassigned
+ {% if all_devices %}
+ - All devices
+ {% else %}
+ - Unassigned
+ {% endif %}
{% elif lot.is_temporary %}
- Temporary Lot
- {{ lot.name }}
@@ -226,10 +230,17 @@
-
+ {% if not all_devices %}
Devices Lots Spreadsheet
+ {% else %}
+
+
+ Devices Lots Spreadsheet
+
+ {% endif %}
-
@@ -324,6 +335,8 @@
{% for f in form_filter %}
{{ f }}
{% endfor %}
+
+
@@ -333,6 +346,38 @@
{{ form_filter.filter.data or "Computer" }}
+
+
+
+
+
+
+
+
@@ -351,7 +396,7 @@
- {% for dev in devices %}
+ {% for dev in devices.items %}
{% if dev.placeholder and (not dev.parent_id or dev.parent.placeholder.kangaroo) %}
@@ -410,6 +455,57 @@
{% endfor %}
|
+
+
+ Showing {{ devices.first }} to {{ devices.last }} of {{ devices.total }} entries
+
+
+
+
@@ -581,10 +677,25 @@
{% include "inventory/alert_lots_changes.html" %}
+
{% if config['DEBUG'] %}
From 5e2dd3344b073413c33fe9af15046a3e44d806eb Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 11:58:42 +0100
Subject: [PATCH 24/49] add pagination to snapshots logs
---
ereuse_devicehub/inventory/views.py | 9 ++
ereuse_devicehub/parser/models.py | 6 ++
.../templates/inventory/snapshots_list.html | 94 +++++++++++++++++--
3 files changed, 100 insertions(+), 9 deletions(-)
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 59e66e07..69387ab8 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -1210,9 +1210,18 @@ class SnapshotListView(GenericMixin):
return flask.render_template(self.template_name, **self.context)
def get_snapshots_log(self):
+ page = int(request.args.get('page', 1))
+ per_page = int(request.args.get('per_page', PER_PAGE))
+
snapshots_log = SnapshotsLog.query.filter(
SnapshotsLog.owner == g.user
).order_by(SnapshotsLog.created.desc())
+
+ snapshots_log = snapshots_log.paginate(page=page, per_page=per_page)
+ snapshots_log.first = per_page * snapshots_log.page - per_page + 1
+ snapshots_log.last = len(snapshots_log.items) + snapshots_log.first - 1
+ return snapshots_log
+
logs = {}
for snap in snapshots_log:
try:
diff --git a/ereuse_devicehub/parser/models.py b/ereuse_devicehub/parser/models.py
index 4d298af0..bdd13f73 100644
--- a/ereuse_devicehub/parser/models.py
+++ b/ereuse_devicehub/parser/models.py
@@ -78,6 +78,12 @@ class SnapshotsLog(Thing):
snapshots.append(s)
return snapshots and 'Update' or 'New Device'
+ def get_system_uuid(self):
+ try:
+ return self.snapshot.device.system_uuid or ''
+ except AttributeError:
+ return ''
+
class PlaceholdersLog(Thing):
"""A Placeholder log."""
diff --git a/ereuse_devicehub/templates/inventory/snapshots_list.html b/ereuse_devicehub/templates/inventory/snapshots_list.html
index 4c35f44e..1804f364 100644
--- a/ereuse_devicehub/templates/inventory/snapshots_list.html
+++ b/ereuse_devicehub/templates/inventory/snapshots_list.html
@@ -22,6 +22,38 @@
+
+
+
+
+
+
+
+
@@ -39,7 +71,7 @@
- {% for snap in snapshots_log %}
+ {% for snap in snapshots_log.items %}
{% if snap.sid and snap.snapshot_uuid %}
@@ -59,26 +91,26 @@
{{ snap.version }}
|
- {% if snap.device %}
+ {% if snap.get_device() %}
- {{ snap.device }}
+ {{ snap.get_device() }}
{% endif %}
|
- {{ snap.system_uuid }}
+ {{ snap.get_system_uuid() }}
|
- {{ snap.status }}
+ {{ snap.get_status() }}
|
- {{ snap.new_device }}
+ {{ snap.get_new_device() }}
|
- {{ snap.type_device }}
+ {{ snap.get_type_device() }}
|
- {{ snap.original_dhid }}
+ {{ snap.get_original_dhid() }}
|
{{ snap.created.strftime('%Y-%m-%d %H:%M') }} |
@@ -93,6 +125,38 @@
|
+
+
+ Showing {{ snapshots_log.first }} to {{ snapshots_log.last }} of {{ snapshots_log.total }} entries
+
+
+
@@ -109,6 +173,18 @@
+
{% endblock main %}
From f9d679547fafe767c37f15f46bf22d8f94081030 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 12:30:02 +0100
Subject: [PATCH 25/49] pagination in placeholder logs
---
ereuse_devicehub/inventory/views.py | 42 ++--------
.../inventory/placeholder_log_list.html | 80 ++++++++++++++++++-
2 files changed, 85 insertions(+), 37 deletions(-)
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 69387ab8..fe1c37e7 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -1222,41 +1222,6 @@ class SnapshotListView(GenericMixin):
snapshots_log.last = len(snapshots_log.items) + snapshots_log.first - 1
return snapshots_log
- logs = {}
- for snap in snapshots_log:
- try:
- system_uuid = snap.snapshot.device.system_uuid or ''
- except AttributeError:
- system_uuid = ''
-
- if snap.snapshot_uuid not in logs:
- logs[snap.snapshot_uuid] = {
- 'sid': snap.sid,
- 'snapshot_uuid': snap.snapshot_uuid,
- 'version': snap.version,
- 'device': snap.get_device(),
- 'system_uuid': system_uuid,
- 'status': snap.get_status(),
- 'severity': snap.severity,
- 'created': snap.created,
- 'type_device': snap.get_type_device(),
- 'original_dhid': snap.get_original_dhid(),
- 'new_device': snap.get_new_device(),
- }
- continue
-
- if snap.created > logs[snap.snapshot_uuid]['created']:
- logs[snap.snapshot_uuid]['created'] = snap.created
-
- if snap.severity > logs[snap.snapshot_uuid]['severity']:
- logs[snap.snapshot_uuid]['severity'] = snap.severity
- logs[snap.snapshot_uuid]['status'] = snap.get_status()
-
- result = sorted(logs.values(), key=lambda d: d['created'])
- result.reverse()
-
- return result
-
class SnapshotDetailView(GenericMixin):
template_name = 'inventory/snapshot_detail.html'
@@ -1385,10 +1350,17 @@ class PlaceholderLogListView(GenericMixin):
return flask.render_template(self.template_name, **self.context)
def get_placeholders_log(self):
+ page = int(request.args.get('page', 1))
+ per_page = int(request.args.get('per_page', PER_PAGE))
+
placeholder_log = PlaceholdersLog.query.filter(
PlaceholdersLog.owner == g.user
).order_by(PlaceholdersLog.created.desc())
+ placeholder_log = placeholder_log.paginate(page=page, per_page=per_page)
+ placeholder_log.first = per_page * placeholder_log.page - per_page + 1
+ placeholder_log.last = len(placeholder_log.items) + placeholder_log.first - 1
+
return placeholder_log
diff --git a/ereuse_devicehub/templates/inventory/placeholder_log_list.html b/ereuse_devicehub/templates/inventory/placeholder_log_list.html
index aaff827d..bc16ccab 100644
--- a/ereuse_devicehub/templates/inventory/placeholder_log_list.html
+++ b/ereuse_devicehub/templates/inventory/placeholder_log_list.html
@@ -22,6 +22,38 @@
+
+
+
+
+
+
+
+
@@ -34,7 +66,7 @@
- {% for log in placeholders_log %}
+ {% for log in placeholders_log.items %}
{{ log.phid }}
@@ -58,6 +90,38 @@
{% endfor %}
|
+
+
+ Showing {{ placeholders_log.first }} to {{ placeholders_log.last }} of {{ placeholders_log.total }} entries
+
+
+
@@ -75,6 +139,18 @@
+
{% endblock main %}
From 3757873b0255d80bc3a1ebe7d127064e53ecde0e Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 13:12:14 +0100
Subject: [PATCH 26/49] fix bug Title tag in erasure list
---
ereuse_devicehub/templates/inventory/erasure_list.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html
index ffae9b16..2f36de71 100644
--- a/ereuse_devicehub/templates/inventory/erasure_list.html
+++ b/ereuse_devicehub/templates/inventory/erasure_list.html
@@ -22,7 +22,7 @@
- All hard drivers
+ All hard drives
From 0b6cfb210d7be39ac810dc189a848d2959682dac Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 15:00:45 +0100
Subject: [PATCH 27/49] add advanced search as top search
---
.../static/js/simple-datatables.js | 8 ++++++++
.../templates/ereuse_devicehub/base.html | 2 +-
.../templates/ereuse_devicehub/base_site.html | 20 ++-----------------
3 files changed, 11 insertions(+), 19 deletions(-)
create mode 100644 ereuse_devicehub/static/js/simple-datatables.js
diff --git a/ereuse_devicehub/static/js/simple-datatables.js b/ereuse_devicehub/static/js/simple-datatables.js
new file mode 100644
index 00000000..7ff88719
--- /dev/null
+++ b/ereuse_devicehub/static/js/simple-datatables.js
@@ -0,0 +1,8 @@
+/**
+ * Minified by jsDelivr using Terser v5.15.1.
+ * Original file: /npm/simple-datatables@4.0.7/dist/umd/simple-datatables.js
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).simpleDatatables=t()}}((function(){return function t(e,s,i){function a(r,o){if(!s[r]){if(!e[r]){var h="function"==typeof require&&require;if(!o&&h)return h(r,!0);if(n)return n(r,!0);var l=new Error("Cannot find module '"+r+"'");throw l.code="MODULE_NOT_FOUND",l}var d=s[r]={exports:{}};e[r][0].call(d.exports,(function(t){return a(e[r][1][t]||t)}),d,d.exports,t,e,s,i)}return s[r].exports}for(var n="function"==typeof require&&require,r=0;r=e?t:""+Array(e+1-i.length).join(s)+t},b={s:m,z:function(t){var e=-t.utcOffset(),s=Math.abs(e),i=Math.floor(s/60),a=s%60;return(e<=0?"+":"-")+m(i,2,"0")+":"+m(a,2,"0")},m:function t(e,s){if(e.date()1)return t(r[0])}else{var o=e.name;y[o]=e,a=o}return!i&&a&&(v=a),a||!i&&v},x=function(t,e){if(w(t))return t.clone();var s="object"==typeof e?e:{};return s.date=t,s.args=arguments,new T(s)},M=b;M.l=C,M.i=w,M.w=function(t,e){return x(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var T=function(){function g(t){this.$L=C(t.locale,null,!0),this.parse(t)}var m=g.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,s=t.utc;if(null===e)return new Date(NaN);if(M.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var i=e.match(p);if(i){var a=i[2]-1||0,n=(i[7]||"0").substring(0,3);return s?new Date(Date.UTC(i[1],a,i[3]||1,i[4]||0,i[5]||0,i[6]||0,n)):new Date(i[1],a,i[3]||1,i[4]||0,i[5]||0,i[6]||0,n)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return M},m.isValid=function(){return!(this.$d.toString()===u)},m.isSame=function(t,e){var s=x(t);return this.startOf(e)<=s&&s<=this.endOf(e)},m.isAfter=function(t,e){return x(t)68?1900:2e3)},o=function(t){return function(e){this[t]=+e}},h=[/[+-]\d\d:?(\d\d)?|Z/,function(t){(this.zone||(this.zone={})).offset=function(t){if(!t)return 0;if("Z"===t)return 0;var e=t.match(/([+-]|\d\d)/g),s=60*e[1]+(+e[2]||0);return 0===s?0:"+"===e[0]?-s:s}(t)}],l=function(t){var e=n[t];return e&&(e.indexOf?e:e.s.concat(e.f))},d=function(t,e){var s,i=n.meridiem;if(i){for(var a=1;a<=24;a+=1)if(t.indexOf(i(a,0,e))>-1){s=a>12;break}}else s=t===(e?"pm":"PM");return s},c={A:[a,function(t){this.afternoon=d(t,!1)}],a:[a,function(t){this.afternoon=d(t,!0)}],S:[/\d/,function(t){this.milliseconds=100*+t}],SS:[s,function(t){this.milliseconds=10*+t}],SSS:[/\d{3}/,function(t){this.milliseconds=+t}],s:[i,o("seconds")],ss:[i,o("seconds")],m:[i,o("minutes")],mm:[i,o("minutes")],H:[i,o("hours")],h:[i,o("hours")],HH:[i,o("hours")],hh:[i,o("hours")],D:[i,o("day")],DD:[s,o("day")],Do:[a,function(t){var e=n.ordinal,s=t.match(/\d+/);if(this.day=s[0],e)for(var i=1;i<=31;i+=1)e(i).replace(/\[|\]/g,"")===t&&(this.day=i)}],M:[i,o("month")],MM:[s,o("month")],MMM:[a,function(t){var e=l("months"),s=(l("monthsShort")||e.map((function(t){return t.slice(0,3)}))).indexOf(t)+1;if(s<1)throw new Error;this.month=s%12||s}],MMMM:[a,function(t){var e=l("months").indexOf(t)+1;if(e<1)throw new Error;this.month=e%12||e}],Y:[/[+-]?\d+/,o("year")],YY:[s,function(t){this.year=r(t)}],YYYY:[/\d{4}/,o("year")],Z:h,ZZ:h};function u(s){var i,a;i=s,a=n&&n.formats;for(var r=(s=i.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(e,s,i){var n=i&&i.toUpperCase();return s||a[i]||t[i]||a[n].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,(function(t,e,s){return e||s.slice(1)}))}))).match(e),o=r.length,h=0;h-1)return new Date(("X"===e?1e3:1)*t);var i=u(e)(t),a=i.year,n=i.month,r=i.day,o=i.hours,h=i.minutes,l=i.seconds,d=i.milliseconds,c=i.zone,p=new Date,f=r||(a||n?1:p.getDate()),g=a||p.getFullYear(),m=0;a&&!n||(m=n>0?n-1:p.getMonth());var b=o||0,v=h||0,y=l||0,w=d||0;return c?new Date(Date.UTC(g,m,f,b,v,y,w+60*c.offset*1e3)):s?new Date(Date.UTC(g,m,f,b,v,y,w)):new Date(g,m,f,b,v,y,w)}catch(t){return new Date("")}}(e,o,i),this.init(),c&&!0!==c&&(this.$L=this.locale(c).$L),d&&e!=this.format(o)&&(this.$d=new Date("")),n={}}else if(o instanceof Array)for(var p=o.length,f=1;f<=p;f+=1){r[1]=o[f-1];var g=s.apply(this,r);if(g.isValid()){this.$d=g.$d,this.$L=g.$L,this.init();break}f===p&&(this.$d=new Date(""))}else a.call(this,t)}}}();e.extend(i),s.parseDate=(t,s)=>{let i=!1;if(s)switch(s){case"ISO_8601":i=t;break;case"RFC_2822":i=e(t.slice(5),"DD MMM YYYY HH:mm:ss ZZ").unix();break;case"MYSQL":i=e(t,"YYYY-MM-DD hh:mm:ss").unix();break;case"UNIX":i=e(t).unix();break;default:i=e(t,s,!0).valueOf()}return i}}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],2:[function(t,e,s){"use strict";Object.defineProperty(s,"__esModule",{value:!0});const i=t=>"[object Object]"===Object.prototype.toString.call(t),a=(t,e)=>{const s=document.createElement(t);if(e&&"object"==typeof e)for(const t in e)"html"===t?s.innerHTML=e[t]:s.setAttribute(t,e[t]);return s},n=t=>{t instanceof NodeList?t.forEach((t=>n(t))):t.innerHTML=""},r=(t,e,s)=>a("li",{class:t,html:`${s}`}),o=(t,e)=>{let s,i;1===e?(s=0,i=t.length):-1===e&&(s=t.length-1,i=-1);for(let a=!0;a;){a=!1;for(let n=s;n!=i;n+=e)if(t[n+e]&&t[n].value>t[n+e].value){const s=t[n],i=t[n+e],r=s;t[n]=i,t[n+e]=r,a=!0}}return t};class h{constructor(t){this.dt=t,this.cursor=!1}build(t){const e=a("tr");let s=this.dt.headings;return s.length||(s=t.map((()=>""))),s.forEach(((s,i)=>{const n=a("td");t[i]&&t[i].length||(t[i]=""),n.innerHTML=t[i],n.data=t[i],e.appendChild(n)})),e}setCursor(t=!1){this.cursor&&this.cursor.classList.remove("dataTable-cursor"),t&&(t.classList.add("dataTable-cursor"),this.cursor=t)}render(t){return t}add(t){if(Array.isArray(t)){const e=this.dt;Array.isArray(t[0])?t.forEach((t=>{e.data.push(this.build(t))})):e.data.push(this.build(t)),e.data.length&&(e.hasRows=!0),this.update(),e.columns.rebuild()}}remove(t){const e=this.dt;Array.isArray(t)?(t.sort(((t,e)=>e-t)),t.forEach((t=>{e.data.splice(t,1)}))):"all"==t?e.data=[]:e.data.splice(t,1),e.data.length||(e.hasRows=!1),this.update(),e.columns.rebuild()}update(){this.dt.data.forEach(((t,e)=>{t.dataIndex=e}))}findRowIndex(t,e){return this.dt.data.findIndex((s=>s.children[t].innerText.toLowerCase().includes(String(e).toLowerCase())))}findRow(t,e){const s=this.findRowIndex(t,e);if(s<0)return{index:-1,row:null,cols:[]};const i=this.dt.data[s];return{index:s,row:i,cols:[...i.cells].map((t=>t.innerHTML))}}updateRow(t,e){const s=this.build(e);this.dt.data.splice(t,1,s),this.update(),this.dt.columns.rebuild()}}class l{constructor(t){this.dt=t}swap(t){if(t.length&&2===t.length){const e=[];this.dt.headings.forEach(((t,s)=>{e.push(s)}));const s=t[0],i=t[1],a=e[i];e[i]=e[s],e[s]=a,this.order(e)}}order(t){let e,s,i,a,n,r,o;const h=[[],[],[],[]],l=this.dt;t.forEach(((t,i)=>{n=l.headings[t],r="false"!==n.getAttribute("data-sortable"),e=n.cloneNode(!0),e.originalCellIndex=i,e.sortable=r,h[0].push(e),l.hiddenColumns.includes(t)||(s=n.cloneNode(!0),s.originalCellIndex=i,s.sortable=r,h[1].push(s))})),l.data.forEach(((e,s)=>{i=e.cloneNode(!1),a=e.cloneNode(!1),i.dataIndex=a.dataIndex=s,null!==e.searchIndex&&void 0!==e.searchIndex&&(i.searchIndex=a.searchIndex=e.searchIndex),t.forEach((t=>{o=e.cells[t].cloneNode(!0),o.data=e.cells[t].data,i.appendChild(o),l.hiddenColumns.includes(t)||(o=e.cells[t].cloneNode(!0),o.data=e.cells[t].data,a.appendChild(o))})),h[2].push(i),h[3].push(a)})),l.headings=h[0],l.activeHeadings=h[1],l.data=h[2],l.activeRows=h[3],l.update()}hide(t){if(t.length){const e=this.dt;t.forEach((t=>{e.hiddenColumns.includes(t)||e.hiddenColumns.push(t)})),this.rebuild()}}show(t){if(t.length){let e;const s=this.dt;t.forEach((t=>{e=s.hiddenColumns.indexOf(t),e>-1&&s.hiddenColumns.splice(e,1)})),this.rebuild()}}visible(t){let e;const s=this.dt;return t=t||s.headings.map((t=>t.originalCellIndex)),isNaN(t)?Array.isArray(t)&&(e=[],t.forEach((t=>{e.push(!s.hiddenColumns.includes(t))}))):e=!s.hiddenColumns.includes(t),e}add(t){let e;const s=document.createElement("th");if(!this.dt.headings.length)return this.dt.insert({headings:[t.heading],data:t.data.map((t=>[t]))}),void this.rebuild();this.dt.hiddenHeader?s.innerHTML="":t.heading.nodeName?s.appendChild(t.heading):s.innerHTML=t.heading,this.dt.headings.push(s),this.dt.data.forEach(((s,i)=>{t.data[i]&&(e=document.createElement("td"),t.data[i].nodeName?e.appendChild(t.data[i]):e.innerHTML=t.data[i],e.data=e.innerHTML,t.render&&(e.innerHTML=t.render.call(this,e.data,e,s)),s.appendChild(e))})),t.type&&s.setAttribute("data-type",t.type),t.format&&s.setAttribute("data-format",t.format),t.hasOwnProperty("sortable")&&(s.sortable=t.sortable,s.setAttribute("data-sortable",!0===t.sortable?"true":"false")),this.rebuild(),this.dt.renderHeader()}remove(t){Array.isArray(t)?(t.sort(((t,e)=>e-t)),t.forEach((t=>this.remove(t)))):(this.dt.headings.splice(t,1),this.dt.data.forEach((e=>{e.removeChild(e.cells[t])}))),this.rebuild()}filter(t,e,s,i){const a=this.dt;if(a.filterState||(a.filterState={originalData:a.data}),!a.filterState[t]){const e=[...i,()=>!0];a.filterState[t]=function(){let t=0;return()=>e[t++%e.length]}()}const n=a.filterState[t](),r=Array.from(a.filterState.originalData).filter((e=>{const s=e.cells[t],i=s.hasAttribute("data-content")?s.getAttribute("data-content"):s.innerText;return"function"==typeof n?n(i):i===n}));a.data=r,a.data.length?(this.rebuild(),a.update()):(a.clear(),a.hasRows=!1,a.setMessage(a.options.labels.noRows)),s||a.emit("datatable.sort",t,e)}sort(e,s,i){const a=this.dt;if(a.hasHeadings&&(e<0||e>a.headings.length))return!1;const n=a.options.filters&&a.options.filters[a.headings[e].textContent];if(n&&0!==n.length)return void this.filter(e,s,i,n);a.sorting=!0,i||a.emit("datatable.sorting",e,s);let r=a.data;const h=[],l=[];let d=0,c=0;const u=a.headings[e],p=[];if("date"===u.getAttribute("data-type")){let e=!1;u.hasAttribute("data-format")&&(e=u.getAttribute("data-format")),p.push(Promise.resolve().then((function(){return t("./date-7061ceee.js")})).then((({parseDate:t})=>s=>t(s,e))))}Promise.all(p).then((t=>{const n=t[0];let p,f;Array.from(r).forEach((t=>{const s=t.cells[e],i=s.hasAttribute("data-content")?s.getAttribute("data-content"):s.innerText;let a;a=n?n(i):"string"==typeof i?i.replace(/(\$|,|\s|%)/g,""):i,parseFloat(a)==a?l[c++]={value:Number(a),row:t}:h[d++]={value:"string"==typeof i?i.toLowerCase():i,row:t}})),s||(s=u.classList.contains("asc")?"desc":"asc"),"desc"==s?(p=o(h,-1),f=o(l,-1),u.classList.remove("asc"),u.classList.add("desc"),u.setAttribute("aria-sort","descending")):(p=o(l,1),f=o(h,1),u.classList.remove("desc"),u.classList.add("asc"),u.setAttribute("aria-sort","ascending")),a.lastTh&&u!=a.lastTh&&(a.lastTh.classList.remove("desc"),a.lastTh.classList.remove("asc"),a.lastTh.removeAttribute("aria-sort")),a.lastTh=u,r=p.concat(f),a.data=[];const g=[];r.forEach(((t,e)=>{a.data.push(t.row),null!==t.row.searchIndex&&void 0!==t.row.searchIndex&&g.push(e)})),a.searchData=g,this.rebuild(),a.update(),i||a.emit("datatable.sort",e,s)}))}rebuild(){let t,e,s,i;const a=this.dt,n=[];a.activeRows=[],a.activeHeadings=[],a.headings.forEach(((t,e)=>{t.originalCellIndex=e,t.sortable="false"!==t.getAttribute("data-sortable"),a.hiddenColumns.includes(e)||a.activeHeadings.push(t)})),a.data.forEach(((r,o)=>{t=r.cloneNode(!1),e=r.cloneNode(!1),t.dataIndex=e.dataIndex=o,null!==r.searchIndex&&void 0!==r.searchIndex&&(t.searchIndex=e.searchIndex=r.searchIndex),Array.from(r.cells).forEach((n=>{s=n.cloneNode(!0),s.data=n.data,t.appendChild(s),a.hiddenColumns.includes(s.cellIndex)||(i=s.cloneNode(!0),i.data=s.data,e.appendChild(i))})),n.push(t),a.activeRows.push(e)})),a.data=n,a.update()}}const d=function(t){let e=!1,s=!1;if((t=t||this.options.data).headings){e=a("thead");const s=a("tr");t.headings.forEach((t=>{const e=a("th",{html:t});s.appendChild(e)})),e.appendChild(s)}t.data&&t.data.length&&(s=a("tbody"),t.data.forEach((e=>{if(t.headings&&t.headings.length!==e.length)throw new Error("The number of rows do not match the number of headings.");const i=a("tr");e.forEach((t=>{const e=a("td",{html:t});i.appendChild(e)})),s.appendChild(i)}))),e&&(null!==this.dom.tHead&&this.dom.removeChild(this.dom.tHead),this.dom.appendChild(e)),s&&(this.dom.tBodies.length&&this.dom.removeChild(this.dom.tBodies[0]),this.dom.appendChild(s))},c={sortable:!0,searchable:!0,paging:!0,perPage:10,perPageSelect:[5,10,15,20,25],nextPrev:!0,firstLast:!1,prevText:"‹",nextText:"›",firstText:"«",lastText:"»",ellipsisText:"…",ascText:"▴",descText:"▾",truncatePager:!0,pagerDelta:2,scrollY:"",fixedColumns:!0,fixedHeight:!1,header:!0,hiddenHeader:!1,footer:!1,tabIndex:!1,rowNavigation:!1,labels:{placeholder:"Search on page...",perPage:"{select} entries per page",noRows:"No entries found",noResults:"No results match your search query",info:"Showing {start} to {end} of {rows} entries"},layout:{top:"{select}{search}",bottom:"{info}{pager}"}};s.DataTable=class{constructor(t,e={}){const s="string"==typeof t?document.querySelector(t):t;if(this.options={...c,...e,layout:{...c.layout,...e.layout},labels:{...c.labels,...e.labels}},this.rows=new h(this),this.columns=new l(this),this.initialized=!1,this.initialLayout=s.innerHTML,this.initialSortable=this.options.sortable,this.options.tabIndex?s.tabIndex=this.options.tabIndex:this.options.rowNavigation&&-1===s.tabIndex&&(s.tabIndex=0),this.options.header||(this.options.sortable=!1),null===s.tHead&&(!this.options.data||this.options.data&&!this.options.data.headings)&&(this.options.sortable=!1),s.tBodies.length&&!s.tBodies[0].rows.length&&this.options.data&&!this.options.data.data)throw new Error("You seem to be using the data option, but you've not defined any rows.");this.dom=s,this.table=this.dom,this.listeners={onResize:t=>this.onResize(t)},this.init()}init(t){if(this.initialized||this.dom.classList.contains("dataTable-table"))return!1;Object.assign(this.options,t||{}),this.currentPage=1,this.onFirstPage=!0,this.hiddenColumns=[],this.columnRenderers=[],this.selectedColumns=[],this.render(),setTimeout((()=>{this.emit("datatable.init"),this.initialized=!0,this.options.plugins&&Object.entries(this.options.plugins).forEach((([t,e])=>{this[t]&&"function"==typeof this[t]&&(this[t]=this[t](e,{createElement:a}),e.enabled&&this[t].init&&"function"==typeof this[t].init&&this[t].init())}))}),10)}render(){let t="";if(this.options.data&&d.call(this),this.body=this.dom.tBodies[0],this.head=this.dom.tHead,this.foot=this.dom.tFoot,this.body||(this.body=a("tbody"),this.dom.appendChild(this.body)),this.hasRows=this.body.rows.length>0,!this.head){const t=a("thead"),e=a("tr");this.hasRows&&(Array.from(this.body.rows[0].cells).forEach((()=>{e.appendChild(a("th"))})),t.appendChild(e)),this.head=t,this.dom.insertBefore(this.head,this.body),this.hiddenHeader=this.options.hiddenHeader}if(this.headings=[],this.hasHeadings=this.head.rows.length>0,this.hasHeadings&&(this.header=this.head.rows[0],this.headings=[].slice.call(this.header.cells)),this.options.header||this.head&&this.dom.removeChild(this.dom.tHead),this.options.footer?this.head&&!this.foot&&(this.foot=a("tfoot",{html:this.head.innerHTML}),this.dom.appendChild(this.foot)):this.foot&&this.dom.removeChild(this.dom.tFoot),this.wrapper=a("div",{class:"dataTable-wrapper dataTable-loading"}),t+="",t+=this.options.layout.top,t+="
",this.options.scrollY.length?t+=``:t+="",t+="",t+=this.options.layout.bottom,t+="
",t=t.replace("{info}",this.options.paging?"":""),this.options.paging&&this.options.perPageSelect){let e="";const s=a("select",{class:"dataTable-selector"});this.options.perPageSelect.forEach((t=>{const e=t===this.options.perPage,i=new Option(t,t,e,e);s.add(i)})),e=e.replace("{select}",s.outerHTML),t=t.replace("{select}",e)}else t=t.replace("{select}","");if(this.options.searchable){const e=``;t=t.replace("{search}",e)}else t=t.replace("{search}","");this.hasHeadings&&this.renderHeader(),this.dom.classList.add("dataTable-table");const e=a("nav",{class:"dataTable-pagination"}),s=a("ul",{class:"dataTable-pagination-list"});e.appendChild(s),t=t.replace(/\{pager\}/g,e.outerHTML),this.wrapper.innerHTML=t,this.container=this.wrapper.querySelector(".dataTable-container"),this.pagers=this.wrapper.querySelectorAll(".dataTable-pagination-list"),this.label=this.wrapper.querySelector(".dataTable-info"),this.dom.parentNode.replaceChild(this.wrapper,this.dom),this.container.appendChild(this.dom),this.rect=this.dom.getBoundingClientRect(),this.data=Array.from(this.body.rows),this.activeRows=this.data.slice(),this.activeHeadings=this.headings.slice(),this.update(),this.setColumns(),this.fixHeight(),this.fixColumns(),this.options.header||this.wrapper.classList.add("no-header"),this.options.footer||this.wrapper.classList.add("no-footer"),this.options.sortable&&this.wrapper.classList.add("sortable"),this.options.searchable&&this.wrapper.classList.add("searchable"),this.options.fixedHeight&&this.wrapper.classList.add("fixed-height"),this.options.fixedColumns&&this.wrapper.classList.add("fixed-columns"),this.bindEvents()}renderPage(t=!1){if(this.hasHeadings&&(n(this.header),this.activeHeadings.forEach((t=>this.header.appendChild(t)))),this.hasRows&&this.totalPages){this.currentPage>this.totalPages&&(this.currentPage=1);const t=this.currentPage-1,e=document.createDocumentFragment();this.pages[t].forEach((t=>e.appendChild(this.rows.render(t)))),this.clear(e),this.onFirstPage=1===this.currentPage,this.onLastPage=this.currentPage===this.lastPage}else this.setMessage(this.options.labels.noRows);let e,s=0,i=0,a=0;if(this.totalPages&&(s=this.currentPage-1,i=s*this.options.perPage,a=i+this.pages[s].length,i+=1,e=this.searching?this.searchData.length:this.data.length),this.label&&this.options.labels.info.length){const t=this.options.labels.info.replace("{start}",i).replace("{end}",a).replace("{page}",this.currentPage).replace("{pages}",this.totalPages).replace("{rows}",e);this.label.innerHTML=e?t:""}if(1==this.currentPage&&this.fixHeight(),this.options.rowNavigation&&(!this.rows.cursor||!this.pages[this.currentPage-1].includes(this.rows.cursor))){const e=this.pages[this.currentPage-1];t?this.rows.setCursor(e[e.length-1]):this.rows.setCursor(e[0])}}renderPager(){if(n(this.pagers),this.totalPages>1){const t="pager",e=document.createDocumentFragment(),s=this.onFirstPage?1:this.currentPage-1,i=this.onLastPage?this.totalPages:this.currentPage+1;this.options.firstLast&&e.appendChild(r(t,1,this.options.firstText)),this.options.nextPrev&&!this.onFirstPage&&e.appendChild(r(t,s,this.options.prevText));let n=this.links;this.options.truncatePager&&(n=((t,e,s,i,n)=>{let r;const o=2*(i=i||2);let h=e-i,l=e+i;const d=[],c=[];e<4-i+o?l=3+o:e>s-(3-i+o)&&(h=s-(2+o));for(let e=1;e<=s;e++)if(1==e||e==s||e>=h&&e<=l){const s=t[e-1];s.classList.remove("active"),d.push(s)}return d.forEach((e=>{const s=e.children[0].getAttribute("data-page");if(r){const e=r.children[0].getAttribute("data-page");if(s-e==2)c.push(t[e]);else if(s-e!=1){const t=a("li",{class:"ellipsis",html:`${n}`});c.push(t)}}c.push(e),r=e})),c})(this.links,this.currentPage,this.pages.length,this.options.pagerDelta,this.options.ellipsisText)),this.links[this.currentPage-1].classList.add("active"),n.forEach((t=>{t.classList.remove("active"),e.appendChild(t)})),this.links[this.currentPage-1].classList.add("active"),this.options.nextPrev&&!this.onLastPage&&e.appendChild(r(t,i,this.options.nextText)),this.options.firstLast&&e.appendChild(r(t,this.totalPages,this.options.lastText)),this.pagers.forEach((t=>{t.appendChild(e.cloneNode(!0))}))}}renderHeader(){this.labels=[],this.headings&&this.headings.length&&this.headings.forEach(((t,e)=>{if(this.labels[e]=t.textContent,t.firstElementChild&&t.firstElementChild.classList.contains("dataTable-sorter")&&(t.innerHTML=t.firstElementChild.innerHTML),t.sortable="false"!==t.getAttribute("data-sortable"),t.originalCellIndex=e,this.options.sortable&&t.sortable){const e=a("a",{href:"#",class:"dataTable-sorter",html:t.innerHTML});t.innerHTML="",t.setAttribute("data-sortable",""),t.appendChild(e)}})),this.fixColumns()}bindEvents(){if(this.options.perPageSelect){const t=this.wrapper.querySelector(".dataTable-selector");t&&t.addEventListener("change",(()=>{this.options.perPage=parseInt(t.value,10),this.update(),this.fixHeight(),this.emit("datatable.perpage",this.options.perPage)}),!1)}this.options.searchable&&(this.input=this.wrapper.querySelector(".dataTable-input"),this.input&&this.input.addEventListener("keyup",(()=>this.search(this.input.value)),!1)),this.wrapper.addEventListener("click",(t=>{const e=t.target.closest("a");e&&"a"===e.nodeName.toLowerCase()&&(e.hasAttribute("data-page")?(this.page(e.getAttribute("data-page")),t.preventDefault()):this.options.sortable&&e.classList.contains("dataTable-sorter")&&"false"!=e.parentNode.getAttribute("data-sortable")&&(this.columns.sort(this.headings.indexOf(e.parentNode)),t.preventDefault()))}),!1),this.options.rowNavigation?(this.table.addEventListener("keydown",(t=>{38===t.keyCode?this.rows.cursor.previousElementSibling?(this.rows.setCursor(this.rows.cursor.previousElementSibling),t.preventDefault(),t.stopPropagation()):this.onFirstPage||this.page(this.currentPage-1,!0):40===t.keyCode?this.rows.cursor.nextElementSibling?(this.rows.setCursor(this.rows.cursor.nextElementSibling),t.preventDefault(),t.stopPropagation()):this.onLastPage||this.page(this.currentPage+1):[13,32].includes(t.keyCode)&&this.emit("datatable.selectrow",this.rows.cursor,t)})),this.body.addEventListener("mousedown",(t=>{if(this.table.matches(":focus")){const e=Array.from(this.body.rows).find((e=>e.contains(t.target)));this.emit("datatable.selectrow",e,t)}}))):this.body.addEventListener("mousedown",(t=>{const e=Array.from(this.body.rows).find((e=>e.contains(t.target)));this.emit("datatable.selectrow",{event:t,row:e})})),window.addEventListener("resize",this.listeners.onResize)}onResize(){this.rect=this.container.getBoundingClientRect(),this.rect.width&&this.fixColumns()}setColumns(t){t||this.data.forEach((t=>{Array.from(t.cells).forEach((t=>{t.data=t.innerHTML}))})),this.options.columns&&this.headings.length&&this.options.columns.forEach((t=>{Array.isArray(t.select)||(t.select=[t.select]),t.hasOwnProperty("render")&&"function"==typeof t.render&&(this.selectedColumns=this.selectedColumns.concat(t.select),this.columnRenderers.push({columns:t.select,renderer:t.render})),t.select.forEach((e=>{const s=this.headings[e];s&&(t.type&&s.setAttribute("data-type",t.type),t.format&&s.setAttribute("data-format",t.format),t.hasOwnProperty("sortable")&&s.setAttribute("data-sortable",t.sortable),t.hasOwnProperty("hidden")&&!1!==t.hidden&&this.columns.hide([e]),t.hasOwnProperty("sort")&&1===t.select.length&&this.columns.sort(t.select[0],t.sort,!0))}))})),this.hasRows&&(this.data.forEach(((t,e)=>{t.dataIndex=e,Array.from(t.cells).forEach((t=>{t.data=t.innerHTML}))})),this.selectedColumns.length&&this.data.forEach((t=>{Array.from(t.cells).forEach(((e,s)=>{this.selectedColumns.includes(s)&&this.columnRenderers.forEach((i=>{i.columns.includes(s)&&(e.innerHTML=i.renderer.call(this,e.data,e,t))}))}))})),this.columns.rebuild()),this.renderHeader()}destroy(){this.dom.innerHTML=this.initialLayout,this.dom.classList.remove("dataTable-table"),this.wrapper.parentNode.replaceChild(this.dom,this.wrapper),this.initialized=!1,window.removeEventListener("resize",this.listeners.onResize)}update(){this.wrapper.classList.remove("dataTable-empty"),this.paginate(),this.renderPage(),this.links=[];let t=this.pages.length;for(;t--;){const e=t+1;this.links[t]=r(0===t?"active":"",e,e)}this.sorting=!1,this.renderPager(),this.rows.update(),this.emit("datatable.update")}paginate(){let t=this.activeRows;return this.searching&&(t=[],this.searchData.forEach((e=>t.push(this.activeRows[e])))),this.options.paging?this.pages=t.map(((e,s)=>s%this.options.perPage==0?t.slice(s,s+this.options.perPage):null)).filter((t=>t)):this.pages=[t],this.totalPages=this.lastPage=this.pages.length,this.totalPages}fixColumns(){if((this.options.scrollY.length||this.options.fixedColumns)&&this.activeHeadings&&this.activeHeadings.length){let t,e=!1;if(this.columnWidths=[],this.dom.tHead){this.options.scrollY.length&&(e=a("thead"),e.appendChild(a("tr")),e.style.height="0px",this.headerTable&&(this.dom.tHead=this.headerTable.tHead)),this.activeHeadings.forEach((t=>{t.style.width=""}));const t=this.activeHeadings.reduce(((t,e)=>t+e.offsetWidth),0);if(this.activeHeadings.forEach(((s,i)=>{const n=s.offsetWidth,r=n/t*100;if(s.style.width=`${r}%`,this.columnWidths[i]=n,this.options.scrollY.length){const t=a("th");e.firstElementChild.appendChild(t),t.style.width=`${r}%`,t.style.paddingTop="0",t.style.paddingBottom="0",t.style.border="0"}})),this.options.scrollY.length){const t=this.dom.parentElement;if(!this.headerTable){this.headerTable=a("table",{class:"dataTable-table"});const e=a("div",{class:"dataTable-headercontainer"});e.appendChild(this.headerTable),t.parentElement.insertBefore(e,t)}const s=this.dom.tHead;this.dom.replaceChild(e,s),this.headerTable.tHead=s,this.headerTable.parentElement.style.paddingRight=`${this.headerTable.clientWidth-this.dom.clientWidth+parseInt(this.headerTable.parentElement.style.paddingRight||"0",10)}px`,t.scrollHeight>t.clientHeight&&(t.style.overflowY="scroll")}}else{t=[],e=a("thead");const s=a("tr");Array.from(this.dom.tBodies[0].rows[0].cells).forEach((()=>{const e=a("th");s.appendChild(e),t.push(e)})),e.appendChild(s),this.dom.insertBefore(e,this.body);const i=[];t.forEach(((t,e)=>{const s=t.offsetWidth,a=s/this.rect.width*100;i.push(a),this.columnWidths[e]=s})),this.data.forEach((t=>{Array.from(t.cells).forEach(((t,e)=>{this.columns.visible(t.cellIndex)&&(t.style.width=`${i[e]}%`)}))})),this.dom.removeChild(e)}}}fixHeight(){this.options.fixedHeight&&(this.container.style.height=null,this.rect=this.container.getBoundingClientRect(),this.container.style.height=`${this.rect.height}px`)}search(t){return!!this.hasRows&&(t=t.toLowerCase(),this.currentPage=1,this.searching=!0,this.searchData=[],t.length?(this.clear(),this.data.forEach(((e,s)=>{const i=this.searchData.includes(e);t.split(" ").reduce(((t,s)=>{let i=!1,a=null,n=null;for(let t=0;tthis.pages.length||t<0)&&(this.renderPage(e),this.renderPager(),void this.emit("datatable.page",t)))}sortColumn(t,e){this.columns.sort(t,e)}insert(t){let e=[];if(i(t)){if(t.headings&&!this.hasHeadings&&!this.hasRows){const e=a("tr");t.headings.forEach((t=>{const s=a("th",{html:t});e.appendChild(s)})),this.head.appendChild(e),this.header=e,this.headings=[].slice.call(e.cells),this.hasHeadings=!0,this.options.sortable=this.initialSortable,this.renderHeader(),this.activeHeadings=this.headings.slice()}t.data&&Array.isArray(t.data)&&(e=t.data)}else Array.isArray(t)&&t.forEach((t=>{const s=[];Object.entries(t).forEach((([t,e])=>{const i=this.labels.indexOf(t);i>-1&&(s[i]=e)})),e.push(s)}));e.length&&(this.rows.add(e),this.hasRows=!0),this.update(),this.setColumns(),this.fixColumns()}refresh(){this.options.searchable&&(this.input.value="",this.searching=!1),this.currentPage=1,this.onFirstPage=!0,this.update(),this.emit("datatable.refresh")}clear(t){this.body&&n(this.body);let e=this.body;this.body||(e=this.dom),t&&("string"==typeof t&&(document.createDocumentFragment().innerHTML=t),e.appendChild(t))}export(t){if(!this.hasHeadings&&!this.hasRows)return!1;const e=this.activeHeadings;let s=[];const a=[];let n,r,o,h;if(!i(t))return!1;const l={download:!0,skipColumn:[],lineDelimiter:"\n",columnDelimiter:",",tableName:"myTable",replacer:null,space:4,...t};if(l.type){if("txt"!==l.type&&"csv"!==l.type||(s[0]=this.header),l.selection)if(isNaN(l.selection)){if(Array.isArray(l.selection))for(n=0;nt.trim().replace(/(^"|"$)/g,"")))),t.shift()),t.forEach(((t,i)=>{e.data[i]=[];const a=t.split(s.columnDelimiter);a.length&&a.forEach((t=>{s.removeDoubleQuotes&&(t=t.trim().replace(/(^"|"$)/g,"")),e.data[i].push(t)}))})))}else if("json"===s.type){const t=(t=>{let e=!1;try{e=JSON.parse(t)}catch(t){return!1}return!(null===e||!Array.isArray(e)&&!i(e))&&e})(s.data);t&&(e={headings:[],data:[]},t.forEach(((t,s)=>{e.data[s]=[],Object.entries(t).forEach((([t,i])=>{e.headings.includes(t)||e.headings.push(t),e.data[s].push(i)}))})))}i(s.data)&&(e=s.data),e&&this.insert(e)}return!1}print(){const t=this.activeHeadings,e=this.activeRows,s=a("table"),i=a("thead"),n=a("tbody"),r=a("tr");t.forEach((t=>{r.appendChild(a("th",{html:t.textContent}))})),i.appendChild(r),e.forEach((t=>{const e=a("tr");Array.from(t.cells).forEach((t=>{e.appendChild(a("td",{html:t.textContent}))})),n.appendChild(e)})),s.appendChild(i),s.appendChild(n);const o=window.open();o.document.body.appendChild(s),o.print()}setMessage(t){let e=1;this.hasRows?e=this.data[0].cells.length:this.activeHeadings.length&&(e=this.activeHeadings.length),this.wrapper.classList.add("dataTable-empty"),this.label&&(this.label.innerHTML=""),this.totalPages=0,this.renderPager(),this.clear(a("tr",{html:`${t} | `}))}on(t,e){this.events=this.events||{},this.events[t]=this.events[t]||[],this.events[t].push(e)}off(t,e){this.events=this.events||{},t in this.events!=0&&this.events[t].splice(this.events[t].indexOf(e),1)}emit(t){if(this.events=this.events||{},t in this.events!=0)for(let e=0;e
-
+
diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
index 57e13f3a..e8fc6b49 100644
--- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
+++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
@@ -8,26 +8,10 @@
-
From 368d82c0074f50c0f6e7cf54d1ae71330cc7ba55 Mon Sep 17 00:00:00 2001
From: Lint Action
Date: Mon, 28 Nov 2022 14:05:48 +0000
Subject: [PATCH 28/49] Fix code style issues with ESLint
---
.../static/js/simple-datatables.js | 98 ++++++++++++++++++-
1 file changed, 96 insertions(+), 2 deletions(-)
diff --git a/ereuse_devicehub/static/js/simple-datatables.js b/ereuse_devicehub/static/js/simple-datatables.js
index 7ff88719..6e1465d8 100644
--- a/ereuse_devicehub/static/js/simple-datatables.js
+++ b/ereuse_devicehub/static/js/simple-datatables.js
@@ -4,5 +4,99 @@
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).simpleDatatables=t()}}((function(){return function t(e,s,i){function a(r,o){if(!s[r]){if(!e[r]){var h="function"==typeof require&&require;if(!o&&h)return h(r,!0);if(n)return n(r,!0);var l=new Error("Cannot find module '"+r+"'");throw l.code="MODULE_NOT_FOUND",l}var d=s[r]={exports:{}};e[r][0].call(d.exports,(function(t){return a(e[r][1][t]||t)}),d,d.exports,t,e,s,i)}return s[r].exports}for(var n="function"==typeof require&&require,r=0;r=e?t:""+Array(e+1-i.length).join(s)+t},b={s:m,z:function(t){var e=-t.utcOffset(),s=Math.abs(e),i=Math.floor(s/60),a=s%60;return(e<=0?"+":"-")+m(i,2,"0")+":"+m(a,2,"0")},m:function t(e,s){if(e.date()1)return t(r[0])}else{var o=e.name;y[o]=e,a=o}return!i&&a&&(v=a),a||!i&&v},x=function(t,e){if(w(t))return t.clone();var s="object"==typeof e?e:{};return s.date=t,s.args=arguments,new T(s)},M=b;M.l=C,M.i=w,M.w=function(t,e){return x(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var T=function(){function g(t){this.$L=C(t.locale,null,!0),this.parse(t)}var m=g.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,s=t.utc;if(null===e)return new Date(NaN);if(M.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var i=e.match(p);if(i){var a=i[2]-1||0,n=(i[7]||"0").substring(0,3);return s?new Date(Date.UTC(i[1],a,i[3]||1,i[4]||0,i[5]||0,i[6]||0,n)):new Date(i[1],a,i[3]||1,i[4]||0,i[5]||0,i[6]||0,n)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return M},m.isValid=function(){return!(this.$d.toString()===u)},m.isSame=function(t,e){var s=x(t);return this.startOf(e)<=s&&s<=this.endOf(e)},m.isAfter=function(t,e){return x(t)68?1900:2e3)},o=function(t){return function(e){this[t]=+e}},h=[/[+-]\d\d:?(\d\d)?|Z/,function(t){(this.zone||(this.zone={})).offset=function(t){if(!t)return 0;if("Z"===t)return 0;var e=t.match(/([+-]|\d\d)/g),s=60*e[1]+(+e[2]||0);return 0===s?0:"+"===e[0]?-s:s}(t)}],l=function(t){var e=n[t];return e&&(e.indexOf?e:e.s.concat(e.f))},d=function(t,e){var s,i=n.meridiem;if(i){for(var a=1;a<=24;a+=1)if(t.indexOf(i(a,0,e))>-1){s=a>12;break}}else s=t===(e?"pm":"PM");return s},c={A:[a,function(t){this.afternoon=d(t,!1)}],a:[a,function(t){this.afternoon=d(t,!0)}],S:[/\d/,function(t){this.milliseconds=100*+t}],SS:[s,function(t){this.milliseconds=10*+t}],SSS:[/\d{3}/,function(t){this.milliseconds=+t}],s:[i,o("seconds")],ss:[i,o("seconds")],m:[i,o("minutes")],mm:[i,o("minutes")],H:[i,o("hours")],h:[i,o("hours")],HH:[i,o("hours")],hh:[i,o("hours")],D:[i,o("day")],DD:[s,o("day")],Do:[a,function(t){var e=n.ordinal,s=t.match(/\d+/);if(this.day=s[0],e)for(var i=1;i<=31;i+=1)e(i).replace(/\[|\]/g,"")===t&&(this.day=i)}],M:[i,o("month")],MM:[s,o("month")],MMM:[a,function(t){var e=l("months"),s=(l("monthsShort")||e.map((function(t){return t.slice(0,3)}))).indexOf(t)+1;if(s<1)throw new Error;this.month=s%12||s}],MMMM:[a,function(t){var e=l("months").indexOf(t)+1;if(e<1)throw new Error;this.month=e%12||e}],Y:[/[+-]?\d+/,o("year")],YY:[s,function(t){this.year=r(t)}],YYYY:[/\d{4}/,o("year")],Z:h,ZZ:h};function u(s){var i,a;i=s,a=n&&n.formats;for(var r=(s=i.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(e,s,i){var n=i&&i.toUpperCase();return s||a[i]||t[i]||a[n].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,(function(t,e,s){return e||s.slice(1)}))}))).match(e),o=r.length,h=0;h-1)return new Date(("X"===e?1e3:1)*t);var i=u(e)(t),a=i.year,n=i.month,r=i.day,o=i.hours,h=i.minutes,l=i.seconds,d=i.milliseconds,c=i.zone,p=new Date,f=r||(a||n?1:p.getDate()),g=a||p.getFullYear(),m=0;a&&!n||(m=n>0?n-1:p.getMonth());var b=o||0,v=h||0,y=l||0,w=d||0;return c?new Date(Date.UTC(g,m,f,b,v,y,w+60*c.offset*1e3)):s?new Date(Date.UTC(g,m,f,b,v,y,w)):new Date(g,m,f,b,v,y,w)}catch(t){return new Date("")}}(e,o,i),this.init(),c&&!0!==c&&(this.$L=this.locale(c).$L),d&&e!=this.format(o)&&(this.$d=new Date("")),n={}}else if(o instanceof Array)for(var p=o.length,f=1;f<=p;f+=1){r[1]=o[f-1];var g=s.apply(this,r);if(g.isValid()){this.$d=g.$d,this.$L=g.$L,this.init();break}f===p&&(this.$d=new Date(""))}else a.call(this,t)}}}();e.extend(i),s.parseDate=(t,s)=>{let i=!1;if(s)switch(s){case"ISO_8601":i=t;break;case"RFC_2822":i=e(t.slice(5),"DD MMM YYYY HH:mm:ss ZZ").unix();break;case"MYSQL":i=e(t,"YYYY-MM-DD hh:mm:ss").unix();break;case"UNIX":i=e(t).unix();break;default:i=e(t,s,!0).valueOf()}return i}}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],2:[function(t,e,s){"use strict";Object.defineProperty(s,"__esModule",{value:!0});const i=t=>"[object Object]"===Object.prototype.toString.call(t),a=(t,e)=>{const s=document.createElement(t);if(e&&"object"==typeof e)for(const t in e)"html"===t?s.innerHTML=e[t]:s.setAttribute(t,e[t]);return s},n=t=>{t instanceof NodeList?t.forEach((t=>n(t))):t.innerHTML=""},r=(t,e,s)=>a("li",{class:t,html:`${s}`}),o=(t,e)=>{let s,i;1===e?(s=0,i=t.length):-1===e&&(s=t.length-1,i=-1);for(let a=!0;a;){a=!1;for(let n=s;n!=i;n+=e)if(t[n+e]&&t[n].value>t[n+e].value){const s=t[n],i=t[n+e],r=s;t[n]=i,t[n+e]=r,a=!0}}return t};class h{constructor(t){this.dt=t,this.cursor=!1}build(t){const e=a("tr");let s=this.dt.headings;return s.length||(s=t.map((()=>""))),s.forEach(((s,i)=>{const n=a("td");t[i]&&t[i].length||(t[i]=""),n.innerHTML=t[i],n.data=t[i],e.appendChild(n)})),e}setCursor(t=!1){this.cursor&&this.cursor.classList.remove("dataTable-cursor"),t&&(t.classList.add("dataTable-cursor"),this.cursor=t)}render(t){return t}add(t){if(Array.isArray(t)){const e=this.dt;Array.isArray(t[0])?t.forEach((t=>{e.data.push(this.build(t))})):e.data.push(this.build(t)),e.data.length&&(e.hasRows=!0),this.update(),e.columns.rebuild()}}remove(t){const e=this.dt;Array.isArray(t)?(t.sort(((t,e)=>e-t)),t.forEach((t=>{e.data.splice(t,1)}))):"all"==t?e.data=[]:e.data.splice(t,1),e.data.length||(e.hasRows=!1),this.update(),e.columns.rebuild()}update(){this.dt.data.forEach(((t,e)=>{t.dataIndex=e}))}findRowIndex(t,e){return this.dt.data.findIndex((s=>s.children[t].innerText.toLowerCase().includes(String(e).toLowerCase())))}findRow(t,e){const s=this.findRowIndex(t,e);if(s<0)return{index:-1,row:null,cols:[]};const i=this.dt.data[s];return{index:s,row:i,cols:[...i.cells].map((t=>t.innerHTML))}}updateRow(t,e){const s=this.build(e);this.dt.data.splice(t,1,s),this.update(),this.dt.columns.rebuild()}}class l{constructor(t){this.dt=t}swap(t){if(t.length&&2===t.length){const e=[];this.dt.headings.forEach(((t,s)=>{e.push(s)}));const s=t[0],i=t[1],a=e[i];e[i]=e[s],e[s]=a,this.order(e)}}order(t){let e,s,i,a,n,r,o;const h=[[],[],[],[]],l=this.dt;t.forEach(((t,i)=>{n=l.headings[t],r="false"!==n.getAttribute("data-sortable"),e=n.cloneNode(!0),e.originalCellIndex=i,e.sortable=r,h[0].push(e),l.hiddenColumns.includes(t)||(s=n.cloneNode(!0),s.originalCellIndex=i,s.sortable=r,h[1].push(s))})),l.data.forEach(((e,s)=>{i=e.cloneNode(!1),a=e.cloneNode(!1),i.dataIndex=a.dataIndex=s,null!==e.searchIndex&&void 0!==e.searchIndex&&(i.searchIndex=a.searchIndex=e.searchIndex),t.forEach((t=>{o=e.cells[t].cloneNode(!0),o.data=e.cells[t].data,i.appendChild(o),l.hiddenColumns.includes(t)||(o=e.cells[t].cloneNode(!0),o.data=e.cells[t].data,a.appendChild(o))})),h[2].push(i),h[3].push(a)})),l.headings=h[0],l.activeHeadings=h[1],l.data=h[2],l.activeRows=h[3],l.update()}hide(t){if(t.length){const e=this.dt;t.forEach((t=>{e.hiddenColumns.includes(t)||e.hiddenColumns.push(t)})),this.rebuild()}}show(t){if(t.length){let e;const s=this.dt;t.forEach((t=>{e=s.hiddenColumns.indexOf(t),e>-1&&s.hiddenColumns.splice(e,1)})),this.rebuild()}}visible(t){let e;const s=this.dt;return t=t||s.headings.map((t=>t.originalCellIndex)),isNaN(t)?Array.isArray(t)&&(e=[],t.forEach((t=>{e.push(!s.hiddenColumns.includes(t))}))):e=!s.hiddenColumns.includes(t),e}add(t){let e;const s=document.createElement("th");if(!this.dt.headings.length)return this.dt.insert({headings:[t.heading],data:t.data.map((t=>[t]))}),void this.rebuild();this.dt.hiddenHeader?s.innerHTML="":t.heading.nodeName?s.appendChild(t.heading):s.innerHTML=t.heading,this.dt.headings.push(s),this.dt.data.forEach(((s,i)=>{t.data[i]&&(e=document.createElement("td"),t.data[i].nodeName?e.appendChild(t.data[i]):e.innerHTML=t.data[i],e.data=e.innerHTML,t.render&&(e.innerHTML=t.render.call(this,e.data,e,s)),s.appendChild(e))})),t.type&&s.setAttribute("data-type",t.type),t.format&&s.setAttribute("data-format",t.format),t.hasOwnProperty("sortable")&&(s.sortable=t.sortable,s.setAttribute("data-sortable",!0===t.sortable?"true":"false")),this.rebuild(),this.dt.renderHeader()}remove(t){Array.isArray(t)?(t.sort(((t,e)=>e-t)),t.forEach((t=>this.remove(t)))):(this.dt.headings.splice(t,1),this.dt.data.forEach((e=>{e.removeChild(e.cells[t])}))),this.rebuild()}filter(t,e,s,i){const a=this.dt;if(a.filterState||(a.filterState={originalData:a.data}),!a.filterState[t]){const e=[...i,()=>!0];a.filterState[t]=function(){let t=0;return()=>e[t++%e.length]}()}const n=a.filterState[t](),r=Array.from(a.filterState.originalData).filter((e=>{const s=e.cells[t],i=s.hasAttribute("data-content")?s.getAttribute("data-content"):s.innerText;return"function"==typeof n?n(i):i===n}));a.data=r,a.data.length?(this.rebuild(),a.update()):(a.clear(),a.hasRows=!1,a.setMessage(a.options.labels.noRows)),s||a.emit("datatable.sort",t,e)}sort(e,s,i){const a=this.dt;if(a.hasHeadings&&(e<0||e>a.headings.length))return!1;const n=a.options.filters&&a.options.filters[a.headings[e].textContent];if(n&&0!==n.length)return void this.filter(e,s,i,n);a.sorting=!0,i||a.emit("datatable.sorting",e,s);let r=a.data;const h=[],l=[];let d=0,c=0;const u=a.headings[e],p=[];if("date"===u.getAttribute("data-type")){let e=!1;u.hasAttribute("data-format")&&(e=u.getAttribute("data-format")),p.push(Promise.resolve().then((function(){return t("./date-7061ceee.js")})).then((({parseDate:t})=>s=>t(s,e))))}Promise.all(p).then((t=>{const n=t[0];let p,f;Array.from(r).forEach((t=>{const s=t.cells[e],i=s.hasAttribute("data-content")?s.getAttribute("data-content"):s.innerText;let a;a=n?n(i):"string"==typeof i?i.replace(/(\$|,|\s|%)/g,""):i,parseFloat(a)==a?l[c++]={value:Number(a),row:t}:h[d++]={value:"string"==typeof i?i.toLowerCase():i,row:t}})),s||(s=u.classList.contains("asc")?"desc":"asc"),"desc"==s?(p=o(h,-1),f=o(l,-1),u.classList.remove("asc"),u.classList.add("desc"),u.setAttribute("aria-sort","descending")):(p=o(l,1),f=o(h,1),u.classList.remove("desc"),u.classList.add("asc"),u.setAttribute("aria-sort","ascending")),a.lastTh&&u!=a.lastTh&&(a.lastTh.classList.remove("desc"),a.lastTh.classList.remove("asc"),a.lastTh.removeAttribute("aria-sort")),a.lastTh=u,r=p.concat(f),a.data=[];const g=[];r.forEach(((t,e)=>{a.data.push(t.row),null!==t.row.searchIndex&&void 0!==t.row.searchIndex&&g.push(e)})),a.searchData=g,this.rebuild(),a.update(),i||a.emit("datatable.sort",e,s)}))}rebuild(){let t,e,s,i;const a=this.dt,n=[];a.activeRows=[],a.activeHeadings=[],a.headings.forEach(((t,e)=>{t.originalCellIndex=e,t.sortable="false"!==t.getAttribute("data-sortable"),a.hiddenColumns.includes(e)||a.activeHeadings.push(t)})),a.data.forEach(((r,o)=>{t=r.cloneNode(!1),e=r.cloneNode(!1),t.dataIndex=e.dataIndex=o,null!==r.searchIndex&&void 0!==r.searchIndex&&(t.searchIndex=e.searchIndex=r.searchIndex),Array.from(r.cells).forEach((n=>{s=n.cloneNode(!0),s.data=n.data,t.appendChild(s),a.hiddenColumns.includes(s.cellIndex)||(i=s.cloneNode(!0),i.data=s.data,e.appendChild(i))})),n.push(t),a.activeRows.push(e)})),a.data=n,a.update()}}const d=function(t){let e=!1,s=!1;if((t=t||this.options.data).headings){e=a("thead");const s=a("tr");t.headings.forEach((t=>{const e=a("th",{html:t});s.appendChild(e)})),e.appendChild(s)}t.data&&t.data.length&&(s=a("tbody"),t.data.forEach((e=>{if(t.headings&&t.headings.length!==e.length)throw new Error("The number of rows do not match the number of headings.");const i=a("tr");e.forEach((t=>{const e=a("td",{html:t});i.appendChild(e)})),s.appendChild(i)}))),e&&(null!==this.dom.tHead&&this.dom.removeChild(this.dom.tHead),this.dom.appendChild(e)),s&&(this.dom.tBodies.length&&this.dom.removeChild(this.dom.tBodies[0]),this.dom.appendChild(s))},c={sortable:!0,searchable:!0,paging:!0,perPage:10,perPageSelect:[5,10,15,20,25],nextPrev:!0,firstLast:!1,prevText:"‹",nextText:"›",firstText:"«",lastText:"»",ellipsisText:"…",ascText:"▴",descText:"▾",truncatePager:!0,pagerDelta:2,scrollY:"",fixedColumns:!0,fixedHeight:!1,header:!0,hiddenHeader:!1,footer:!1,tabIndex:!1,rowNavigation:!1,labels:{placeholder:"Search on page...",perPage:"{select} entries per page",noRows:"No entries found",noResults:"No results match your search query",info:"Showing {start} to {end} of {rows} entries"},layout:{top:"{select}{search}",bottom:"{info}{pager}"}};s.DataTable=class{constructor(t,e={}){const s="string"==typeof t?document.querySelector(t):t;if(this.options={...c,...e,layout:{...c.layout,...e.layout},labels:{...c.labels,...e.labels}},this.rows=new h(this),this.columns=new l(this),this.initialized=!1,this.initialLayout=s.innerHTML,this.initialSortable=this.options.sortable,this.options.tabIndex?s.tabIndex=this.options.tabIndex:this.options.rowNavigation&&-1===s.tabIndex&&(s.tabIndex=0),this.options.header||(this.options.sortable=!1),null===s.tHead&&(!this.options.data||this.options.data&&!this.options.data.headings)&&(this.options.sortable=!1),s.tBodies.length&&!s.tBodies[0].rows.length&&this.options.data&&!this.options.data.data)throw new Error("You seem to be using the data option, but you've not defined any rows.");this.dom=s,this.table=this.dom,this.listeners={onResize:t=>this.onResize(t)},this.init()}init(t){if(this.initialized||this.dom.classList.contains("dataTable-table"))return!1;Object.assign(this.options,t||{}),this.currentPage=1,this.onFirstPage=!0,this.hiddenColumns=[],this.columnRenderers=[],this.selectedColumns=[],this.render(),setTimeout((()=>{this.emit("datatable.init"),this.initialized=!0,this.options.plugins&&Object.entries(this.options.plugins).forEach((([t,e])=>{this[t]&&"function"==typeof this[t]&&(this[t]=this[t](e,{createElement:a}),e.enabled&&this[t].init&&"function"==typeof this[t].init&&this[t].init())}))}),10)}render(){let t="";if(this.options.data&&d.call(this),this.body=this.dom.tBodies[0],this.head=this.dom.tHead,this.foot=this.dom.tFoot,this.body||(this.body=a("tbody"),this.dom.appendChild(this.body)),this.hasRows=this.body.rows.length>0,!this.head){const t=a("thead"),e=a("tr");this.hasRows&&(Array.from(this.body.rows[0].cells).forEach((()=>{e.appendChild(a("th"))})),t.appendChild(e)),this.head=t,this.dom.insertBefore(this.head,this.body),this.hiddenHeader=this.options.hiddenHeader}if(this.headings=[],this.hasHeadings=this.head.rows.length>0,this.hasHeadings&&(this.header=this.head.rows[0],this.headings=[].slice.call(this.header.cells)),this.options.header||this.head&&this.dom.removeChild(this.dom.tHead),this.options.footer?this.head&&!this.foot&&(this.foot=a("tfoot",{html:this.head.innerHTML}),this.dom.appendChild(this.foot)):this.foot&&this.dom.removeChild(this.dom.tFoot),this.wrapper=a("div",{class:"dataTable-wrapper dataTable-loading"}),t+="",t+=this.options.layout.top,t+="
",this.options.scrollY.length?t+=``:t+="",t+="",t+=this.options.layout.bottom,t+="
",t=t.replace("{info}",this.options.paging?"":""),this.options.paging&&this.options.perPageSelect){let e="";const s=a("select",{class:"dataTable-selector"});this.options.perPageSelect.forEach((t=>{const e=t===this.options.perPage,i=new Option(t,t,e,e);s.add(i)})),e=e.replace("{select}",s.outerHTML),t=t.replace("{select}",e)}else t=t.replace("{select}","");if(this.options.searchable){const e=``;t=t.replace("{search}",e)}else t=t.replace("{search}","");this.hasHeadings&&this.renderHeader(),this.dom.classList.add("dataTable-table");const e=a("nav",{class:"dataTable-pagination"}),s=a("ul",{class:"dataTable-pagination-list"});e.appendChild(s),t=t.replace(/\{pager\}/g,e.outerHTML),this.wrapper.innerHTML=t,this.container=this.wrapper.querySelector(".dataTable-container"),this.pagers=this.wrapper.querySelectorAll(".dataTable-pagination-list"),this.label=this.wrapper.querySelector(".dataTable-info"),this.dom.parentNode.replaceChild(this.wrapper,this.dom),this.container.appendChild(this.dom),this.rect=this.dom.getBoundingClientRect(),this.data=Array.from(this.body.rows),this.activeRows=this.data.slice(),this.activeHeadings=this.headings.slice(),this.update(),this.setColumns(),this.fixHeight(),this.fixColumns(),this.options.header||this.wrapper.classList.add("no-header"),this.options.footer||this.wrapper.classList.add("no-footer"),this.options.sortable&&this.wrapper.classList.add("sortable"),this.options.searchable&&this.wrapper.classList.add("searchable"),this.options.fixedHeight&&this.wrapper.classList.add("fixed-height"),this.options.fixedColumns&&this.wrapper.classList.add("fixed-columns"),this.bindEvents()}renderPage(t=!1){if(this.hasHeadings&&(n(this.header),this.activeHeadings.forEach((t=>this.header.appendChild(t)))),this.hasRows&&this.totalPages){this.currentPage>this.totalPages&&(this.currentPage=1);const t=this.currentPage-1,e=document.createDocumentFragment();this.pages[t].forEach((t=>e.appendChild(this.rows.render(t)))),this.clear(e),this.onFirstPage=1===this.currentPage,this.onLastPage=this.currentPage===this.lastPage}else this.setMessage(this.options.labels.noRows);let e,s=0,i=0,a=0;if(this.totalPages&&(s=this.currentPage-1,i=s*this.options.perPage,a=i+this.pages[s].length,i+=1,e=this.searching?this.searchData.length:this.data.length),this.label&&this.options.labels.info.length){const t=this.options.labels.info.replace("{start}",i).replace("{end}",a).replace("{page}",this.currentPage).replace("{pages}",this.totalPages).replace("{rows}",e);this.label.innerHTML=e?t:""}if(1==this.currentPage&&this.fixHeight(),this.options.rowNavigation&&(!this.rows.cursor||!this.pages[this.currentPage-1].includes(this.rows.cursor))){const e=this.pages[this.currentPage-1];t?this.rows.setCursor(e[e.length-1]):this.rows.setCursor(e[0])}}renderPager(){if(n(this.pagers),this.totalPages>1){const t="pager",e=document.createDocumentFragment(),s=this.onFirstPage?1:this.currentPage-1,i=this.onLastPage?this.totalPages:this.currentPage+1;this.options.firstLast&&e.appendChild(r(t,1,this.options.firstText)),this.options.nextPrev&&!this.onFirstPage&&e.appendChild(r(t,s,this.options.prevText));let n=this.links;this.options.truncatePager&&(n=((t,e,s,i,n)=>{let r;const o=2*(i=i||2);let h=e-i,l=e+i;const d=[],c=[];e<4-i+o?l=3+o:e>s-(3-i+o)&&(h=s-(2+o));for(let e=1;e<=s;e++)if(1==e||e==s||e>=h&&e<=l){const s=t[e-1];s.classList.remove("active"),d.push(s)}return d.forEach((e=>{const s=e.children[0].getAttribute("data-page");if(r){const e=r.children[0].getAttribute("data-page");if(s-e==2)c.push(t[e]);else if(s-e!=1){const t=a("li",{class:"ellipsis",html:`${n}`});c.push(t)}}c.push(e),r=e})),c})(this.links,this.currentPage,this.pages.length,this.options.pagerDelta,this.options.ellipsisText)),this.links[this.currentPage-1].classList.add("active"),n.forEach((t=>{t.classList.remove("active"),e.appendChild(t)})),this.links[this.currentPage-1].classList.add("active"),this.options.nextPrev&&!this.onLastPage&&e.appendChild(r(t,i,this.options.nextText)),this.options.firstLast&&e.appendChild(r(t,this.totalPages,this.options.lastText)),this.pagers.forEach((t=>{t.appendChild(e.cloneNode(!0))}))}}renderHeader(){this.labels=[],this.headings&&this.headings.length&&this.headings.forEach(((t,e)=>{if(this.labels[e]=t.textContent,t.firstElementChild&&t.firstElementChild.classList.contains("dataTable-sorter")&&(t.innerHTML=t.firstElementChild.innerHTML),t.sortable="false"!==t.getAttribute("data-sortable"),t.originalCellIndex=e,this.options.sortable&&t.sortable){const e=a("a",{href:"#",class:"dataTable-sorter",html:t.innerHTML});t.innerHTML="",t.setAttribute("data-sortable",""),t.appendChild(e)}})),this.fixColumns()}bindEvents(){if(this.options.perPageSelect){const t=this.wrapper.querySelector(".dataTable-selector");t&&t.addEventListener("change",(()=>{this.options.perPage=parseInt(t.value,10),this.update(),this.fixHeight(),this.emit("datatable.perpage",this.options.perPage)}),!1)}this.options.searchable&&(this.input=this.wrapper.querySelector(".dataTable-input"),this.input&&this.input.addEventListener("keyup",(()=>this.search(this.input.value)),!1)),this.wrapper.addEventListener("click",(t=>{const e=t.target.closest("a");e&&"a"===e.nodeName.toLowerCase()&&(e.hasAttribute("data-page")?(this.page(e.getAttribute("data-page")),t.preventDefault()):this.options.sortable&&e.classList.contains("dataTable-sorter")&&"false"!=e.parentNode.getAttribute("data-sortable")&&(this.columns.sort(this.headings.indexOf(e.parentNode)),t.preventDefault()))}),!1),this.options.rowNavigation?(this.table.addEventListener("keydown",(t=>{38===t.keyCode?this.rows.cursor.previousElementSibling?(this.rows.setCursor(this.rows.cursor.previousElementSibling),t.preventDefault(),t.stopPropagation()):this.onFirstPage||this.page(this.currentPage-1,!0):40===t.keyCode?this.rows.cursor.nextElementSibling?(this.rows.setCursor(this.rows.cursor.nextElementSibling),t.preventDefault(),t.stopPropagation()):this.onLastPage||this.page(this.currentPage+1):[13,32].includes(t.keyCode)&&this.emit("datatable.selectrow",this.rows.cursor,t)})),this.body.addEventListener("mousedown",(t=>{if(this.table.matches(":focus")){const e=Array.from(this.body.rows).find((e=>e.contains(t.target)));this.emit("datatable.selectrow",e,t)}}))):this.body.addEventListener("mousedown",(t=>{const e=Array.from(this.body.rows).find((e=>e.contains(t.target)));this.emit("datatable.selectrow",{event:t,row:e})})),window.addEventListener("resize",this.listeners.onResize)}onResize(){this.rect=this.container.getBoundingClientRect(),this.rect.width&&this.fixColumns()}setColumns(t){t||this.data.forEach((t=>{Array.from(t.cells).forEach((t=>{t.data=t.innerHTML}))})),this.options.columns&&this.headings.length&&this.options.columns.forEach((t=>{Array.isArray(t.select)||(t.select=[t.select]),t.hasOwnProperty("render")&&"function"==typeof t.render&&(this.selectedColumns=this.selectedColumns.concat(t.select),this.columnRenderers.push({columns:t.select,renderer:t.render})),t.select.forEach((e=>{const s=this.headings[e];s&&(t.type&&s.setAttribute("data-type",t.type),t.format&&s.setAttribute("data-format",t.format),t.hasOwnProperty("sortable")&&s.setAttribute("data-sortable",t.sortable),t.hasOwnProperty("hidden")&&!1!==t.hidden&&this.columns.hide([e]),t.hasOwnProperty("sort")&&1===t.select.length&&this.columns.sort(t.select[0],t.sort,!0))}))})),this.hasRows&&(this.data.forEach(((t,e)=>{t.dataIndex=e,Array.from(t.cells).forEach((t=>{t.data=t.innerHTML}))})),this.selectedColumns.length&&this.data.forEach((t=>{Array.from(t.cells).forEach(((e,s)=>{this.selectedColumns.includes(s)&&this.columnRenderers.forEach((i=>{i.columns.includes(s)&&(e.innerHTML=i.renderer.call(this,e.data,e,t))}))}))})),this.columns.rebuild()),this.renderHeader()}destroy(){this.dom.innerHTML=this.initialLayout,this.dom.classList.remove("dataTable-table"),this.wrapper.parentNode.replaceChild(this.dom,this.wrapper),this.initialized=!1,window.removeEventListener("resize",this.listeners.onResize)}update(){this.wrapper.classList.remove("dataTable-empty"),this.paginate(),this.renderPage(),this.links=[];let t=this.pages.length;for(;t--;){const e=t+1;this.links[t]=r(0===t?"active":"",e,e)}this.sorting=!1,this.renderPager(),this.rows.update(),this.emit("datatable.update")}paginate(){let t=this.activeRows;return this.searching&&(t=[],this.searchData.forEach((e=>t.push(this.activeRows[e])))),this.options.paging?this.pages=t.map(((e,s)=>s%this.options.perPage==0?t.slice(s,s+this.options.perPage):null)).filter((t=>t)):this.pages=[t],this.totalPages=this.lastPage=this.pages.length,this.totalPages}fixColumns(){if((this.options.scrollY.length||this.options.fixedColumns)&&this.activeHeadings&&this.activeHeadings.length){let t,e=!1;if(this.columnWidths=[],this.dom.tHead){this.options.scrollY.length&&(e=a("thead"),e.appendChild(a("tr")),e.style.height="0px",this.headerTable&&(this.dom.tHead=this.headerTable.tHead)),this.activeHeadings.forEach((t=>{t.style.width=""}));const t=this.activeHeadings.reduce(((t,e)=>t+e.offsetWidth),0);if(this.activeHeadings.forEach(((s,i)=>{const n=s.offsetWidth,r=n/t*100;if(s.style.width=`${r}%`,this.columnWidths[i]=n,this.options.scrollY.length){const t=a("th");e.firstElementChild.appendChild(t),t.style.width=`${r}%`,t.style.paddingTop="0",t.style.paddingBottom="0",t.style.border="0"}})),this.options.scrollY.length){const t=this.dom.parentElement;if(!this.headerTable){this.headerTable=a("table",{class:"dataTable-table"});const e=a("div",{class:"dataTable-headercontainer"});e.appendChild(this.headerTable),t.parentElement.insertBefore(e,t)}const s=this.dom.tHead;this.dom.replaceChild(e,s),this.headerTable.tHead=s,this.headerTable.parentElement.style.paddingRight=`${this.headerTable.clientWidth-this.dom.clientWidth+parseInt(this.headerTable.parentElement.style.paddingRight||"0",10)}px`,t.scrollHeight>t.clientHeight&&(t.style.overflowY="scroll")}}else{t=[],e=a("thead");const s=a("tr");Array.from(this.dom.tBodies[0].rows[0].cells).forEach((()=>{const e=a("th");s.appendChild(e),t.push(e)})),e.appendChild(s),this.dom.insertBefore(e,this.body);const i=[];t.forEach(((t,e)=>{const s=t.offsetWidth,a=s/this.rect.width*100;i.push(a),this.columnWidths[e]=s})),this.data.forEach((t=>{Array.from(t.cells).forEach(((t,e)=>{this.columns.visible(t.cellIndex)&&(t.style.width=`${i[e]}%`)}))})),this.dom.removeChild(e)}}}fixHeight(){this.options.fixedHeight&&(this.container.style.height=null,this.rect=this.container.getBoundingClientRect(),this.container.style.height=`${this.rect.height}px`)}search(t){return!!this.hasRows&&(t=t.toLowerCase(),this.currentPage=1,this.searching=!0,this.searchData=[],t.length?(this.clear(),this.data.forEach(((e,s)=>{const i=this.searchData.includes(e);t.split(" ").reduce(((t,s)=>{let i=!1,a=null,n=null;for(let t=0;tthis.pages.length||t<0)&&(this.renderPage(e),this.renderPager(),void this.emit("datatable.page",t)))}sortColumn(t,e){this.columns.sort(t,e)}insert(t){let e=[];if(i(t)){if(t.headings&&!this.hasHeadings&&!this.hasRows){const e=a("tr");t.headings.forEach((t=>{const s=a("th",{html:t});e.appendChild(s)})),this.head.appendChild(e),this.header=e,this.headings=[].slice.call(e.cells),this.hasHeadings=!0,this.options.sortable=this.initialSortable,this.renderHeader(),this.activeHeadings=this.headings.slice()}t.data&&Array.isArray(t.data)&&(e=t.data)}else Array.isArray(t)&&t.forEach((t=>{const s=[];Object.entries(t).forEach((([t,e])=>{const i=this.labels.indexOf(t);i>-1&&(s[i]=e)})),e.push(s)}));e.length&&(this.rows.add(e),this.hasRows=!0),this.update(),this.setColumns(),this.fixColumns()}refresh(){this.options.searchable&&(this.input.value="",this.searching=!1),this.currentPage=1,this.onFirstPage=!0,this.update(),this.emit("datatable.refresh")}clear(t){this.body&&n(this.body);let e=this.body;this.body||(e=this.dom),t&&("string"==typeof t&&(document.createDocumentFragment().innerHTML=t),e.appendChild(t))}export(t){if(!this.hasHeadings&&!this.hasRows)return!1;const e=this.activeHeadings;let s=[];const a=[];let n,r,o,h;if(!i(t))return!1;const l={download:!0,skipColumn:[],lineDelimiter:"\n",columnDelimiter:",",tableName:"myTable",replacer:null,space:4,...t};if(l.type){if("txt"!==l.type&&"csv"!==l.type||(s[0]=this.header),l.selection)if(isNaN(l.selection)){if(Array.isArray(l.selection))for(n=0;nt.trim().replace(/(^"|"$)/g,"")))),t.shift()),t.forEach(((t,i)=>{e.data[i]=[];const a=t.split(s.columnDelimiter);a.length&&a.forEach((t=>{s.removeDoubleQuotes&&(t=t.trim().replace(/(^"|"$)/g,"")),e.data[i].push(t)}))})))}else if("json"===s.type){const t=(t=>{let e=!1;try{e=JSON.parse(t)}catch(t){return!1}return!(null===e||!Array.isArray(e)&&!i(e))&&e})(s.data);t&&(e={headings:[],data:[]},t.forEach(((t,s)=>{e.data[s]=[],Object.entries(t).forEach((([t,i])=>{e.headings.includes(t)||e.headings.push(t),e.data[s].push(i)}))})))}i(s.data)&&(e=s.data),e&&this.insert(e)}return!1}print(){const t=this.activeHeadings,e=this.activeRows,s=a("table"),i=a("thead"),n=a("tbody"),r=a("tr");t.forEach((t=>{r.appendChild(a("th",{html:t.textContent}))})),i.appendChild(r),e.forEach((t=>{const e=a("tr");Array.from(t.cells).forEach((t=>{e.appendChild(a("td",{html:t.textContent}))})),n.appendChild(e)})),s.appendChild(i),s.appendChild(n);const o=window.open();o.document.body.appendChild(s),o.print()}setMessage(t){let e=1;this.hasRows?e=this.data[0].cells.length:this.activeHeadings.length&&(e=this.activeHeadings.length),this.wrapper.classList.add("dataTable-empty"),this.label&&(this.label.innerHTML=""),this.totalPages=0,this.renderPager(),this.clear(a("tr",{html:`${t} | `}))}on(t,e){this.events=this.events||{},this.events[t]=this.events[t]||[],this.events[t].push(e)}off(t,e){this.events=this.events||{},t in this.events!=0&&this.events[t].splice(this.events[t].indexOf(e),1)}emit(t){if(this.events=this.events||{},t in this.events!=0)for(let e=0;e function t(e,s,i){function a(r,o){if(!s[r]){if(!e[r]){const h=typeof require==="function"&&require;if(!o&&h)return h(r,!0);if(n)return n(r,!0);const l=new Error(`Cannot find module '${r}'`);throw l.code="MODULE_NOT_FOUND",l}const d=s[r]={exports:{}};e[r][0].call(d.exports,((t)=> a(e[r][1][t]||t)),d,d.exports,t,e,s,i)}return s[r].exports}for(var n=typeof require==="function"&&require,r=0;r=e?t:`${Array(e+1-i.length).join(s)}${t}`}; const b={s:m,z(t){const e=-t.utcOffset(); const s=Math.abs(e); const i=Math.floor(s/60); const a=s%60;return`${(e<=0?"+":"-")+m(i,2,"0")}:${m(a,2,"0")}`},m:function t(e,s){if(e.date()1)return t(r[0])}else{const o=e.name;y[o]=e,a=o}return!i&&a&&(v=a),a||!i&&v}; const x=function(t,e){if(w(t))return t.clone();const s=typeof e==="object"?e:{};return s.date=t,s.args=arguments,new T(s)}; const M=b;M.l=C,M.i=w,M.w=function(t,e){return x(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var T=function(){function g(t){this.$L=C(t.locale,null,!0),this.parse(t)}const m=g.prototype;return m.parse=function(t){this.$d=function(t){const e=t.date; const s=t.utc;if(e===null)return new Date(NaN);if(M.u(e))return new Date;if(e instanceof Date)return new Date(e);if(typeof e==="string"&&!/Z$/i.test(e)){const i=e.match(p);if(i){const a=i[2]-1||0; const n=(i[7]||"0").substring(0,3);return s?new Date(Date.UTC(i[1],a,i[3]||1,i[4]||0,i[5]||0,i[6]||0,n)):new Date(i[1],a,i[3]||1,i[4]||0,i[5]||0,i[6]||0,n)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},m.init=function(){const t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return M},m.isValid=function(){return!(this.$d.toString()===u)},m.isSame=function(t,e){const s=x(t);return this.startOf(e)<=s&&s<=this.endOf(e)},m.isAfter=function(t,e){return x(t) e||g[t]||a.replace(":","")))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(s,c,u){let p; const f=M.p(c); const g=x(s); const m=(g.utcOffset()-this.utcOffset())*t; const b=this-g; let v=M.m(this,g);return v=(p={},p[d]=v/12,p[h]=v,p[l]=v/3,p[o]=(b-m)/6048e5,p[r]=(b-m)/864e5,p[n]=b/e,p[a]=b/t,p[i]=b/1e3,p)[f]||b,u?v:M.a(v)},m.daysInMonth=function(){return this.endOf(h).$D},m.$locale=function(){return y[this.$L]},m.locale=function(t,e){if(!t)return this.$L;const s=this.clone(); const i=C(t,e,!0);return i&&(s.$L=i),s},m.clone=function(){return M.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},g}(); const $=T.prototype;return x.prototype=$,[["$ms",s],["$s",i],["$m",a],["$H",n],["$W",r],["$M",h],["$y",d],["$D",c]].forEach(((t)=> {$[t[1]]=function(e){return this.$g(e,t[0],t[1])}})),x.extend=function(t,e){return t.$i||(t(e,T,x),t.$i=!0),x},x.locale=C,x.isDayjs=w,x.unix=function(t){return x(1e3*t)},x.en=y[v],x.Ls=y,x.p={},x}(); const i={exports:{}}.exports=function(){const t={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"}; const e=/(\[[^[]*\])|([-_:/.,()\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g; const s=/\d\d/; const i=/\d\d?/; const a=/\d*[^-_:/,()\s\d]+/; let n={}; let r=function(t){return(t=+t)+(t>68?1900:2e3)}; const o=function(t){return function(e){this[t]=+e}}; const h=[/[+-]\d\d:?(\d\d)?|Z/,function(t){(this.zone||(this.zone={})).offset=function(t){if(!t)return 0;if(t==="Z")return 0;const e=t.match(/([+-]|\d\d)/g); const s=60*e[1]+(+e[2]||0);return s===0?0:e[0]==="+"?-s:s}(t)}]; const l=function(t){const e=n[t];return e&&(e.indexOf?e:e.s.concat(e.f))}; const d=function(t,e){let s; const i=n.meridiem;if(i){for(let a=1;a<=24;a+=1)if(t.indexOf(i(a,0,e))>-1){s=a>12;break}}else s=t===(e?"pm":"PM");return s}; const c={A:[a,function(t){this.afternoon=d(t,!1)}],a:[a,function(t){this.afternoon=d(t,!0)}],S:[/\d/,function(t){this.milliseconds=100*+t}],SS:[s,function(t){this.milliseconds=10*+t}],SSS:[/\d{3}/,function(t){this.milliseconds=+t}],s:[i,o("seconds")],ss:[i,o("seconds")],m:[i,o("minutes")],mm:[i,o("minutes")],H:[i,o("hours")],h:[i,o("hours")],HH:[i,o("hours")],hh:[i,o("hours")],D:[i,o("day")],DD:[s,o("day")],Do:[a,function(t){const e=n.ordinal; const s=t.match(/\d+/);if(this.day=s[0],e)for(let i=1;i<=31;i+=1)e(i).replace(/\[|\]/g,"")===t&&(this.day=i)}],M:[i,o("month")],MM:[s,o("month")],MMM:[a,function(t){const e=l("months"); const s=(l("monthsShort")||e.map(((t)=> t.slice(0,3)))).indexOf(t)+1;if(s<1)throw new Error;this.month=s%12||s}],MMMM:[a,function(t){const e=l("months").indexOf(t)+1;if(e<1)throw new Error;this.month=e%12||e}],Y:[/[+-]?\d+/,o("year")],YY:[s,function(t){this.year=r(t)}],YYYY:[/\d{4}/,o("year")],Z:h,ZZ:h};function u(s){let i; let a;i=s,a=n&&n.formats;for(var r=(s=i.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,((e,s,i)=> {const n=i&&i.toUpperCase();return s||a[i]||t[i]||a[n].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,((t,e,s)=> e||s.slice(1)))}))).match(e),o=r.length,h=0;h-1)return new Date((e==="X"?1e3:1)*t);const i=u(e)(t); const a=i.year; const n=i.month; const r=i.day; const o=i.hours; const h=i.minutes; const l=i.seconds; const d=i.milliseconds; const c=i.zone; const p=new Date; const f=r||(a||n?1:p.getDate()); const g=a||p.getFullYear(); let m=0;a&&!n||(m=n>0?n-1:p.getMonth());const b=o||0; const v=h||0; const y=l||0; const w=d||0;return c?new Date(Date.UTC(g,m,f,b,v,y,w+60*c.offset*1e3)):s?new Date(Date.UTC(g,m,f,b,v,y,w)):new Date(g,m,f,b,v,y,w)}catch(t){return new Date("")}}(e,o,i),this.init(),c&&!0!==c&&(this.$L=this.locale(c).$L),d&&e!=this.format(o)&&(this.$d=new Date("")),n={}}else if(o instanceof Array)for(let p=o.length,f=1;f<=p;f+=1){r[1]=o[f-1];const g=s.apply(this,r);if(g.isValid()){this.$d=g.$d,this.$L=g.$L,this.init();break}f===p&&(this.$d=new Date(""))}else a.call(this,t)}}}();e.extend(i),s.parseDate=(t,s)=>{let i=!1;if(s)switch(s){case"ISO_8601":i=t;break;case"RFC_2822":i=e(t.slice(5),"DD MMM YYYY HH:mm:ss ZZ").unix();break;case"MYSQL":i=e(t,"YYYY-MM-DD hh:mm:ss").unix();break;case"UNIX":i=e(t).unix();break;default:i=e(t,s,!0).valueOf()}return i}}).call(this)}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],2:[function(t,e,s){"use strict";
+
+Object.defineProperty(s,"__esModule",{value:!0});const i=t=>Object.prototype.toString.call(t)==="[object Object]"; const a=(t,e)=>{const s=document.createElement(t);if(e&&typeof e==="object")for(const t in e)t==="html"?s.innerHTML=e[t]:s.setAttribute(t,e[t]);return s}; const n=t=>{t instanceof NodeList?t.forEach((t=>n(t))):t.innerHTML=""}; const r=(t,e,s)=>a("li",{class:t,html:`${s}`}); const o=(t,e)=>{let s; let i;e===1?(s=0,i=t.length):e===-1&&(s=t.length-1,i=-1);for(let a=!0;a;){a=!1;for(let n=s;n!=i;n+=e)if(t[n+e]&&t[n].value>t[n+e].value){const s=t[n]; const i=t[n+e]; const r=s;t[n]=i,t[n+e]=r,a=!0}}return t};class h{constructor(t){this.dt=t,this.cursor=!1}
+
+build(t){const e=a("tr");let s=this.dt.headings;return s.length||(s=t.map((()=>""))),s.forEach(((s,i)=>{const n=a("td");t[i]&&t[i].length||(t[i]=""),n.innerHTML=t[i],n.data=t[i],e.appendChild(n)})),e}
+
+setCursor(t=!1){this.cursor&&this.cursor.classList.remove("dataTable-cursor"),t&&(t.classList.add("dataTable-cursor"),this.cursor=t)}
+
+render(t){return t}
+
+add(t){if(Array.isArray(t)){const e=this.dt;Array.isArray(t[0])?t.forEach((t=>{e.data.push(this.build(t))})):e.data.push(this.build(t)),e.data.length&&(e.hasRows=!0),this.update(),e.columns.rebuild()}}
+
+remove(t){const e=this.dt;Array.isArray(t)?(t.sort(((t,e)=>e-t)),t.forEach((t=>{e.data.splice(t,1)}))):t=="all"?e.data=[]:e.data.splice(t,1),e.data.length||(e.hasRows=!1),this.update(),e.columns.rebuild()}
+
+update(){this.dt.data.forEach(((t,e)=>{t.dataIndex=e}))}
+
+findRowIndex(t,e){return this.dt.data.findIndex((s=>s.children[t].innerText.toLowerCase().includes(String(e).toLowerCase())))}
+
+findRow(t,e){const s=this.findRowIndex(t,e);if(s<0)return{index:-1,row:null,cols:[]};const i=this.dt.data[s];return{index:s,row:i,cols:[...i.cells].map((t=>t.innerHTML))}}
+
+updateRow(t,e){const s=this.build(e);this.dt.data.splice(t,1,s),this.update(),this.dt.columns.rebuild()}}class l{constructor(t){this.dt=t}
+
+swap(t){if(t.length&&t.length===2){const e=[];this.dt.headings.forEach(((t,s)=>{e.push(s)}));const s=t[0]; const i=t[1]; const a=e[i];e[i]=e[s],e[s]=a,this.order(e)}}
+
+order(t){let e; let s; let i; let a; let n; let r; let o;const h=[[],[],[],[]]; const l=this.dt;t.forEach(((t,i)=>{n=l.headings[t],r=n.getAttribute("data-sortable")!=="false",e=n.cloneNode(!0),e.originalCellIndex=i,e.sortable=r,h[0].push(e),l.hiddenColumns.includes(t)||(s=n.cloneNode(!0),s.originalCellIndex=i,s.sortable=r,h[1].push(s))})),l.data.forEach(((e,s)=>{i=e.cloneNode(!1),a=e.cloneNode(!1),i.dataIndex=a.dataIndex=s,e.searchIndex!==null&&void 0!==e.searchIndex&&(i.searchIndex=a.searchIndex=e.searchIndex),t.forEach((t=>{o=e.cells[t].cloneNode(!0),o.data=e.cells[t].data,i.appendChild(o),l.hiddenColumns.includes(t)||(o=e.cells[t].cloneNode(!0),o.data=e.cells[t].data,a.appendChild(o))})),h[2].push(i),h[3].push(a)})),l.headings=h[0],l.activeHeadings=h[1],l.data=h[2],l.activeRows=h[3],l.update()}
+
+hide(t){if(t.length){const e=this.dt;t.forEach((t=>{e.hiddenColumns.includes(t)||e.hiddenColumns.push(t)})),this.rebuild()}}
+
+show(t){if(t.length){let e;const s=this.dt;t.forEach((t=>{e=s.hiddenColumns.indexOf(t),e>-1&&s.hiddenColumns.splice(e,1)})),this.rebuild()}}
+
+visible(t){let e;const s=this.dt;return t=t||s.headings.map((t=>t.originalCellIndex)),isNaN(t)?Array.isArray(t)&&(e=[],t.forEach((t=>{e.push(!s.hiddenColumns.includes(t))}))):e=!s.hiddenColumns.includes(t),e}
+
+add(t){let e;const s=document.createElement("th");if(!this.dt.headings.length)return this.dt.insert({headings:[t.heading],data:t.data.map((t=>[t]))}),void this.rebuild();this.dt.hiddenHeader?s.innerHTML="":t.heading.nodeName?s.appendChild(t.heading):s.innerHTML=t.heading,this.dt.headings.push(s),this.dt.data.forEach(((s,i)=>{t.data[i]&&(e=document.createElement("td"),t.data[i].nodeName?e.appendChild(t.data[i]):e.innerHTML=t.data[i],e.data=e.innerHTML,t.render&&(e.innerHTML=t.render.call(this,e.data,e,s)),s.appendChild(e))})),t.type&&s.setAttribute("data-type",t.type),t.format&&s.setAttribute("data-format",t.format),t.hasOwnProperty("sortable")&&(s.sortable=t.sortable,s.setAttribute("data-sortable",!0===t.sortable?"true":"false")),this.rebuild(),this.dt.renderHeader()}
+
+remove(t){Array.isArray(t)?(t.sort(((t,e)=>e-t)),t.forEach((t=>this.remove(t)))):(this.dt.headings.splice(t,1),this.dt.data.forEach((e=>{e.removeChild(e.cells[t])}))),this.rebuild()}
+
+filter(t,e,s,i){const a=this.dt;if(a.filterState||(a.filterState={originalData:a.data}),!a.filterState[t]){const e=[...i,()=>!0];a.filterState[t]=function(){let t=0;return()=>e[t++%e.length]}()}const n=a.filterState[t](); const r=Array.from(a.filterState.originalData).filter((e=>{const s=e.cells[t]; const i=s.hasAttribute("data-content")?s.getAttribute("data-content"):s.innerText;return typeof n==="function"?n(i):i===n}));a.data=r,a.data.length?(this.rebuild(),a.update()):(a.clear(),a.hasRows=!1,a.setMessage(a.options.labels.noRows)),s||a.emit("datatable.sort",t,e)}
+
+sort(e,s,i){const a=this.dt;if(a.hasHeadings&&(e<0||e>a.headings.length))return!1;const n=a.options.filters&&a.options.filters[a.headings[e].textContent];if(n&&n.length!==0)return void this.filter(e,s,i,n);a.sorting=!0,i||a.emit("datatable.sorting",e,s);let r=a.data;const h=[]; const l=[];let d=0; let c=0;const u=a.headings[e]; const p=[];if(u.getAttribute("data-type")==="date"){let e=!1;u.hasAttribute("data-format")&&(e=u.getAttribute("data-format")),p.push(Promise.resolve().then((()=> t("./date-7061ceee.js"))).then((({parseDate:t})=>s=>t(s,e))))}Promise.all(p).then((t=>{const n=t[0];let p; let f;Array.from(r).forEach((t=>{const s=t.cells[e]; const i=s.hasAttribute("data-content")?s.getAttribute("data-content"):s.innerText;let a;a=n?n(i):typeof i==="string"?i.replace(/(\$|,|\s|%)/g,""):i,parseFloat(a)==a?l[c++]={value:Number(a),row:t}:h[d++]={value:typeof i==="string"?i.toLowerCase():i,row:t}})),s||(s=u.classList.contains("asc")?"desc":"asc"),s=="desc"?(p=o(h,-1),f=o(l,-1),u.classList.remove("asc"),u.classList.add("desc"),u.setAttribute("aria-sort","descending")):(p=o(l,1),f=o(h,1),u.classList.remove("desc"),u.classList.add("asc"),u.setAttribute("aria-sort","ascending")),a.lastTh&&u!=a.lastTh&&(a.lastTh.classList.remove("desc"),a.lastTh.classList.remove("asc"),a.lastTh.removeAttribute("aria-sort")),a.lastTh=u,r=p.concat(f),a.data=[];const g=[];r.forEach(((t,e)=>{a.data.push(t.row),t.row.searchIndex!==null&&void 0!==t.row.searchIndex&&g.push(e)})),a.searchData=g,this.rebuild(),a.update(),i||a.emit("datatable.sort",e,s)}))}
+
+rebuild(){let t; let e; let s; let i;const a=this.dt; const n=[];a.activeRows=[],a.activeHeadings=[],a.headings.forEach(((t,e)=>{t.originalCellIndex=e,t.sortable=t.getAttribute("data-sortable")!=="false",a.hiddenColumns.includes(e)||a.activeHeadings.push(t)})),a.data.forEach(((r,o)=>{t=r.cloneNode(!1),e=r.cloneNode(!1),t.dataIndex=e.dataIndex=o,r.searchIndex!==null&&void 0!==r.searchIndex&&(t.searchIndex=e.searchIndex=r.searchIndex),Array.from(r.cells).forEach((n=>{s=n.cloneNode(!0),s.data=n.data,t.appendChild(s),a.hiddenColumns.includes(s.cellIndex)||(i=s.cloneNode(!0),i.data=s.data,e.appendChild(i))})),n.push(t),a.activeRows.push(e)})),a.data=n,a.update()}}const d=function(t){let e=!1; let s=!1;if((t=t||this.options.data).headings){e=a("thead");const s=a("tr");t.headings.forEach((t=>{const e=a("th",{html:t});s.appendChild(e)})),e.appendChild(s)}t.data&&t.data.length&&(s=a("tbody"),t.data.forEach((e=>{if(t.headings&&t.headings.length!==e.length)throw new Error("The number of rows do not match the number of headings.");const i=a("tr");e.forEach((t=>{const e=a("td",{html:t});i.appendChild(e)})),s.appendChild(i)}))),e&&(this.dom.tHead!==null&&this.dom.removeChild(this.dom.tHead),this.dom.appendChild(e)),s&&(this.dom.tBodies.length&&this.dom.removeChild(this.dom.tBodies[0]),this.dom.appendChild(s))}; const c={sortable:!0,searchable:!0,paging:!0,perPage:10,perPageSelect:[5,10,15,20,25],nextPrev:!0,firstLast:!1,prevText:"‹",nextText:"›",firstText:"«",lastText:"»",ellipsisText:"…",ascText:"▴",descText:"▾",truncatePager:!0,pagerDelta:2,scrollY:"",fixedColumns:!0,fixedHeight:!1,header:!0,hiddenHeader:!1,footer:!1,tabIndex:!1,rowNavigation:!1,labels:{placeholder:"Search on page...",perPage:"{select} entries per page",noRows:"No entries found",noResults:"No results match your search query",info:"Showing {start} to {end} of {rows} entries"},layout:{top:"{select}{search}",bottom:"{info}{pager}"}};s.DataTable=class{constructor(t,e={}){const s=typeof t==="string"?document.querySelector(t):t;if(this.options={...c,...e,layout:{...c.layout,...e.layout},labels:{...c.labels,...e.labels}},this.rows=new h(this),this.columns=new l(this),this.initialized=!1,this.initialLayout=s.innerHTML,this.initialSortable=this.options.sortable,this.options.tabIndex?s.tabIndex=this.options.tabIndex:this.options.rowNavigation&&s.tabIndex===-1&&(s.tabIndex=0),this.options.header||(this.options.sortable=!1),s.tHead===null&&(!this.options.data||this.options.data&&!this.options.data.headings)&&(this.options.sortable=!1),s.tBodies.length&&!s.tBodies[0].rows.length&&this.options.data&&!this.options.data.data)throw new Error("You seem to be using the data option, but you've not defined any rows.");this.dom=s,this.table=this.dom,this.listeners={onResize:t=>this.onResize(t)},this.init()}
+
+init(t){if(this.initialized||this.dom.classList.contains("dataTable-table"))return!1;Object.assign(this.options,t||{}),this.currentPage=1,this.onFirstPage=!0,this.hiddenColumns=[],this.columnRenderers=[],this.selectedColumns=[],this.render(),setTimeout((()=>{this.emit("datatable.init"),this.initialized=!0,this.options.plugins&&Object.entries(this.options.plugins).forEach((([t,e])=>{this[t]&&typeof this[t]==="function"&&(this[t]=this[t](e,{createElement:a}),e.enabled&&this[t].init&&typeof this[t].init==="function"&&this[t].init())}))}),10)}
+
+render(){let t="";if(this.options.data&&d.call(this),this.body=this.dom.tBodies[0],this.head=this.dom.tHead,this.foot=this.dom.tFoot,this.body||(this.body=a("tbody"),this.dom.appendChild(this.body)),this.hasRows=this.body.rows.length>0,!this.head){const t=a("thead"); const e=a("tr");this.hasRows&&(Array.from(this.body.rows[0].cells).forEach((()=>{e.appendChild(a("th"))})),t.appendChild(e)),this.head=t,this.dom.insertBefore(this.head,this.body),this.hiddenHeader=this.options.hiddenHeader}if(this.headings=[],this.hasHeadings=this.head.rows.length>0,this.hasHeadings&&(this.header=this.head.rows[0],this.headings=[].slice.call(this.header.cells)),this.options.header||this.head&&this.dom.removeChild(this.dom.tHead),this.options.footer?this.head&&!this.foot&&(this.foot=a("tfoot",{html:this.head.innerHTML}),this.dom.appendChild(this.foot)):this.foot&&this.dom.removeChild(this.dom.tFoot),this.wrapper=a("div",{class:"dataTable-wrapper dataTable-loading"}),t+="",t+=this.options.layout.top,t+="
",this.options.scrollY.length?t+=``:t+="",t+="",t+=this.options.layout.bottom,t+="
",t=t.replace("{info}",this.options.paging?"":""),this.options.paging&&this.options.perPageSelect){let e="";const s=a("select",{class:"dataTable-selector"});this.options.perPageSelect.forEach((t=>{const e=t===this.options.perPage; const i=new Option(t,t,e,e);s.add(i)})),e=e.replace("{select}",s.outerHTML),t=t.replace("{select}",e)}else t=t.replace("{select}","");if(this.options.searchable){const e=``;t=t.replace("{search}",e)}else t=t.replace("{search}","");this.hasHeadings&&this.renderHeader(),this.dom.classList.add("dataTable-table");const e=a("nav",{class:"dataTable-pagination"}); const s=a("ul",{class:"dataTable-pagination-list"});e.appendChild(s),t=t.replace(/\{pager\}/g,e.outerHTML),this.wrapper.innerHTML=t,this.container=this.wrapper.querySelector(".dataTable-container"),this.pagers=this.wrapper.querySelectorAll(".dataTable-pagination-list"),this.label=this.wrapper.querySelector(".dataTable-info"),this.dom.parentNode.replaceChild(this.wrapper,this.dom),this.container.appendChild(this.dom),this.rect=this.dom.getBoundingClientRect(),this.data=Array.from(this.body.rows),this.activeRows=this.data.slice(),this.activeHeadings=this.headings.slice(),this.update(),this.setColumns(),this.fixHeight(),this.fixColumns(),this.options.header||this.wrapper.classList.add("no-header"),this.options.footer||this.wrapper.classList.add("no-footer"),this.options.sortable&&this.wrapper.classList.add("sortable"),this.options.searchable&&this.wrapper.classList.add("searchable"),this.options.fixedHeight&&this.wrapper.classList.add("fixed-height"),this.options.fixedColumns&&this.wrapper.classList.add("fixed-columns"),this.bindEvents()}
+
+renderPage(t=!1){if(this.hasHeadings&&(n(this.header),this.activeHeadings.forEach((t=>this.header.appendChild(t)))),this.hasRows&&this.totalPages){this.currentPage>this.totalPages&&(this.currentPage=1);const t=this.currentPage-1; const e=document.createDocumentFragment();this.pages[t].forEach((t=>e.appendChild(this.rows.render(t)))),this.clear(e),this.onFirstPage=this.currentPage===1,this.onLastPage=this.currentPage===this.lastPage}else this.setMessage(this.options.labels.noRows);let e; let s=0; let i=0; let a=0;if(this.totalPages&&(s=this.currentPage-1,i=s*this.options.perPage,a=i+this.pages[s].length,i+=1,e=this.searching?this.searchData.length:this.data.length),this.label&&this.options.labels.info.length){const t=this.options.labels.info.replace("{start}",i).replace("{end}",a).replace("{page}",this.currentPage).replace("{pages}",this.totalPages).replace("{rows}",e);this.label.innerHTML=e?t:""}if(this.currentPage==1&&this.fixHeight(),this.options.rowNavigation&&(!this.rows.cursor||!this.pages[this.currentPage-1].includes(this.rows.cursor))){const e=this.pages[this.currentPage-1];t?this.rows.setCursor(e[e.length-1]):this.rows.setCursor(e[0])}}
+
+renderPager(){if(n(this.pagers),this.totalPages>1){const t="pager"; const e=document.createDocumentFragment(); const s=this.onFirstPage?1:this.currentPage-1; const i=this.onLastPage?this.totalPages:this.currentPage+1;this.options.firstLast&&e.appendChild(r(t,1,this.options.firstText)),this.options.nextPrev&&!this.onFirstPage&&e.appendChild(r(t,s,this.options.prevText));let n=this.links;this.options.truncatePager&&(n=((t,e,s,i,n)=>{let r;const o=2*(i=i||2);let h=e-i; let l=e+i;const d=[]; const c=[];e<4-i+o?l=3+o:e>s-(3-i+o)&&(h=s-(2+o));for(let e=1;e<=s;e++)if(e==1||e==s||e>=h&&e<=l){const s=t[e-1];s.classList.remove("active"),d.push(s)}return d.forEach((e=>{const s=e.children[0].getAttribute("data-page");if(r){const e=r.children[0].getAttribute("data-page");if(s-e==2)c.push(t[e]);else if(s-e!=1){const t=a("li",{class:"ellipsis",html:`${n}`});c.push(t)}}c.push(e),r=e})),c})(this.links,this.currentPage,this.pages.length,this.options.pagerDelta,this.options.ellipsisText)),this.links[this.currentPage-1].classList.add("active"),n.forEach((t=>{t.classList.remove("active"),e.appendChild(t)})),this.links[this.currentPage-1].classList.add("active"),this.options.nextPrev&&!this.onLastPage&&e.appendChild(r(t,i,this.options.nextText)),this.options.firstLast&&e.appendChild(r(t,this.totalPages,this.options.lastText)),this.pagers.forEach((t=>{t.appendChild(e.cloneNode(!0))}))}}
+
+renderHeader(){this.labels=[],this.headings&&this.headings.length&&this.headings.forEach(((t,e)=>{if(this.labels[e]=t.textContent,t.firstElementChild&&t.firstElementChild.classList.contains("dataTable-sorter")&&(t.innerHTML=t.firstElementChild.innerHTML),t.sortable=t.getAttribute("data-sortable")!=="false",t.originalCellIndex=e,this.options.sortable&&t.sortable){const e=a("a",{href:"#",class:"dataTable-sorter",html:t.innerHTML});t.innerHTML="",t.setAttribute("data-sortable",""),t.appendChild(e)}})),this.fixColumns()}
+
+bindEvents(){if(this.options.perPageSelect){const t=this.wrapper.querySelector(".dataTable-selector");t&&t.addEventListener("change",(()=>{this.options.perPage=parseInt(t.value,10),this.update(),this.fixHeight(),this.emit("datatable.perpage",this.options.perPage)}),!1)}this.options.searchable&&(this.input=this.wrapper.querySelector(".dataTable-input"),this.input&&this.input.addEventListener("keyup",(()=>this.search(this.input.value)),!1)),this.wrapper.addEventListener("click",(t=>{const e=t.target.closest("a");e&&e.nodeName.toLowerCase()==="a"&&(e.hasAttribute("data-page")?(this.page(e.getAttribute("data-page")),t.preventDefault()):this.options.sortable&&e.classList.contains("dataTable-sorter")&&e.parentNode.getAttribute("data-sortable")!="false"&&(this.columns.sort(this.headings.indexOf(e.parentNode)),t.preventDefault()))}),!1),this.options.rowNavigation?(this.table.addEventListener("keydown",(t=>{t.keyCode===38?this.rows.cursor.previousElementSibling?(this.rows.setCursor(this.rows.cursor.previousElementSibling),t.preventDefault(),t.stopPropagation()):this.onFirstPage||this.page(this.currentPage-1,!0):t.keyCode===40?this.rows.cursor.nextElementSibling?(this.rows.setCursor(this.rows.cursor.nextElementSibling),t.preventDefault(),t.stopPropagation()):this.onLastPage||this.page(this.currentPage+1):[13,32].includes(t.keyCode)&&this.emit("datatable.selectrow",this.rows.cursor,t)})),this.body.addEventListener("mousedown",(t=>{if(this.table.matches(":focus")){const e=Array.from(this.body.rows).find((e=>e.contains(t.target)));this.emit("datatable.selectrow",e,t)}}))):this.body.addEventListener("mousedown",(t=>{const e=Array.from(this.body.rows).find((e=>e.contains(t.target)));this.emit("datatable.selectrow",{event:t,row:e})})),window.addEventListener("resize",this.listeners.onResize)}
+
+onResize(){this.rect=this.container.getBoundingClientRect(),this.rect.width&&this.fixColumns()}
+
+setColumns(t){t||this.data.forEach((t=>{Array.from(t.cells).forEach((t=>{t.data=t.innerHTML}))})),this.options.columns&&this.headings.length&&this.options.columns.forEach((t=>{Array.isArray(t.select)||(t.select=[t.select]),t.hasOwnProperty("render")&&typeof t.render==="function"&&(this.selectedColumns=this.selectedColumns.concat(t.select),this.columnRenderers.push({columns:t.select,renderer:t.render})),t.select.forEach((e=>{const s=this.headings[e];s&&(t.type&&s.setAttribute("data-type",t.type),t.format&&s.setAttribute("data-format",t.format),t.hasOwnProperty("sortable")&&s.setAttribute("data-sortable",t.sortable),t.hasOwnProperty("hidden")&&!1!==t.hidden&&this.columns.hide([e]),t.hasOwnProperty("sort")&&t.select.length===1&&this.columns.sort(t.select[0],t.sort,!0))}))})),this.hasRows&&(this.data.forEach(((t,e)=>{t.dataIndex=e,Array.from(t.cells).forEach((t=>{t.data=t.innerHTML}))})),this.selectedColumns.length&&this.data.forEach((t=>{Array.from(t.cells).forEach(((e,s)=>{this.selectedColumns.includes(s)&&this.columnRenderers.forEach((i=>{i.columns.includes(s)&&(e.innerHTML=i.renderer.call(this,e.data,e,t))}))}))})),this.columns.rebuild()),this.renderHeader()}
+
+destroy(){this.dom.innerHTML=this.initialLayout,this.dom.classList.remove("dataTable-table"),this.wrapper.parentNode.replaceChild(this.dom,this.wrapper),this.initialized=!1,window.removeEventListener("resize",this.listeners.onResize)}
+
+update(){this.wrapper.classList.remove("dataTable-empty"),this.paginate(),this.renderPage(),this.links=[];let t=this.pages.length;for(;t--;){const e=t+1;this.links[t]=r(t===0?"active":"",e,e)}this.sorting=!1,this.renderPager(),this.rows.update(),this.emit("datatable.update")}
+
+paginate(){let t=this.activeRows;return this.searching&&(t=[],this.searchData.forEach((e=>t.push(this.activeRows[e])))),this.options.paging?this.pages=t.map(((e,s)=>s%this.options.perPage==0?t.slice(s,s+this.options.perPage):null)).filter((t=>t)):this.pages=[t],this.totalPages=this.lastPage=this.pages.length,this.totalPages}
+
+fixColumns(){if((this.options.scrollY.length||this.options.fixedColumns)&&this.activeHeadings&&this.activeHeadings.length){let t; let e=!1;if(this.columnWidths=[],this.dom.tHead){this.options.scrollY.length&&(e=a("thead"),e.appendChild(a("tr")),e.style.height="0px",this.headerTable&&(this.dom.tHead=this.headerTable.tHead)),this.activeHeadings.forEach((t=>{t.style.width=""}));const t=this.activeHeadings.reduce(((t,e)=>t+e.offsetWidth),0);if(this.activeHeadings.forEach(((s,i)=>{const n=s.offsetWidth; const r=n/t*100;if(s.style.width=`${r}%`,this.columnWidths[i]=n,this.options.scrollY.length){const t=a("th");e.firstElementChild.appendChild(t),t.style.width=`${r}%`,t.style.paddingTop="0",t.style.paddingBottom="0",t.style.border="0"}})),this.options.scrollY.length){const t=this.dom.parentElement;if(!this.headerTable){this.headerTable=a("table",{class:"dataTable-table"});const e=a("div",{class:"dataTable-headercontainer"});e.appendChild(this.headerTable),t.parentElement.insertBefore(e,t)}const s=this.dom.tHead;this.dom.replaceChild(e,s),this.headerTable.tHead=s,this.headerTable.parentElement.style.paddingRight=`${this.headerTable.clientWidth-this.dom.clientWidth+parseInt(this.headerTable.parentElement.style.paddingRight||"0",10)}px`,t.scrollHeight>t.clientHeight&&(t.style.overflowY="scroll")}}else{t=[],e=a("thead");const s=a("tr");Array.from(this.dom.tBodies[0].rows[0].cells).forEach((()=>{const e=a("th");s.appendChild(e),t.push(e)})),e.appendChild(s),this.dom.insertBefore(e,this.body);const i=[];t.forEach(((t,e)=>{const s=t.offsetWidth; const a=s/this.rect.width*100;i.push(a),this.columnWidths[e]=s})),this.data.forEach((t=>{Array.from(t.cells).forEach(((t,e)=>{this.columns.visible(t.cellIndex)&&(t.style.width=`${i[e]}%`)}))})),this.dom.removeChild(e)}}}
+
+fixHeight(){this.options.fixedHeight&&(this.container.style.height=null,this.rect=this.container.getBoundingClientRect(),this.container.style.height=`${this.rect.height}px`)}
+
+search(t){return!!this.hasRows&&(t=t.toLowerCase(),this.currentPage=1,this.searching=!0,this.searchData=[],t.length?(this.clear(),this.data.forEach(((e,s)=>{const i=this.searchData.includes(e);t.split(" ").reduce(((t,s)=>{let i=!1; let a=null; let n=null;for(let t=0;tthis.pages.length||t<0)&&(this.renderPage(e),this.renderPager(),void this.emit("datatable.page",t)))}
+
+sortColumn(t,e){this.columns.sort(t,e)}
+
+insert(t){let e=[];if(i(t)){if(t.headings&&!this.hasHeadings&&!this.hasRows){const e=a("tr");t.headings.forEach((t=>{const s=a("th",{html:t});e.appendChild(s)})),this.head.appendChild(e),this.header=e,this.headings=[].slice.call(e.cells),this.hasHeadings=!0,this.options.sortable=this.initialSortable,this.renderHeader(),this.activeHeadings=this.headings.slice()}t.data&&Array.isArray(t.data)&&(e=t.data)}else Array.isArray(t)&&t.forEach((t=>{const s=[];Object.entries(t).forEach((([t,e])=>{const i=this.labels.indexOf(t);i>-1&&(s[i]=e)})),e.push(s)}));e.length&&(this.rows.add(e),this.hasRows=!0),this.update(),this.setColumns(),this.fixColumns()}
+
+refresh(){this.options.searchable&&(this.input.value="",this.searching=!1),this.currentPage=1,this.onFirstPage=!0,this.update(),this.emit("datatable.refresh")}
+
+clear(t){this.body&&n(this.body);let e=this.body;this.body||(e=this.dom),t&&(typeof t==="string"&&(document.createDocumentFragment().innerHTML=t),e.appendChild(t))}
+
+export(t){if(!this.hasHeadings&&!this.hasRows)return!1;const e=this.activeHeadings;let s=[];const a=[];let n; let r; let o; let h;if(!i(t))return!1;const l={download:!0,skipColumn:[],lineDelimiter:"\n",columnDelimiter:",",tableName:"myTable",replacer:null,space:4,...t};if(l.type){if(l.type!=="txt"&&l.type!=="csv"||(s[0]=this.header),l.selection)if(isNaN(l.selection)){if(Array.isArray(l.selection))for(n=0;nt.trim().replace(/(^"|"$)/g,"")))),t.shift()),t.forEach(((t,i)=>{e.data[i]=[];const a=t.split(s.columnDelimiter);a.length&&a.forEach((t=>{s.removeDoubleQuotes&&(t=t.trim().replace(/(^"|"$)/g,"")),e.data[i].push(t)}))})))}else if(s.type==="json"){const t=(t=>{let e=!1;try{e=JSON.parse(t)}catch(t){return!1}return!(e===null||!Array.isArray(e)&&!i(e))&&e})(s.data);t&&(e={headings:[],data:[]},t.forEach(((t,s)=>{e.data[s]=[],Object.entries(t).forEach((([t,i])=>{e.headings.includes(t)||e.headings.push(t),e.data[s].push(i)}))})))}i(s.data)&&(e=s.data),e&&this.insert(e)}return!1}
+
+print(){const t=this.activeHeadings; const e=this.activeRows; const s=a("table"); const i=a("thead"); const n=a("tbody"); const r=a("tr");t.forEach((t=>{r.appendChild(a("th",{html:t.textContent}))})),i.appendChild(r),e.forEach((t=>{const e=a("tr");Array.from(t.cells).forEach((t=>{e.appendChild(a("td",{html:t.textContent}))})),n.appendChild(e)})),s.appendChild(i),s.appendChild(n);const o=window.open();o.document.body.appendChild(s),o.print()}
+
+setMessage(t){let e=1;this.hasRows?e=this.data[0].cells.length:this.activeHeadings.length&&(e=this.activeHeadings.length),this.wrapper.classList.add("dataTable-empty"),this.label&&(this.label.innerHTML=""),this.totalPages=0,this.renderPager(),this.clear(a("tr",{html:`${t} | `}))}
+
+on(t,e){this.events=this.events||{},this.events[t]=this.events[t]||[],this.events[t].push(e)}
+
+off(t,e){this.events=this.events||{},t in this.events!=0&&this.events[t].splice(this.events[t].indexOf(e),1)}
+
+emit(t){if(this.events=this.events||{},t in this.events!=0)for(let e=0;e
Date: Mon, 28 Nov 2022 15:10:12 +0100
Subject: [PATCH 29/49] fix
---
ereuse_devicehub/templates/ereuse_devicehub/base_site.html | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
index e8fc6b49..b65955f0 100644
--- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
+++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
@@ -11,6 +11,8 @@
From b39388bef00eb5705f4b24bd7d448a49422e7ad4 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 15:24:31 +0100
Subject: [PATCH 30/49] fix
---
ereuse_devicehub/static/js/main.js | 2 +-
ereuse_devicehub/templates/ereuse_devicehub/base_site.html | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/ereuse_devicehub/static/js/main.js b/ereuse_devicehub/static/js/main.js
index 474658d5..7bea4a96 100644
--- a/ereuse_devicehub/static/js/main.js
+++ b/ereuse_devicehub/static/js/main.js
@@ -48,12 +48,12 @@
/**
* Search bar toggle
- */
if (select(".search-bar-toggle")) {
on("click", ".search-bar-toggle", (e) => {
select(".search-bar").classList.toggle("search-bar-show")
})
}
+ */
/**
* Navbar links active state on scroll
diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
index b65955f0..e8fc6b49 100644
--- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
+++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
@@ -11,8 +11,6 @@
From 79fbe323a2926a0e6bcbe7432617cebeb462cfec Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 16:39:43 +0100
Subject: [PATCH 31/49] try fix
---
.../templates/ereuse_devicehub/base_site.html | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
index e8fc6b49..c5aa24ed 100644
--- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
+++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
@@ -12,6 +12,21 @@
+
From 07f947b1ad3acfb458be117efaebf2882269dba2 Mon Sep 17 00:00:00 2001
From: Cayo Puigdefabregas
Date: Mon, 28 Nov 2022 17:00:30 +0100
Subject: [PATCH 32/49] fix search
---
.../templates/ereuse_devicehub/base_site.html | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
index c5aa24ed..f3865433 100644
--- a/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
+++ b/ereuse_devicehub/templates/ereuse_devicehub/base_site.html
@@ -8,10 +8,17 @@
-
+
+
+