diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index b86dca83..9cc85d30 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -50,11 +50,15 @@ from ereuse_devicehub.resources.device.models import ( Keyboard, Laptop, MemoryCardReader, + Monitor, Mouse, + Other, Placeholder, + Projector, Server, Smartphone, Tablet, + TelevisionSet, ) from ereuse_devicehub.resources.documents.models import DataWipeDocument from ereuse_devicehub.resources.enums import Severity @@ -81,7 +85,6 @@ DEVICES = { ], "Mobile, tablet & smartphone": [ "All Mobile", - "Mobile", "Tablet", "Smartphone", "Cellphone", @@ -91,6 +94,14 @@ DEVICES = { "HardDrive", "SolidStageDrive", ], + "Accessories": [ + "All Accessories", + "Mouse", + "MemoryCardReader", + "SAI", + "Keyboard", + ], + "Other Devices": ["Other"], } COMPUTERS = ['Desktop', 'Laptop', 'Server', 'Computer'] @@ -98,6 +109,8 @@ COMPUTERS = ['Desktop', 'Laptop', 'Server', 'Computer'] MONITORS = ["ComputerMonitor", "Monitor", "TelevisionSet", "Projector"] MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"] STORAGE = ["HardDrive", "SolidStateDrive"] +ACCESSORIES = ["Mouse", "MemoryCardReader", "SAI", "Keyboard"] +OTHERS = ["Other"] class AdvancedSearchForm(FlaskForm): @@ -170,7 +183,7 @@ class FilterForm(FlaskForm): # Generic Filters if "All Devices" == self.device_type: - filter_type = COMPUTERS + MONITORS + MOBILE + filter_type = COMPUTERS + MONITORS + MOBILE + OTHERS elif "All Computers" == self.device_type: filter_type = COMPUTERS @@ -184,6 +197,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,10 +387,14 @@ class NewDeviceForm(FlaskForm): "Tablet": Tablet, "Cellphone": Cellphone, "ComputerMonitor": ComputerMonitor, + "Monitor": Monitor, + "TelevisionSet": TelevisionSet, + "Projector": Projector, "Mouse": Mouse, "Keyboard": Keyboard, "SAI": SAI, "MemoryCardReader": MemoryCardReader, + "Other": Other, } def reset_from_obj(self): diff --git a/ereuse_devicehub/migrations/versions/410aadae7652_device_other.py b/ereuse_devicehub/migrations/versions/410aadae7652_device_other.py new file mode 100644 index 00000000..1d22d1dd --- /dev/null +++ b/ereuse_devicehub/migrations/versions/410aadae7652_device_other.py @@ -0,0 +1,39 @@ +"""device other + +Revision ID: 410aadae7652 +Revises: d65745749e34 +Create Date: 2022-11-29 12:00:40.272121 + +""" +import sqlalchemy as sa +from alembic import context, op + +# revision identifiers, used by Alembic. +revision = '410aadae7652' +down_revision = 'd65745749e34' +branch_labels = None +depends_on = None + + +def get_inv(): + INV = context.get_x_argument(as_dictionary=True).get('inventory') + if not INV: + raise ValueError("Inventory value is not specified") + return INV + + +def upgrade(): + op.create_table( + 'other', + sa.Column('id', sa.BigInteger(), nullable=False), + sa.ForeignKeyConstraint( + ['id'], + [f'{get_inv()}.device.id'], + ), + sa.PrimaryKeyConstraint('id'), + schema=f'{get_inv()}', + ) + + +def downgrade(): + op.drop_table('other', schema=f'{get_inv()}') diff --git a/ereuse_devicehub/resources/device/definitions.py b/ereuse_devicehub/resources/device/definitions.py index cdc99c05..d5678135 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): @@ -389,3 +695,35 @@ class ManufacturerDef(Resource): """Loads the manufacturers to the database.""" if exclude_schema != 'common': Manufacturer.add_all_to_session(db.session) + + +class OtherDef(DeviceDef): + VIEW = None + SCHEMA = schemas.Computer + SCHEMA = schemas.Other + + 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, + ) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 35e4d559..6fa60182 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -1637,3 +1637,11 @@ def create_code_tag(mapper, connection, device): # from flask_sqlalchemy import event # event.listen(Device, 'after_insert', create_code_tag, propagate=True) + + +class Other(Device): + """ + Used for put in there all devices than not have actualy a class + """ + + id = Column(BigInteger, ForeignKey(Device.id), primary_key=True) diff --git a/ereuse_devicehub/resources/device/schemas.py b/ereuse_devicehub/resources/device/schemas.py index 890dd287..8f92ffa7 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__ @@ -577,3 +581,7 @@ class Bike(Recreation): class Racket(Recreation): pass + + +class Other(Device): + pass diff --git a/ereuse_devicehub/templates/inventory/device_create.html b/ereuse_devicehub/templates/inventory/device_create.html index 6acf564f..8ad8634a 100644 --- a/ereuse_devicehub/templates/inventory/device_create.html +++ b/ereuse_devicehub/templates/inventory/device_create.html @@ -46,7 +46,13 @@ + {% if form.type.data == 'ComputerMonitor' %} selected="selected"{% endif %}>Computer Monitor + + + + + + Type of devices {% if form.type.errors %} diff --git a/tests/test_basic.py b/tests/test_basic.py index 68c7d696..7322e77b 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -117,4 +117,4 @@ def test_api_docs(client: Client): 'scheme': 'basic', 'name': 'Authorization', } - assert len(docs['definitions']) == 132 + assert len(docs['definitions']) == 134